Created by Piotr Podsiadly
Lemme click that "I understand" button
for making sure corporation is compliant with the law.
comes with the cost.
Web application security is difficult to master.
Let's dive into CSRF!
The basics at first
from OWASP wiki page.
<img src="http://bank.com/transfer.do?acct=HACKER&amount=100000">
triggers
GET /transfer.do?acct=HACKER&amount=100000 HTTP/1.1
Host: bank.com
<body onload="document.forms[0].submit()">
<form action="http://bank.com/transfer.do" method="POST">
</form>
triggers
POST /transfer.do HTTP/1.1
Host: bank.com
Content-Type: application/x-www-form-urlencoded
acct=HACKER&amount=100000
Attack that forces end user to execute unwanted actions on a web app in which they're currently authenticated.
Hacker sends "Password reset problem" email to helpdesk.
It reaches logged in Alice. Alice clicks the link in email.
<body onload="document.forms[0].submit()">
<form action="/personal-information" method="POST">
Hacker recovers Alice account password to bob@hacker.org and gains admin privileges
Session cookie headers are automatically passed with every page request matching associated domain
GET / HTTP/1.1
Host: google.com
Cookie: SID=JWAAAsh-84ShNVVG...
Synchronizer Token Pattern - random "challenge" tokens associated with user's session
<form action="/personal-information" method="POST">
Same-origin policy prevents the hacker from reading DOM of other domain
Hi, i lost my access to Host-It.com.
Can you log in and click this link to see if you have same issue or is it just my account?
thanks, Peter
Nowdays mitigated by modern web browsers pаypal.com
you can ensure user is already logged in by embedding your HTML on vulnerable website
<img src="/action?param=value">
In that case no user action is required
CSRF is good enough by itself, HTML injection just helps to scale it
With Synchronizer Token Pattern you can still be vulnerable
or even hurt yourself.
Don't put the token as GET request param value.
If you do, it can be read from:
or retrieved through social engineering by asking the user to copy and paste the link.
If you have CORS enabled
Access-Control-Allow-Origin: *
you allow any domain to read your site HTML/DOM. This includes reading CSRF-Token.
Persistent XSS is much more dangerous making CSRF almost irrevelant.
Hacker could read CSRF-Tokens but he can also read cookies values and impersonate the user.
CSRF would still be viable followup to XSS if cookies are marked with HttpOnly flag and there is no way to prevent it.
A library implementing synchronizer token pattern to mitigate the risk of CSRF attacks
A JavaEE Filter + exposes ways to integrate CSRF-Tokens into HTML.
...
<filter-class>org.owasp.csrfguard.CsrfGuardFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CSRFGuard</filter-name>
<url-pattern>/*</url-pattern>
Sources on github
Can be easily automated:
Those requests that succeed are CSRF vulnerable
For manual test you can check existance of CSRF-Token in each request and if its there delete/change it. Also read OWASP testing guide v4
We covered the basics, let's dive in to advanced topics at last!
What if application uses XMLHttpRequest
$.ajax({
type: "POST",
url: "/change-my-email",
data: { email: "john@domain.com" }
}).done(function( msg ) {
console.log( "Data Saved: " + msg );
});
instead of simple form
<form action="/change-my-email" method="POST">
</form>
jQuery
POST /change-my-email HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
email=john%40domain.com
simple form
POST /change-my-email HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
email=john%40domain.com
X- deprecated as per RFC 6648
Using jQuery does not protect from CSRF, someone can always make equivalent self-submitting form
Can you make it from HTML?
support for PUT and DELETE methods in forms - Nothing guarantees that it wont be an option in the future
Rails example - support for PUT in "legacy" browsers
<form action="/news/1" method="post">
</form>
With HTML form
<form enctype="text/plain" action="/doit" method="post">
<input type="hidden" name='<?xml version'
value='"1.0"?><mySoapBody>isHere</mySoapBody>'>
<input type="submit" value="test"/>
</form>
browser create following request
POST /doit HTTP/1.1
Host: www.example.com
Content-Type: text/plain
<?xml version="1.0"?><mySoapBody>isHere</mySoapBody>
With HTML form
<form enctype="text/plain" action="/doit" method="post">
<input type="hidden" name='{"ignoreMe":"' value='", "email":"john@domain.com"}'>
<input type="submit" value="test"/>
</form>
browser create following request
POST /doit HTTP/1.1
Host: www.example.com
Content-Type: text/plain
{"ignoreMe":"=", "email":"john@domain.com"}
It does not matter.
You should prottect from CSRF regardless of web technology stack.
CSRF definition key words: "execute actions" by "authenticated" user
Do we protect read only corporate account balance?
Some read only pages may take more than few seconds to fetch and process the data
<img src="http://stock-data-online.com/?show-all"/>
<h1>Refresh 10 times</h1>
<h3>and we will pay $1 to <a href="http://www.unicef.org/">UNICEF</a></h3>
Valued customers may have higher priority or a simple IP base throtling ensures one user cannot exhaust resources.
All these can be bypassed by CSRF
not-so-popular-internet-speed-test.com/measure fetches 100MB
<html>
<head>
<meta http-equiv="refresh" content="30">
</head>
<body>
<iframe src="http://popular-internet-speed-test.com/measure" class="hidden"/>
<h1>Please wait while we load the movie</h1>
Buffering ... <img src="spinning-circle.gif"/>
</body>
</html>
1Gbps = 40 concurrent users with average home network
CSRF protection would prevent such attack
Protect everything antipatern
hackable URLs
http://my-app.com/documents
http://my-app.com/documents/presentations
http://my-app.com/documents/presentations/2015
http://my-app.com/documents/presentations/2015/how-to-protect-from-csrf.html
and web resource principles
CSRF - "execute action" by "authenticated" user
<img src="http://my-app.com/logout"/>
https://accounts.google.com/Logout?...secTok=....
Prompt pattern
Google log-in
Functionality | Decision |
---|---|
State changing actions by authenticated user | Protect |
Long running read only operation that consumes significant amount of resources | Protect |
Large files, network consuming resources that are not core functionality of the website | Don't protect, implement proper throttling |
Internet speed test app | Protect |
Static resources, lightweight read-only dynamic pages | Don't protect |
Log-out page | Don't protect |
Log-in page | Protect |
Implement CSRF protection for actions that you dont want to be executed by users without their knowledge.