Pentesting Django and Rails
By Levi Gross
Python• Dangerous models
– Pickle• Code execution
– urllib• No SSL verification built in• file:// is valid• Redirects allow any file to be read (this was fixed in 2.7.2)
– XSS in Basic HTTPServer• A wide open playground
– But syntax is holy• Easy to execute code on the host system
– eval• input
– Pickle• No authentication• Code Execution
• Unicode issues• C extensions
Django• Auth Framework
– Secure Session framework– Uses salted SHA1 hashes
• Can use MD5 and crypt but will auto upgrade– Basic global permission structure
• Cache backend uses pickle• Default use of Unicode • Default URLS• Exceptions don’t propagate back to the user
– If the system is NOT in debug mode• Automatic variable escape• Built in CSRF protection
– Unique hashes– In web forms, AJAX and the cookie
• Default Admin site• Insecure form wizard
– Fixed in 1.3• Compatible with Python 2.4 – 2.7
Ruby• $SAFE isn’t really safe
– Even layer 4 can be bypassed by exceptions• Patched but still insecure
• SSL verification is disabled by default– And encouraged as it slows down you application
• Global Variables• Language syntax isn’t holy• C Extensions• Eval• FileUtils
– remove_entry_secure• WEBrick issues• Buffer overflow in ARGF.inplace_mode=
Rails• Secure session framework
– Try not to store data in cookies• Remember base64 is not a method of encryption.• The database is your friend• No information should be put into cookies besides for the hash
– If you need to put information within the cookie• Signed cookies
• REST• Basic permissions• Default variable escape• Escaping SQL statements• CSRF Protection like Django• Use of site admin
– Relies on 3rd party gem (but what doesn’t in rails)
Django Information Disclosure• Using the default URLS
– Default paths for media– Admin URLs
• Putting DB fields in URLs• URLS == Views• Switching GET and POST• Popular Django apps don’t always adhere to secure princeables
– Dajax• Exceptions propagate back to the user
– Celery• Pickle
– Piston• Object Level permissions
– Sentry• Default URLS
• Raw template code in html comments
Rails Information Disclosure
• Using insecure gems• Letting exceptions propagate to a user• Raw template code in the page• View logic written in Javascript• Default URLS• Object ID’s in the URL
Countermeasures• Never let exceptions propagate to end user
• Don’t paste your raw tracebacks directly into any public online location.– Sanitize them
• Don’t rely on anything here for security
HTTP Sessions in Django & Rails• Django
– Each session is a unique hash value– Cookies can be read via javascript– Predictable cookie name ‘sessionid’– Uses the pickle model to serialize data– Defaults to an insecure cookie– Values are stored in the session backend– No default cookie domain– File backend allows for reading on /tmp folder– Immune to classic cookie poisoning
• Rails– Signed cookies– Default storage is to the cookie…
Session Hijacking in Django and Rails
• Once you have the cookie you have the user….
Cookie Poisoning in Django and Rails
• Django– Django defaults to it’s session backend which doesn’t do this.
• Rails – Rails allows you to shoot yourself in the foot.
Attack• Django
– People will still use request.COOKIES• Server setup can cause issues with session backend
• Rails– Any classic cookie poisoning attack– Storing info in cookies– Not signing cookies– Using cookies to manipulate view logic
Countermeasures• General
– Cycle sessions when user authenticates– Use a cryptographic nonce– Use Sticky Sessions
• Django– Make sure you use Djangos session Application
• Use a consistent session backend• Escape and Validate all data
– Make sure you set the following settings• HTTP_ONLY (Only in 1.3)
– Safari ignores this value
• SECURE• Change the cookie name• Serialize using JSON or YAML
• Rails– Sign cookies
• Never trust your user data
– Make the cookies secure and HTTP only– Use the DB/ KV store to store session data
• Send the user a hash
– Clear the sessions after login
XSS in Django
• Auto escapes ‘<>&” with their “safe alternatives”
Problems1. Any other Unicode will bypass this check2. If items are not properly quoted you can still
inject attributes into tags1. Other special characters aren’t escaped ( )
3. Designers1. Hate |safe and just use {% autoescape off %}
XSS in Rails• 2.x
– Variables aren’t automatically escaped• Tags are stripped using the strip_tags method
• 3.x– Automatic variable escape
• Unless you use raw– or some other function that doesn’t return safe output
Attack• White lists are useless
– selselectect <scri<script>pt>• Sanitizing the HTML special characters has the same issue Django has.• Inconsistent sanitization of data
– link_to , textile, tag, content_tag– When faced with ambiguous input (concatenation of safe and unsafe data) will default to unsafe
• Sanitizing doesn’t always work. • AJAX still isn’t escaped• RJS isn’t automatically escaped
Countermeasures• General
– Force the browser to use UTF-8– Never trust user input– Don’t use user input for HTML tag attributes– Take a page out of the python zen
• In the face of ambiguity, refuse the temptation to guess.
• Django– Use the OWASP ESAPI– If you need styling
• Use Sanitizers– lxml– bleach
• Use markdown• Use whitelists not blacklists
• Rails– Escape all user input– before_filter :only => […] instead of :except => […]– Explicitly sanitize data
• sanitize()• <=%sanitize {template tag} %>
CSRF in Django• Built in CSRF protection• Recently updated to include AJAX• In the form and the HTTP headers/Cookie
• It’s annoying so people turn it off– document.write() breaks it
• Only recently do they check AJAX request• Doesn’t work for subdomains
Attacks
CSRF in Rails
• Recently updated to include AJAX• REST makes things harder…• Stored in the cookie
Attacks
• People don’t think they need it• A XSS exploit renders this protection useless.• Same subdomain issue
HTTP Parameter Poisoning
• Directory Traversal / Local file inclusion– http://someserver/somepage/?val=g&file=../../../../../../etc/passwd – http://somesite/file_download/file=../config/database.yml
• HTTP Response Splitting– Injecting /r/n into fields splitting the response headers (XXS like
affect) • Remote file inclusion
– /myview?someparam=C:\\ftp\\upload\\exploit• Invalid method
– Using a POST in place of a GET and vis a vis• Referrer poisoning
– http://someserver/somepage/?val=g&referrer=<myurl>
HTTP Parameter Poisoning in Django• Django is immune to
– Directory Traversal– HTTP Response Splitting– Remote file inclusion– Referrer Poisoning
• Forms cleaned_data allows for value escaping
Attacks• Switching GET and POST are not enforced• Not all HTTP Parameters are autoescaped by
default– Cache and sessions use pickle
HTTP Parameter Poisoning in Rails
• Blind use of HTTP parameters– Invalid file name checking• arbitrary file upload and execution
– XSS• Remember use AJAX
– Privilege escalation– SQL Injection– Blind Redirection– File includes
Exploiting Logic Flaws in Django &Rails
• Django– @login_required– Permissions are global– Objects are serialized– Arbitrary input may have some exciting outcomes
• Logic manipulation• debug=True
– Remember in python nothing is sacred• Rails
– explicit authentication– explicit permission checking– Permissions not always object based– Ruby syntax is extendable
SQL Injection
• Cookies• HTTP Parameters• Logic Flaws• XSS
SQL Injection in Django
• Parameterized queries• LIKE queries are escaped
Attacks
• WHERE is still injectable• People use cursor.raw() all the time• Character escaping is always being broken
– More python unicode fun….
SQL Injection in Rails
• Uses regex to “escape” values– *.connection.quote
• Very easy to execute raw SQL– where– order
Counter Measures
• Rails– Parameterized queries
• Be wary of what your users give you• Validate and sanitize all input• Only use permissions that you need• Encrypt sensitive data
Passwords in Django
• Brute force friendly• Salted SHA1 hashes– The core developers don’t want to upgrade anytime
soon.• Incompatible with Python 2.4
• Timing attacks– Mitigation added in 1.3 but some implementations
flawed due to string interning• Compatible with older insecure hashes• The Achilles heel of any system
Passwords in Rails
• No authentication– Very popular
• REST Authentication– Blind use of params[:]
• Clear text passwords in the logs• Brute force friendly• Salted hashes– Good but not perfect
• Timing attacks
Authentication• OAUTH
– Everyone forgets to use SSL– Even if you do your still opening yourself up to a Man In The Middle Attack
• Permissions– Django
• Not object based
Best Worst
Countermeasures
• Dual factor authentication• Rate limit authentication logic• Monitoring• Tough object level permissions• Whitelists/blacklists• Certificate authentication to verify the
provider
Denial of Service in Django & Rails
• Remember the GIL (Global Interpreter Lock)• No rate limiting• Switching HTTP methods• Python– Virtual methods calls
• Ruby– Slow method dispatch
DDOS Mitigation
• Rate Limit– By IP– By View/Process
• Use Background processing– Django
• Celery
– Rails• Gearman
• Allow for graceful failure of website services– Take a page out of web application scaling
Recommended Resources
• Django– http://www.djangobook.com/en/2.0/chapter20/– http://readthedocs.org/docs/playdoh/en/latest/
• Rails– http://www.rorsecurity.info/– http://groups.google.com/group/rubyonrails-
security
Questions
Top Related