Jenny Duckett and Alex Muller
Government Digital Service
@jenny_duckett, @alexmuller
A really broad overview of web security
(so alpha it doesn’t even have a banner)
This is our first attempt at running a security workshop, so there’ll be lots which could be better - please ask lots of questions and give us feedback at any time
There’ll be a mini-retro at the end of the day to focus on this
Help us make the next one better!
Lots of us are new to GDS and we don’t all know each other yet...
Mid-morning and mid-afternoon breaks, and lunch obvs
Mini-retro 20-30 mins at the end of the day
We’re aiming to spend lots of time on practical exercises, so if we’re talking too much then please tell us :)
Fix the vulnerabilities to make the tests pass
We’ll be using it for most of the practical sessions today, and there’s lots more to explore in it
We’ve forked it and we’re using our virtualbox branch
What do we mean by web security?
What are the risks and possible consequences?
Discuss with the people on your table for a couple of minutes, then all together
We aren’t security experts
Web security is a huge topic
...but understanding some general principles really helps
These are ours:
Don’t trust user input, ever
Browsers are a special environment
Your frameworks and tools can help, but understand how to use them properly and their limitations
Don’t do it yourself - use standard well-understood things instead
As we said, we aren’t experts, but we find these helpful for thinking about security
These are really high level
We’ll talk about these in more detail
There is one thing you need to know before we begin:
Computer Misuse Act 1990
Unauthorised access to computer material is punishable by 12 months imprisonment
Putting some code on the server and getting it to run
The code can come from any user input
It can damage anything running on the server
SQL injection
'SELECT * FROM data WHERE foo=' + '1; DROP TABLE users' + ';'
Remote code execution
ImageTragick (CVE-2016-3714)
Practical stuff:
SQL injection in analytics in Railsgoat
ImageTragick
SQL injection with Railsgoat: analytics page, as admin - try to get a list of all the users: http://localhost:3000/admin/1/analytics?ip=FOO&field[*%20FROM%20users--]=true
Prevention: understand what Rails does against SQL injection and how to use it right, eg where with params or a string
Tools eg brakeman can help, but unless you’re running it regularly and seeing the output it doesn’t help…
http://edgeguides.rubyonrails.org/security.html#sql-injection
“We had thousands of hits in the first 15 minutes. We were at the top of hacker news, which a lot of people see. We were getting the word out on something tragickally simple to exploit. We'd do it again.”
imagetragick.com
Few people took any notice of the first announcement until they made the website - name and logo were a joke originally but they immediately made it much more distinctive
People need to know a vulnerability exists before they can patch it, and marketing helps that
Authenticating users
If you want to play along with the demo in a few minutes, download the password-related files from the raspberry pi
Don’t build it yourself
(but the alternatives aren’t perfect either)
Hash passwords before storing them in your database
MD5, SHA-512, bcrypt
Crack an MD5 password
Discuss difference between hashing and encryption?
Salting passwords? What are you trying to gain by doing this? (time)
Demo: use hashcat to crack some passwords
echo -n "taylorswift" | md5sum | cut -f1 -d" " > /tmp/hash.txt
tar xvzf rockyou.tar.gz
chmod +x hashcat-cli64.app
./hashcat-cli64.app /tmp/hash.txt rockyou.txt
Managing expiry of sessions is hard
There’s a lot of state to manage across many different actions that users can take - complex
When users report issues with authentication systems, take it seriously
Devise as an example of why you should keep dependencies up-to-date - most other things we’re talking about are possible via this vector
Check user input on every request
Every request is entirely independent. There’s no such thing as being “authenticated” with HTTP. That’s what cookies are.
Changing params
Hiding a button isn’t enough
Direct object references
Missing function-level access control
Specialist Publisher authorisation to publish manuals
Demo: authorisation to publish manuals in Specialist Publisher
Don’t trust user input - check every time!
Make sure your application is configured correctly in production
For example, Rails has a development mode that shows stack traces
Don’t show stack traces to people
Applications should be served over a secure connection
Cookies (this is why you need to do authentication properly)
People don’t pay attention (this is why phishing attacks work)
From the server’s point of view, the browser is the user
Lots of bad things can happen in a browser
Cross-site scripting (XSS)
It’s useful to think of this as JavaScript injection
XSS isn’t the clearest name for this to us
It covers getting any kind of unintended JS to run in someone else’s browser
Two types of XSS:
This happens when you take user input and render it without escaping it correctly
Don’t trust user input, remember :)
Publishing apps could be victims of stored XSS - we have to sanitize input to prevent it
Deploy old branch temporarily to integration
Get a bit of actually dangerous JS to use instead of just alert - send cookies to our logging app?
Cross-site request forgery (CSRF)
A user on another website is tricked into making a request against your website
The malicious request has access to your site’s cookies so it’s “authenticated”
Practical: be the victim of a CSRF attack in Railsgoat (and fix it)
Do HTTP right
img tags with GET
Same-origin policy
The browser won’t let a site make an HTTP request to another origin unless the site has cross-origin resource sharing (CORS) configured
Cookies:
HttpOnly
Secure
SameSite (draft RFC)
Practical: write some JavaScript to try and get the CSRF token from a Signon form
Then do the same thing with the GitHub API. See the difference?
Man-in-the-middle attacks
Somebody is intercepting your web traffic
HTTP strict transport security (HSTS)
HTTP public key pinning (HPKP)
Users can be tricked easily - phishing
Developers make mistakes
Privileged users or anyone with higher levels of access are more likely to be targeted
Chaining vulnerabilities
This makes any of these vulnerabilities much more dangerous (and interesting!)
A vulnerability which on its own would have only a small impact can let you escalate to exploit another one which wouldn’t have been possible on its own
Instead of trying to get a user’s already-authenticated session cookie, force them to use a session you already have access to and get them to authenticate it for you
<script>
document.cookie ="_session_id=16d5b78a2a03c8d9";
</script>
The “XSS” to fix the session doesn’t rely on cross-site requests - just setting the cookie for the current page, JS injection
The mitigation for this is to expire the user’s session when they login and logout and give them a new session, which the attacker doesn’t have access to - Devise does this for you
Also you can delete sessions from the database a short time after they were created - this gives the attacker less time to exploit the attack
What other examples can we come up with?
Timing attacks
Draft RFC on same-site cookies
Twitter credit card thing
Thanks!
Jenny Duckett and Alex Muller
@jenny_duckett, @alexmuller