Exploit Mitigation Make it less feasible to exploit bugs (i.e. turn “security bugs” back into “ordinary bugs”): • Stack Smashing Protection (SSP) • Data Execution Prevention (DEP / NX) • Address Space Layout Randomization (ASLR)
Encapsulate Hazardous Code We don’t write web apps in C/C++ anymore. ! Most of our high-level languages and web servers are still built on C, but these are carefully-curated components written by skilled developers with lots of review (we hope!).
To Review Hypothesis: Buffer overflows fell off the OWASP Top 10 thanks to • Concerted efforts to define and (automatically!) detect anti- patterns • Better tooling to simplify code / limit human error • Catch-all exploit mitigation technologies • The simple fact that we don’t build web apps in C/C++ anymore!
To Review Hypothesis: Buffer overflows fell off the OWASP Top 10 thanks to: • Concerted efforts to define and (automatically!) detect anti- patterns • Better tooling to simplify code / limit human error • Catch-all exploit mitigation technologies • The simple fact that we don’t build web apps in C/C++ anymore! ! How can we apply these ideas to other classes of bugs?
XSRF Review 1. Alice logs into https://mybank.com, and gets back a session cookie:
200 OK Set-Cookie: session-id=123-456789; path=/; domain=.mybank.com; Secure; HttpOnly; 2. Alice is tricked into opening https://evilsite.com, whose JavaScript code sends a POST to mybank.com:
POST /transfer_funds Cookie: session-id=123-456789 ... destination=evil_account_number&amount=100000¤cy=USD
XSRF Tokens Elegant solution: • Requires no new server-side state • Can be added to most existing web applications with minor modifications • “Secure by default”
Threats • Annoy users (i.e. alert(‘hi’)) • Steal any data in the DOM • (Including XSRF tokens!) • Phish users’ credentials, even if it wasn’t a login page! XSS - Review
Context-Aware Auto-Escaping Basic idea: as you’re generating template output, feed it back through an HTML parser. When you hit a template directive, figure out what context you’re in, and call the appropriate escaping function!
Mitigation: Content-Security-Policy (CSP) HTTP Header that will tell the browser from what sources it’s allowed to load (and in the case of scripts, execute) content. •Content-Security-Policy: default-src ‘self' - load scripts/ images/etc. only from the same domain (and do not run inline scripts or process inline CSS!) •Content-Security-Policy: default-src 'self'; img-src * - same, except allow loading images from any host For more, see: http://cspisawesome.com
Mitigation: Content-Security-Policy (CSP) • Turns security vulnerabilities back into “ordinary bugs”… • (… if your users are using supported browsers!) • Eliminating inline scripts usually requires some restructuring • but separating code, data, and presentation is a good pattern anyway, right? :)
SQL Injection - Review class LoginHandler(tornado.web.RequestHandler): def post(self): user = self.get_argument('username') password = self.get_argument('password') ! pwhash = hashlib.sha1(password).hexdigest(); row = self.application.db.get( 'SELECT uid FROM users WHERE uname=\'%s\' AND password=\'%s\'' % (user, pwhash)) if row: self.set_secure_cookie('user', str(row.uid)) self.redirect('/') ! ! (By the way, DO NOT store your passwords like this!)
Fun things to submit for ‘user’: • akgood' OR '1' = '1 • akgood'; DROP TABLE users; SELECT … • or just point a tool like sqlmap (http://sqlmap.org/) at it! SQL Injection - Review
Parameterized Queries class LoginHandler(tornado.web.RequestHandler): def post(self): user = self.get_argument('username') password = self.get_argument('password') ! pwhash = hashlib.sha1(password).hexdigest(); row = self.application.db.get( 'SELECT uid FROM users WHERE uname=%s AND password=%s', user, pwhash) if row: self.set_secure_cookie('user', str(row.uid)) self.redirect('/') ! ! Can you see the difference?!
Static Analysis If you really must write raw SQL: • basic: a check to ensure that developers never use the string interpolation operator (‘%’) in a database function call • better: dataflow analysis to trace the construction of a query string and ensure no untrusted inputs were used (a.k.a. ‘taint analysis’)
Static Analysis: Homegrown Hacks Example: make sure that we only ever use Python’s “SystemRandom” class to generate random values
v1: basically, grep for instances of: • ‘random\.\w+’ (other than ‘random.SystemRandom) • ‘from random import .*’ (other than ‘from random import SystemRandom) v2: use the python AST
Checking SystemRandom with the AST class RandomVisitor(ast.NodeVisitor): def visit_Attribute(self, node): if (isinstance(node.value, ast.Name) and node.value.id == 'random' and node.attr != 'SystemRandom'): raise BadRandomGenerator(node.lineno) ! def visit_ImportFrom(self, node): if (node.module == 'random' and any(alias.name != 'SystemRandom' for alias in node.names)): raise BadRandomGenerator(node.lineno) ! with open(some_python_module, 'r') as fp: m = ast.parse(fp.read()) RandomVisitor().visit(m)
• Use frameworks and tools that prevent entire classes of bugs by default - either by intentionally mitigating vulnerabilities or simply by encapsulating dangerous code so you don’t have to deal with it. • If you see an anti-pattern, write a script to enforce it! • Can be quite basic, especially if you pair it with peer code reviews and consistent coding norms • Don’t forget about the rest of the SDL Conclusions