Cross site request forgery

in-depth study

Created by Piotr Podsiadly

OMG yet another security training

Lemme click that "I understand" button

Many security trainings are great

for making sure corporation is compliant with the law.

Impractical training

Reducing chance of being compromised

comes with the cost.

Web application security is difficult to master.

Let's dive into CSRF!

Cross site request forgery

The basics at first

GET example

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
						

POST example


<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
						

CSRF Definition

Attack that forces end user to execute unwanted actions on a web app in which they're currently authenticated.

  • state-changing requests, not theft of data
  • social engineering like sending a link via email or chat
  • administrative account victim

Sever scenario

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

Why it works?

Session cookie headers are automatically passed with every page request matching associated domain


GET / HTTP/1.1
Host: google.com
Cookie: SID=JWAAAsh-84ShNVVG...
						

How to prevent it?

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

Social engineering highlights

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

URL magic

  • аЬϲ - cyrlic, sigma
  • abc - latin

Nowdays mitigated by modern web browsers pаypal.com

HTML injection synergy

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

CSRF prevention epic fails

With Synchronizer Token Pattern you can still be vulnerable

gun hold backward

or even hurt yourself.

Disclosure of CSRF-Token in URL

Don't put the token as GET request param value.

If you do, it can be read from:

  • browser history
  • http log files
  • referer header

or retrieved through social engineering by asking the user to copy and paste the link.

Cross-origin resource sharing

If you have CORS enabled


Access-Control-Allow-Origin: *
						

you allow any domain to read your site HTML/DOM. This includes reading CSRF-Token.

XSS vs CSRF

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.

Fix XSS first!

Prevention Measures That Do NOT Work

  • Using a Secret Cookie
  • Only Accepting POST Requests
  • Multi-Step Transactions

Code review for CSRF

  • Is this a state changing action?
  • What if someone asks user to perform it without his consent?
  • Which HTTP method it uses?
  • Does it utilize common prevention logic?

OWASP code review wiki page

OWASP CSRFGuard

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

Testing for CSRF

Can be easily automated:

  • record real traffic
  • log in again
  • replay the traffic with new session

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

WAIT! There is more

We covered the basics, let's dive in to advanced topics at last!

CSRF in HTML5/Ajax web application

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>
						

HTTP/TCP level comparisson

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

PUT or DELETE method

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

bug/feature

Rails example - support for PUT in "legacy" browsers


<form action="/news/1" method="post">
  
</form>
						

XML SOAP body

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>
						

JSON body

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"}
						

AJAX or good old forms

It does not matter.

You should prottect from CSRF regardless of web technology stack.

blog post

Read only / public pages

CSRF definition key words: "execute actions" by "authenticated" user

Do we protect read only corporate account balance?

IP based throttling

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

DDoS through 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

CSRF tokens and page usability

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

Log-out usability and CSRF protection

CSRF - "execute action" by "authenticated" user


<img src="http://my-app.com/logout"/>
						

single sign-on

  • chat.web-app.com
  • shop.web-app.com
  • wiki.web-app.com

https://accounts.google.com/Logout?...secTok=....

Protecting Log-in page from CSRF

Prompt pattern

Google log-in



						

When to protect

FunctionalityDecision
State changing actions by authenticated userProtect
Long running read only operation that consumes significant amount of resourcesProtect
Large files, network consuming resources that are not core functionality of the websiteDon't protect, implement proper throttling
Internet speed test appProtect
Static resources, lightweight read-only dynamic pagesDon't protect
Log-out pageDon't protect
Log-in pageProtect

blog post

Summary

Implement CSRF protection for actions that you dont want to be executed by users without their knowledge.

Knowledge check

This presentation

THE END

BY Piotr Podsiadly

Piotr Podsiadly