Ø Definition:
“A CSRF attack forces a logged-on victim’s browser
to send a forged HTTP request, including the victim’s session cookie and any
other automatically included authentication information, to a vulnerable web
application. This allows the attacker to force the victim’s browser to
generate requests the vulnerable application thinks are legitimate requests
from the victim.”
|
Ø A Cross-site
request forgery attack, also known as CSRF or XSRF (pronounced
sea-surf) is the less well known, but equally dangerous, cousin of the Cross
Site Scripting (XSS) attack.
Ø The MVC
framework introduced new security methods like AntiForgeryToken.
Example: Simple banking website
Ø The site properly
blocks anonymous users from taking any action. You can see that in the code for
the controller:
[Authorize]
public class HomeController : Controller
{
//...
}
|
Ø Notice that
we use the AuthorizeAttribute on the controller (without specifying any roles)
to specify that all actions of this controller require the user to be
authentication.
Ø After logging
in, we get a simple form that allows us to transfer money to another account in
the bank. Note that for the sake of the demo, I’ve included an information
disclosure vulnerability by allowing you to see the balance for other bank
members.
Ø To transfer
money to my Bookie, for example, I can enter an amount of $1000, select the
Bookie account, and then click Transfer. The following shows the HTTP POST that
is sent to the website (slightly edited).
POST /Home/Transfer HTTP/1.1
Referer: http://localhost:54607/csrf-mvc.html
User-Agent: ...
Content-Type: application/x-www-form-urlencoded
Host: 127.0.0.1:54607
Content-Length: 34
Cookie: .ASPXAUTH=98A250...03BB37
Amount=1000&destinationAccountId=3 |
Ø There are
three important things to notice here. We are posting to a well known URL,
/Home/Transfer, we are sending a cookie, .ASPXAUTH, which lets the site know we
are already logged in, and we are posting some data
(Amount=1000&destinationAccountId=3), namely the amount we want to transfer
and the account id we want to transfer to. Let’s briefly look at the code that
executes the transfer.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Transfer(int destinationAccountId, double amount) {
string username = User.Identity.Name;
Account source = _context.Accounts.First(a => a.Username == username);
Account destination = _context.Accounts.FirstOrDefault(
a => a.Id == destinationAccountId);
source.Balance -= amount;
destination.Balance += amount;
_context.SubmitChanges();
return RedirectToAction("Index");
}
Ø The code is
straightforward. We simply transfer money from one account to another. At this
point, everything looks fine. We’re making sure the user is logged in before we
transfer money. And we are making sure that this method can only be called from
a POST request and not a GET request (this last point is important. Never allow changes to data via a GET request).
Ø Well BadGuy,
another bank user has an idea. He sets up a website that has a page with the
following code:
<html>
<head>
<title></title>
</head>
<body>
<form name="badform" method="post"
action="http://localhost:54607/Home/Transfer">
<input type="hidden" name="destinationAccountId" value="2" />
<input type="hidden" name="amount" value="1000" />
</form>
<script type="text/javascript">
document.badform.submit();
</script>
</body>
</html>
Ø What he’s
done here is create an HTML page that replicates the fields in bank transfer
form as hidden inputs and then runs some JavaScript to submit the form. The
form has its action set to post to the bank’s URL.
Ø The end
result is that I’m out of $1000 and BadGuy has his bank account
increased by $1000. Drat!
Ø The mitigation in ASP.NET
MVC is to use the AntiForgery helpers.
·
The first step is to add the
ValidateAntiForgeryTokenAttribute to the action method.
[ValidateAntiForgeryToken]
public ActionResult Transfer(int destinationAccountId, double amount) {}
·
Next step is add Html.AntiForgeryToken()
method in view.
@using (Html.BeginForm("Transfer", "Home")) {
<p>
<label for="Amount">Amount:</legend>
@= Html.TextBox("Amount")
</p>
<p>
<label for="destinationAccountId">
Destination Account:
</legend>
@= Html.DropDownList("destinationAccountId", "Select an Account")
</p>
<p>
@= Html.AntiForgeryToken()
<input type="submit" value="transfer" />
</p>
}
·
When you
view source, you’ll see the following hidden input.
<input name="__RequestVerificationToken"
type="hidden"value="WaE634+3jjeuJFgcVB7FMKNzOxKrPq/WwQmU7iqD7PxyTtf8H8M3hre+VUZY1Hxf" />
Ø Let us have a
brief look at the security methods.
·
Authorize attribute: This is useful to authorize a
user or role to access any resource in the application after authenticated.
This helps to have User and Role level protections.
·
Http Referrer Check: This is a general method not
confined to .NET. This is to prevent an URL request which is not from the site,
but from an external link or the link directly executed at the browser
navigation bar.
·
Anti Forgery Token: This is a powerful option to
prevent any hidden field manipulation while form posting and prevents
Cross-Site Request Forgery
Ø When a web
server is designed to receive a request from a client without any mechanism for
verifying that it was intentionally sent, then it might be possible for an
attacker to trick a client into making an unintentional request to the web
server which will be treated as an authentic request. This can be done via a
URL, image load, XMLHttpRequest, etc. and can result in exposure of data or
unintended code execution.
Ø In order for
this attack to be successful, your site must track users logged in with
cookies, and they must be logged into your site at the time they visit a site
or click a link which the attacker has provided to the user.
Ø There are a
variety of tricks employed which can cause a user to 'click' the attacker link.
For instance, any site an attacker has access to, such as a forum or social
network account, may include special image tags which actually call include the
link to the target site. The link can be crafted to force the users browser to
execute an action using the session credentials they logged in as, along with
any effects of submitting that link.
Ø In this way, when the page loads, the user has
'clicked' whatever link is placed in the image tag, and the authenticated
action has been performed without the users permission.
Ø If the
targeted user happens to be an administrator, this attack could potentially
allow an attacker to gain control of an entire web application.
Ø Imagine the following
attack scenario:
·
Bob is browsing mysite.com, and is logged in as a
user.
·
Mysite.com has a button which, when pushed, will
send an e-card to all of Bob's saved contacts automatically with a link.
·
While Bob is on mysite, he has a question about
some features, and goes to his favorite forum about mysite - mysiteforums.com.
·
He opens an interesting post by another user. This
post contains an image tag looking something like <img
src='http://www.mysite.com/send-e-cards'/>
·
Bob's browser tries to fetch the image, and sends
Bob's authentication cookie along with the request to mysite.com/send-e-cards.
·
Mysite.com receives the request from Bob to send
the e-cards, and so sends the ecards.
·
The attack is successful, even though Bob never
clicked on the send button!
Ø This kind of
attack was successfully used to spread worms through both MySpace and Facebook.
The nature of the attack makes it easy to self-propagate on sites where users
may post profile information.
Ø Impact to Your Site &
User Base
·
Impact for XSRF can be minimal or critical
depending on the nature of your site. It is classified as lower during our
scans due to the lack of additional information needed to make a proper
security assessment, which can only be made by site owners.
·
XSRF could potentially be used for anything ranging
from tricking a user into changing their password on your site, to withdrawing
funds if the site is a bank allowing transactions.
Ø How to Prevent CSRF Attacks
·
Preventing CSRF requires changing how all GET and
POST requests work on a site, to ensure that users who are requesting an action
have actually done so, and were not tricked into doing so. Because of the way
an XSRF attack works, the attacker never has access to the cookie data stored
on the targets machine, and this fact can be used to craft a defense.
·
Taking advantage of this, site owners can generate
unique values on all forms, such that an attacker would not be able to guess
ahead of time what to submit in the POST or GET request. This is called a
nonce, or unique random value.
Ø To implement this, you have
to include a few logic layers in your application.
·
Include a hidden form field on all forms of your
site which are required when a user is logged in. For example purposes, let's
call it the nonce.
·
Include the nonce value in the users session
variables, so that they have a copy.
·
After every POST or GET evaluation you want to
protect, make sure that the nonce from the browser (session) matches the nonce
from the form (GET/POST value)
·
If they do not match, then the page may have been
submitted fraudulently (XSRF)
·
The nonce may be generated new for each form, or
stored server side in a database. Be aware that if it is generated new each
time, you may face issues with users back button functionality, or multiple
tabs.
Thanks to Mr K.S. Sivanath for his valuable document about Cross Site Request Forgery(CSRF) vulnerabilities in OWASP CONCEPTS
Contact Details: sivanathks@hotmail.com
No comments :
Post a Comment