Header Ads

INTRODUCTION TO CSRF (Cross Site Request Forgery)

Website security An introduction to Cross-site request forgery. Description, explanation, examples, prevention

What is it?

Instead of just a definition, how about a situational breakdown first:
Cross-site: The action is being done by one user(on a site) and it affects one or more other users(on other sites).
Request: An HTTP request being made on a page
Forgery: Someone else sending a request your way and you making it
CSRF or XSRF for short
The two most fitting nicknames for it I think are Sea-Surf(made from pronouncing the acronym CSRF, you are surfing the internet taking advantage of their session) and session riding, since you are taking advantage of another user's session to perform certain tasks(riding it).

Different?

You may have noticed how the name is similar to XSS as far as the cross-site part goes. This is true because both attacks require more than one user to carry out. In an XSS example, you would need one person to
inject code into a guestbook, but then another user to view that page and get his cookies stolen. In a similar sense, in a CSRF attack one user would trick another into making a request. With CSRF though, a certain
script may be executed when they visit the page, but there is an action being performed just by them accessing the page. It's not something on the page that's being exploited, but just them going to the page unknowingly.

What is required?

Some form of authentication. Like I said, it is a two person job. The victim is logged in and when he "signs" these forged requests, he(or she) is actually doing the final step of the attack. It's required for the person
to have some kind of privilege on the site, whether it be admin, developer, or a plain and simple registered user. The reason is because a number of new pages are now available once you have some sort of further
access within the site. (Like when you are logged out of HBH, you can't use the shoutbox, post in the forums, do the challenges, submit code etc) Just like you couldn't make a new entry or add a friend unless logged
in on myspace or another blog/networking site. A person viewing your site that is not logged in would not be at risk.

Why it works?

Because the (vulnerable) sites do not check to see if it's actually the real person making the request or not. There are simple solutions for this though, I'll get into those later.

Proof of concept:

First, you have to know exactly what's going on before crafting links and getting fancy. Slick sends a link to Smooth in an IM window. He tells Smooth how he just uploaded some new pictures a few hours ago, and
wants someone's opinion on how they look. In reality, Slick hasn't been logged in since a week ago. That doesn't really matter though, because at the moment, Smooth is logged in. It's only because he saw pictures
of Smooth and his girlfriend last month that he's motivated for such an attack. If you didn't know what I meant by "action", it's just something being done on a page. One of the easiest ways to exploit CSRF is to exploit
URL's that use the GET method of requesting(http://site.com/do_you.php?get=it) Post is vulnerable too, more on that later.

Here would be the basic link to close Smooth's account:

http://myimagehostingsite.net/closeAcct.php?confirm=yes
Slick wants to make this a done deal though, he knows if Smooth sees that, he'll know something is fishy. He does a little crafting with hex encoding.

http://myimagehostingsite.net/closeAcct.php?confirm=yes

Smooth dismisses that as a bunch of mumbo jumbo to do with the site that Slick probably doesn't know anything about, so he clicks the link. myimagehostingsite.net doesn't know how the link came to be or how it's being
accessed, it just knows it's being accessed in Smooth's session. Once he is at closeAcct.php and the confirm variable is set to "yes", the account is wiped from the database.

Crafting Examples

Hex encoding is just one way to disguise a link. Here are a few ways to actually hide that a request will be made at all. One common and sneaky way to craft the link is to put it inside of an image tag. Unlike the case of
a hyperlink, you don't have to click it, because it automatically makes an HTTP request on the image when the page loads.
Here's what we could put in an html document.

<img src="http://site.com/page.php?badaction=value" width="0" height="0">

Notice the width and height are 0, for the reason we don't want anyone noticing the broken image. That might suggest something suspicious is going on.

Double click picture to enlarge

<img src="elusive_picture.jpg" onmouse<em></em>over="window.location='http://site.com/not-so-elusive-site.php'">

We trick the user into holding the cursor over the image, then they are redirected. (Unlikely that a person will view the source before going to the page,

<form method="post" name="request" action="http://site/vuln_page"> </form> <body on<em></em>load="request.submit()">
We gave the name "request" to the form, then submitted it when the page loaded. Still vulnerable with $_POST!

The Misconception

Do you think that since GET variables are displayed in the URL and submitted once a link is clicked that POST variables are safe from CSRF? Well, you wouldn't be so lucky(depending on how you look at it). Attacks like phishing can easily work around using a GET page.
Javascript is also handy for submitting forms with post fields. Refer to the last example if you didn't already catch that.

Preventing

On the user's end, they can log out of a site when they aren't using it, that way their session isn't open for attacks from other users. On the coder's end, it is solved by generating a unique key for an action the user could perform
and only follow through on it if they key equals the right value. On a side note, something that won't prevent but will do damage control if you are attacked is to not use the same password for multiple sites. This is a bad idea and
you could get completely screwed over this way.

<? //secure.php $id = createUniqueHash(); if ( $_GET['action'] == 'something' ) { if ( $_GET['token'] == $id ) //do action; else die('Action failed: Incorrect key'); } ?>

instead of
secure.php?action=something
a variable is sent and checked before carrying out the action
secure.php?action=something&token=ad9037jkc00q42

Closing

Surprisingly, I know some people are already knowledgeable on this, but hopefully you enjoyed the read anyway. Comments welcome.
Powered by Blogger.