2. Shameless self promotion I work at AxialMarket Researching computer security for 11 years. Pentesting for 8 years Python is my language of choice Contact info Blog: http://www.levigross.com levi@levigross.com @levigross
3. Disclaimer This talk is strictly for educational purposes. I am not responsible for any outcome of this talk. All images used in the subsequent slides are for informational purposes only and are owned by their respective copyright holders.
5. Python Dangerous models Pickle Code execution urllib ssl certs 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 Unicode issues C extensions
6. Django Auth Framework Session framework Uses unique hashes Uses salted 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 Automatic variable escape Built in CSRF protection Unique hashes In web forms as well as in the cookie
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 Global Variables Language syntax isn’t holy Eval FileUtils remove_entry_secure WEBrick issues Buffer overflow in ARGF.inplace_mode= C extensions
8. 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 Signed cookies REST Basic permissions Default variable escape Escaping SQL statements
10. General Information Disclosure Job sites Internal External Exceptions propagating to the end user Showing everyone what you are running Post mortem blog posts Google Pastebins Complaints Stack Exchange Github Mailing lists Anomalies Forgotten password? Just ask…
11. And so the fun begins… File "/opt/python/domains/bitbucket.org/2011-01-05/bitbucket/../bitbucket/apps/bb/clogging.py", line 60, in wrap return f(request, *args, **kwargs) File "/opt/python/domains/bitbucket.org/2011-01-05/bitbucket/../bitbucket/apps/bb/decorators.py", line 111, in wrap return f(req, *a, **kwa) File "/opt/python/domains/bitbucket.org/2011-01-05/bitbucket/../bitbucket/apps/bb/views.py", line 211, in frontpage newsfeed = load_from_store(request.user) File "/opt/python/domains/bitbucket.org/2011-01-05/bitbucket/../bitbucket/apps/bb/newsfeed.py", line 39, in load_from_store if not r.exists(key): File "/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/redis/client.py", line 529, in exists return self.execute_command('EXISTS', name) File "/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/redis/client.py", line 330, in execute_command **options File "/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/redis/client.py", line 309, in _execute_command self.connection.send(command, self) File "/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/redis/client.py", line 82, in send self.connect(redis_instance) File "/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/redis/client.py", line 67, in connect redis_instance._setup_connection() File "/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/redis/client.py", line 424, in _setup_connection self.execute_command('SELECT', self.connection.db) File "/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/redis/client.py", line 330, in execute_command **options File "/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/redis/client.py", line 312, in _execute_command return self.parse_response(command_name, **options) File "/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/redis/client.py", line 390, in parse_response response = self._parse_response(command_name, catch_errors) File "/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/redis/client.py", line 335, in _parse_response response = conn.read()[:-2] # strip last two characters () File "/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/redis/client.py", line 99, in read return self._fp.readline() File "/opt/python/2.7/lib/python2.7/socket.py", line 445, in readline data = self._sock.recv(self._rbufsize)
15. Django Information Disclosure Using the default URLS Default paths for media Admin Urls Putting DB fields in urls URLS == Views Switching GET and POST Dajax Celery Piston Template code in the html
16. Rails Information Disclosure Using insecure gems Don’t let exceptions propagate to a user Raw template code in the page View logic written in Javascript Default URLS Object ID’s in the URL
17. Countermeasures Never let exceptions propagate to end user Don’t paste your raw tracebacks directly into any public online location. Sanitize them Every bit of information that is released can be used against you. Don’t rely on anything here for security
18. Build a profile of your target Blackbox testing Look for patterns Corners cut Style of code (html) Learn about the application Learn the problems/issues programmers face when dealing with these systems Gauge difficulty
21. 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 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…
22. Session Hijacking in Django and Rails Once you have the cookie you have the user….
23. Attack Scenarios TCP Sniffing WiFi ARP Poisoning Thank you SSL for being useless Stealing cookies via a 3rd party site Who needs passwords when you have sessions…
24. Countermeasures General Cycle sessions when user authenticates Use a cryptographic nonce Django Make sure you set the following settings HTTP_ONLY (Only in 1.3) SECURE Change the cookie name Serialize using JSON or YAML Rails Sign cookies Make the cookies secure and HTTP only Use the DB to store session data Clear the sessions after login
25. XSS (Cross site scripting) Enables attackers to inject client-side script (html/JS) into web pages viewed by other users.
26. XSS in Django Auto escapes ‘<>&” with their “safe alternatives” Problems Any other unicode will bypass this check If items are not properly quoted you can still inject attributes into tags Other special characters aren’t escaped ( ) Designers Hate |safe and just use {% autoescape off %}
27. 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. Tags that don’t sanitize Concatenation will remove any escaping Sanitizing doesn’t always work. AJAX still isn’t escaped
28. Attack Scenarios Steal user info Change User settings Steal an admin cookie and add yourself as an admin user. Execute code as an admin to add yourself as an admin user
29. 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 => […] Use sanitizers
30. Clickjacking Overlaying the current website with an IFRAME. Tricking the user into clicking on certain elements User unknowingly performs action on the website he is logged into.
31. Attack Scenario Lure the user to your site. Add yourself as an admin user The skies the limit
32. Frame busting X-FRAME-OPTIONS DENY Disable IFRAME javascript Restricted => IE Sandbox => Chrome designMode in Firefox and Safari Use javascript to navigate back to prevent IFRAMES from opening your site. This is always being exploited so keep up with the latest exploits. Read More: https://www.owasp.org/index.php/Clickjacking
34. CSRF in Django Built in CSRF protection Keep up to date In the form and the HTTP headers/Cookie Attacks It’s annoying so people turn it off Only recently do they check AJAX request Use subdomains
35. CSRF in Rails Like Django recently changed REST makes things harder… Stored in the cookie Attacks A XSS exploit renders this protection useless. Subdomains
36. Attack Scenario Attacker uses XSS to inject code within admin site to exploit internal site CSRF issue <imgsrc=<evil IP> gives me your NTLM
37. Cookie Poisoning Cookies are encoded Base64 People never see them…. Lets store important information Attacker can Submit a malformed cookie Steal another users cookie
38. Cookie Poisoning in Django Django defaults to it’s session backend which doesn’t do this. Attack People will still use request.COOKIES Issues with session backend
39. Cookie Poisoning in Rails Rails allows you to shoot yourself in the foot. Attack Storing info in cookies Not signing cookies Using cookies to manipulate view logic
40. Attack Scenario Pass malformed cookie back to the server DDOS Remote code execution Impersonation
41. Counter Measures Use sticky sessions Django Use session app Use a consistent session backend Escape and validate data Rails Sign your cookies Only use hashes Never trust the user
42. HTTP Parameter Poisoning Injecting invalid values into HTTP params Directory Traversal http://someserver/somepage/?val=g&file=../../../../../../etc/passwd HTTP Response Splitting Injecting /r/n into fields splitting the response headers Remote file inclusion /myview?someparam=C:ftpuploadexploit Invalid method Using a POST in place of a GET and vis a vis Referrer poisoning http://someserver/somepage/?val=g&referrer=<myurl>
43. HTTP Parameter Poisoning in Django Django is immune to Directory Traversal HTTP Response Splitting Remote file inclusion Forms cleaned_data allows for value escaping Attacks Switching GET and Post are not enforced Not all HTTP Params are autoescaped by default Cache and sessions use pickle
44. 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
45. Attack Scenarios Remote code execution via the cache/session layer Authentication bypass by GET/POST switch.
46. Logic Flaws Unauthenticated views Information leaks Weak or invalid permissions eval Passing unsanitary input around
47. 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 Ruby syntax is extendable
49. 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….
50. SQL Injection in Rails Uses regular expression to “escape” values Even with parameterized queries *.connection.quote Very easy to execute raw SQL where order
52. Counter Measures Only use permissions that you need Validate and sanitize all input (twice cannot hurt) Encrypt sensitive data
53. Passwords in Django Brute force friendly Salted hashes Good but not perfect Timing attacks Mitigation added in 1.3 but flawed due to pythons string intern Compatible with older insecure hashes The Achilles heel of any system
54. 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
55. What are timing attacks Side channel attacks Linear operations The dangerous binary comparison..
57. Authentication OAUTH Everyone forgets to use SSL Even if you do your still opening yourself up to a Man In The Middle Attack Best Worst
58. Attack Scenarios Crack password SQL injection Brute Force Phishing DDOS No SSL on OAuth Even with SSL still vulnerable to a Man In the Middle attack Have fun
59. Countermeasures Dual factor authentication Rate limit authentication logic Monitoring Tough permission checks Whitelists/blacklists Certificate authentication to verify the provider
60. Denial of Service in Django & Rails Remember the GIL No rate limiting Switching HTTP methods Python Virtual methods calls Ruby Slow method dispatch
61. Great another crazy guy screaming about the end of the world. Never rely on one thing alone. Ask yourself at every point of your application. “If someone penetrated until here what is stopping him?” Onion? Code defensively Remember that unknown variables will enter the equation and you have to account for them. Monitor everything Show you care Create a security page Make sure to include a PGP key Create an incident response document Give it a trial run Remember a good programmer looks both ways before crossing a one way street.
62. Recommended Reading General https://www.owasp.org https://www.owasp.org/index.php/Top_10_2010-Main Writing Secure Code (by Microsoft Press) Hacking Exposed web applications The Web Application Hacker's Handbook http://www.reddit.com/r/netsec Django http://www.djangobook.com/en/2.0/chapter20/ Rails http://www.rorsecurity.info/ http://groups.google.com/group/rubyonrails-security Tools http://www.metasploit.com/download/ http://w3af.sourceforge.net/