CSRF (Cross-Site Request Forgery) 2022

The Cross-Site Request Forgery is an attack in which they get access to your system by tricking users into performing actions on another site by inadvertently clicking a link or submitting a form. It is often called CSRF, or XSRF as a short form.

It gets its long name from:

  • “Cross-Site”: originates on one site but performs an action on another
  • “Request Forgery”: it is not a genuine user request

CSRF attacks are especially powerful if the target site has previously authenticated the user’s browser — in other words, if a user has already logged into the target site through the same browser that subsequently loads the attacking site. When you send a request to a website or open an attachment, your browser transfers all stored cookies, which attack your system. Only if those cookies include something like a “logged in=true” setting will the destination server recognize the request as coming from a currently logged-in user. The exploit takes advantage of the fact that the server trusts the user’s browser.

Typically attackers use CSRF attacks to make state-changing requests. The request performs some action, but the attacker will not be able to see the results of the request since it is still a request by the user’s browser.

CSRF

Cross-Site Request Forgery GET Request

The simplest CSRF attack is simply to trick a user into making a GET request to a specific URL. This can be performed by inserting the URL into a disguised link. The link could be put in a blog comment (lots of WordPress exploits have used this technique), a post on a web forum, or a phishing email.

<a href="http://hackermag.com/best_hacker/vote/48576">View PDF</a>

The link hides its true action, and it may fool some users. But it is not a very sophisticated attack because it still requires the user to click the link to activate the action.

A more sophisticated version places the URL somewhere that obviates the need for user action, such as the image source attribute of an image tag.

<img src="http://hackermag.com/best_hacker/vote/48576" />

When a page is loaded, the browser automatically makes individual requests to retrieve all images in the HTML. When a user views a forum page with the above image in a user post, the browser issues a GET request to that URL. The user does not need to click any link; the damage is done while the browser is interpreting the HTML.


Cross-Site Request Forgery GET Request with Authentication

The biggest danger from a CSRF attack comes when the target URL links to a page on a website that requires user authentication and the user’s browser still retains its previous authentication state. The attack takes advantage of the browser’s authenticated state.

Imagine that a user logs in to their bank website. The bank website places a cookie in the user’s browser to indicate that they have permitted their access. Future requests to any page on the bank’s website will include that cookie as proof of authorization.

It works a lot like going to a concert and getting a wristband when you pay or present a ticket. The wristband is what proves your authorized status. Wristband: authorized to be inside. No wristband: not authorized, should not be granted access.

Assume that after completing their banking, the user closes the browser window but does not click “Log out.”. The user’s browser still has the bank authorization cookie — it’s still wearing the wristband.

If an attacker can mislead the user into making a request to the bank’s website when the cookie with the authorization be sent then the request will be regarded authenticated. As far as the bank can tell, this is just another request from the user’s browser.

<img src="https://bank.com/transfer?amount=10000&to_account=2468013579" />

If a user loads a page with the above image tag, it will trigger a GET request to the URL specified in src. In this scenario, an unauthenticated user will get the bank.com‘s login page. But a previously authenticated user could get access if the request is accepted by bank.com.

There are many actions that a CSRF attack can take. Some of the more common ones are:

  • Change password
  • Change email address
  • Login to a site
  • Transfer funds
  • Download malware

Cross-Site Request Forgery GET Request Preventions

The best defense against CSRF attacks that take the form of getting requests is to disallow GET requests for key actions, especially actions that “change state” in some way.

It is considered a best practice to only use GET requests for retrieving data, not for actions that make changes. Instead, use POST requests (such as form submissions) for actions that make changes. (See also HTTP Request Types (GET vs. POST))

Links and image tag sources are always requested. Making all GET requests harmless removes a major pathway for CSRF attacks.


Cross-Site Request Forgery POST Request Attack

GET requests are not the only way to trigger a CSRF attack. An attacker can forge a form. Walking through it step-by-step will help you understand.

Imagine that an attacker does some research to see what a legitimate bank looks like.

<html>
  <head>
    <title>Bank Website</title>
  </head>
  <body>
    <form action="http://bank.com/transfer" method="POST" name="bank_form">
      <input type="text" name="amount" value="" />
      <input type="text" name="to_account" value="" />
      <input type="submit" value="submit" />
    </form>
  </body>
</html>

The attacker can then put that HTML into another page and then trick a user into submitting the form. This would pass any “allow POST requests only” protections that have been put in place, the request would send an authorization cookie, just like a GET request does.

The attacker only needs to find a way to trick a user into submitting this form. They can do that by using CSS to hide the form and then using JavaScript to submit the form when the page loads.

<html>
  <head>
    <title>Fake Form</title>
  </head>
  <body onload="document.bank_form.submit()">
    <form action="http://bank.com/transfer" method="POST" name="bank_form" style="display: none;">
      <input type="text" name="amount" value="10000" />
      <input type="text" name="to_account" value="2468013579" />
    </form>
  </body>
</html>

Notice that the body has an attribute that will submit the form immediately and the form has a style attribute that hides it.

It does not require the user to click “Submit”, in fact, there is not even a submit button on the form. Convincing a user to visit this page is enough to trigger the request. And it’s simple to do using phishing emails.

There is one problem with this attack so far. The form will submit and then the user will see the results of the submission. It might be a page on the bank’s website which says, “Funds transfer complete”. If a user saw that, they would be suspicious and probably call their bank to void the transaction.

An attacker will also need to hide the results. Forms allow sending their results to an iframe using a target attribute.

<html>
  <head>
    <title>Fake Form</title>
  </head>
  <body onload="document.bank_form.submit()">
    <form action="http://bank.com/transfer" method="POST" name="bank_form" style="display: none;" target="hidden_results" >
      <input type="text" name="amount" value="10000" />
      <input type="text" name="to_account" value="2468013579" />
    </form>
    <iframe name="hidden_results" style="display: none;"></iframe>
  </body>
</html>

Notice the addition of the iframe tag (with display: none) and the form the tag has a new target attribute.

If the attacker hides  iframe and sends the form results there, the user will have no hint that the CSRF attack has occurred.


Cross-Site Request Forgery POST Request Defenses

One easy defense is to verify that the HTTP referer in the POST the request is originating from the correct domain. Any legitimate form submission should have a referer and that referer should be the expected one for the form page. The referer is spoofable, but it adds another challenge for an attacker to overcome. And each layer of defense adds to a Defense-in-depth strategy.

<?php
  function request_is_same_domain() {
    if(!isset($_SERVER['HTTP_REFERER'])) { return false; }
    $referer_host = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
    return ($referer_host === $_SERVER['HTTP_HOST']);
  }
?>

The use of “CSRF Tokens,” also known as the “synchronizer token pattern,” is the most effective protection against CSRF attacks.

The synchronizer token pattern can be implemented on forms using the following steps.


  1. Generate a large, unique, random string for use as a token.
<?php
  function csrf_token() {
    // Requires PHP 7 or later
    return bin2hex(random_bytes(64));
  }
?>

  1. Add token to user’s session data
<?php
  function create_csrf_token() {
    $token = csrf_token();
    $_SESSION['csrf_token'] = $token;
    $_SESSION['csrf_token_time'] = time();
    return $token;
  }
?>

  1. Add token to the form data.
<?php
  function csrf_token_tag() {
    $token = create_csrf_token();
    return '<input type="hidden" name="csrf_token" value="' . $token . '">';
  }
?>

In any form:

<?php echo csrf_token_tag(); ?>

  1. When the form is submitted, compare the form token with the session token.
<?php
  function csrf_token_is_valid() {
    if(!isset($_POST['csrf_token'])) { return false; }
    if(!isset($_SESSION['csrf_token'])) { return false; }
    return ($_POST['csrf_token'] === $_SESSION['csrf_token']);
  }
?>

  1. If the tokens match then the form is valid. If not, it is invalid.
<?php
  if(csrf_token_is_valid()) {
    // process the form
  } else {
    // reject the form
  }
?>

Generally, the attacker should not be able to see the session token given to the user, nor should they be able to set it. Therefore the attacker cannot predict the correct form token to add to their fake form.

Unless the attacker also can use Cross-Site Scripting (XSS) to gain access to the user’s browser cookies. Then they could potentially steal the token information they need to construct a matching form. When putting CSRF protections in place, it is equally important to make sure that XSS protections are in place.

This is a simple CSRF token implementation, and there are more advanced versions. A token could be only valid for a limited time period, such as 5 or 10 minutes. The token generated could be unique for each form on the site. The session token and the form token could be different values that are complimentary. For example, encrypting one string could return the other string.


CSRF tokens are the best protection, but there are a few more that can further strengthen application defenses. Often these defenses are added to the most sensitive actions. These include access-related actions like changing a username, email, password, or security preferences, or high-stakes actions like deleting something significant or transferring money.

For sensitive actions, the site could require additional user action or confirmation in addition to the form submission. For example after the form is submitted, a second “please confirm this action” page could be presented. A CSRF attack would not be able to react to the second page. Some sites add a CAPTCHA image to confirm that there is a user behind an action.

Before changing passwords or security preferences, many sites require a user to re-authenticate by providing their password again. A CSRF attack would not be able to respond to the second request, nor would the attacker know the correct password.

Share your love
TheCyberDelta
TheCyberDelta

I am just a robot

Articles: 39
Home
Editorials
Articles
Search