Exploit cross-site request forgery (CSRF) - Lab
TL;DR - show me the fun part!
1- Login into the app.
2- Exploit the app.
3- List users, notice the new one.
Intro
Cross-site request forgery (CSRF) is a web vulnerability that allows an attacker to make users (victims) perform actions that they do not intend to perform.
Let’s say a web app allows users after authentication, to update their login email using endpoint
https://example.com/profile/updateEmail
In CSRF, the attacker can make the users change their login email address to whatever email set by the attacker.
CSRF requires user interaction, like authenticated user visits on a malicious page.
Enough talking, let’s get our hands dirty ๐.
CSRF in action - app demo ๐
In this lab you will play and exploit a flawed web app to understand and analyse how CSRF attack works.
Let’s get started and see how this app works in the first place!
-
Start network monitor in your browser developer tool (I will be using Firefox)
-
Open the web app login page
-
Click on login - no need for credentials ๐
-
After a successful login, the app sends back a session-cookie ๐ช
The session cookie has the following attributes:-
- domain - valid for
secure-cookie.io
and all subdomains - expires - life time is 1 hour
- httpOnly - cookie can’t be read by JS
- path - valid for all paths, like /admin /verify /add /whatever
- samesite -
None
means the browser will send this cookie forsame-site
+cross-site
requests ๐ - secure - cookie should be submitted over HTTPs only
- value - random token in JWT format
-
The web app offers you as an admin to create a new user(s). Keep the network tab running. Fill the form to create new user and click on
Add
button. -
Let’s inspect the HTTP request that has been sent.
POST /addUser HTTP/2
Host: csrf.secure-cookie.io
Referer: https://csrf.secure-cookie.io/admin
Content-Type: text/plain
Origin: https://csrf.secure-cookie.io
Cookie: SessionId=eyJ0eXAiOiJKV1 ...etc
- HTTP method is
POST
and endpoint is/addUser
- Adding host, the complete URL would be
https://csrf.secure-cookie.io/addUser
- The request was made from page path
https://csrf.secure-cookie.io/admin
- The data (username and password) has been sent in
text/plain
format - The request was made from origin
https://csrf.secure-cookie.io
SessionId
cookie was included in the request header - only authenticated person can add new users.
Now click on list users
to verify that a new UserID has been created. Before we proceed,
do you think /addUser
api is secure?
You can pass the request from your browser to Burp Repeater to manipulate the request. You can try to omit cookie value or inject stuff in the form fields ๐.
Assuming the endpoint is properly validating the cookies before creating a user. Then how an attacker can exploit this api?
let’s continue to find out!
CSRF in action - attack demo ๐ฅ
The csrf attack can be explained in one image
-
Authenticated user visiting attacker page. Please do so to exploit the endpoint.
-
Attacker page contains JS asking the browser to make API calls (like add user) to the vulnerable endpoint.
-
Browser sends the request along side with the cookies (by default) to the requested endpoint.
After visiting the attacker’s page, jump back to admin portal and click again List Users
button aaaaaaand….
a new user has just been created! ๐ฎ
What you just saw explains the naming of cross site request forgery:-
-
The request was made cross site from an attacker’s site.
-
The request has been forged without the victim’s awareness.
Let’s deep dive in each step ๐
Analysing the attack ๐
-
Reload the attacker page again while having the network tab opened.
-
View the page source code and notice that the JS function
execute_all_attacks();
will be executed whenever the HTML body gets loaded in the browser. It also calls another functionattack_addUser_endpoint()
.
<body onload="execute_all_attacks();">
<script>
function execute_all_attacks(){
attack_addUser_endpoint();
}
</script>
โ๏ธ This means, the attack happens as soon as the user (victim) visits the attacker page. No other user interaction is required (like clicking on a button as in Clickjacking).
- In the network tab you should see a POST request has been sent to /addUser endpoint.
To trace the JS function that made that call, click on
initiator
field and then click onattack_addUser_endpoint()
. Below is the related snippet.
function get_post_http_headers(data, content_type){
return {
method:"POST",
body: data,
headers: {'Content-Type':content_type},
credentials: 'include'
}}
function attack_addUser_endpoint(){
backdoor_user = "user=backdoor,pass=backdoor"
var options = get_post_http_headers(data=backdoor_user,content_type='text/plain')
var request = fetch(url="https://csrf.secure-cookie.io/addUser",options);
request.catch(err => update_user_added_html())
}
-
This function exploits the vulnerable endpoint
/addUser
. The function:-- sets a
backdoor_user
username and password as request body. - calls
get_post_http_headers();
to set HTTP headers such as POST method, content-type. - makes cross-site request using fetch() against
https://csrf.secure-cookie.io/addUser
- sets a
-
The browser is gonna make the request and send the cookies along with the request.
-
If you already read my write up same-origin policy rules. Now you might be wondering, isn’t this a violation of same-origin policy (SOP) as the request was made cross origin?
๐ CSRF attack does not violate same-origin policy rules. SOP will allow the attacker to WRITE to the endpoint but not to READ the response. The request will hit the endpoint but JS is not allowed to read the response.
- To prove this โ๏ธ, go to console tab and notice what the warning msg says.
The Same Origin Policy disallows reading the remote resource.
In this attack, the attacker does not really care about the response from /addUser
. Because the
“backdoor user” is already sent by the victim’s browser. And it’s an authenticated
request since the browser includes the session-id cookie in the request.