Pentesting for startups

Preview:

Citation preview

Pentesting for startups

By Levi Gross

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

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.

The cost of ignorance

• Dropbox• Gawker• Sony

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

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

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

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

Information Disclosure

Your Parts are showing

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…

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 **optionsFile "/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 **optionsFile "/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 (\r\n)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)

Pasting code into images

But wait there’s more

remote: Push worked, but post-receive failed: Connection reset by peerremote: /data/github/current/vendor/gems/ruby/1.8/gems/redis-2.2.0/lib/redis/client.rb:234:in `ensure_connected'remote: /data/github/current/vendor/gems/ruby/1.8/gems/redis-2.2.0/lib/redis/client.rb:114:in `process'remote: /data/github/current/vendor/gems/ruby/1.8/gems/redis-2.2.0/lib/redis/client.rb:183:in `logging'remote: /data/github/current/vendor/gems/ruby/1.8/gems/redis-2.2.0/lib/redis/client.rb:113:in `process'remote: /data/github/current/vendor/gems/ruby/1.8/gems/redis-2.2.0/lib/redis/client.rb:38:in `call'remote: /data/github/current/vendor/gems/ruby/1.8/gems/redis-2.2.0/lib/redis.rb:428:in `sadd'remote: /usr/lib/ruby/1.8/monitor.rb:242:in `synchronize'remote: /data/github/current/vendor/gems/ruby/1.8/gems/redis-2.2.0/lib/redis.rb:427:in `sadd'remote: /data/github/current/vendor/gems/ruby/1.8/gems/redis-namespace-0.8.0/lib/redis/namespace.rb:188:in `send'remote: /data/github/current/vendor/gems/ruby/1.8/gems/redis-namespace-0.8.0/lib/redis/namespace.rb:188:in `method_missing'remote: /data/github/current/vendor/gems/ruby/1.8/gems/resque-1.10.0/lib/resque.rb:184:in `watch_queue'remote: /data/github/current/vendor/gems/ruby/1.8/gems/resque-1.10.0/lib/resque.rb:129:in `push'remote: /data/github/current/vendor/gems/ruby/1.8/gems/resque-1.10.0/lib/resque/job.rb:51:in `create'remote: /data/github/current/lib/rock_queue.rb:58:in `enqueue'remote: /data/github/current/lib/rock_queue.rb:28:in `push'remote: hooks/post-receive:37

Not just code hosting sites

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

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

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

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

Time to kick down the door

Session Hijacking• TCP sniffing– Firesheep

• ARP Poisoning

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…

Session Hijacking in Django and Rails

• Once you have the cookie you have the user….

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…

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

XSS (Cross site scripting)

• Enables attackers to inject client-side script (html/JS) into web pages viewed by other users.

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.• Tags that don’t sanitize• Concatenation will remove any escaping• Sanitizing doesn’t always work. • AJAX still isn’t escaped

Attack Scenarios

1. Steal user info2. Change User settings3. Steal an admin cookie and add yourself as an

admin user.4. Execute code as an admin to add yourself as

an admin user

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

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.

Attack Scenario

• Lure the user to your site.• Add yourself as an admin user• The skies the limit

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

CSRFCross site request forgery

CSRF in Django• Built in CSRF protection• Keep up to date• In the form and the HTTP headers/Cookie

• It’s annoying so people turn it off• Only recently do they check AJAX request• Use subdomains

Attacks

CSRF in Rails

• Like Django recently changed• REST makes things harder…• Stored in the cookie

Attacks

• A XSS exploit renders this protection useless.• Subdomains

Attack Scenario

• Attacker uses XSS to inject code within admin site to exploit internal site CSRF issue

• <img src=\\<evil IP> gives me your NTLM

Cookie Poisoning

• Cookies are encoded– Base64

• People never see them…. • Lets store important information• Attacker can– Submit a malformed cookie– Steal another users cookie

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

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

Attack Scenario

• Pass malformed cookie back to the server– DDOS– Remote code execution– Impersonation

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

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:\\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

• 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

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

Attack Scenarios

• Remote code execution via the cache/session layer

• Authentication bypass by GET/POST switch.

Logic Flaws

• Unauthenticated views• Information leaks• Weak or invalid permissions• eval• Passing unsanitary input around

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

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 regular expression to “escape” values– Even with parameterized queries – *.connection.quote

• Very easy to execute raw SQL– where– order

Attack Scenarios

• Information theft• Hosting malware or exploits• Full site exploitation

Counter Measures

• Only use permissions that you need• Validate and sanitize all input (twice cannot

hurt)• Encrypt sensitive data

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

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

What are timing attacks

• Side channel attacks• Linear operations• The dangerous binary comparison..

Countermeasures

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

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

Countermeasures

• Dual factor authentication• Rate limit authentication logic• Monitoring• Tough permission checks• Whitelists/blacklists• Certificate authentication to verify the

provider

Denial of Service in Django & Rails

• Remember the GIL• No rate limiting• Switching HTTP methods• Python– Virtual methods calls

• Ruby– Slow method dispatch

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.

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/

Questions

Recommended