Blog

Fighting CSRF

Posted by Kellanved in Development, Modifications with the tags , , on January 14th, 2009

Cross-Site-Request-Forgery, short CSRF, is a type of vulnerabilities that gets more and more attention. The concept can be translated as “tricking the browser into automatically performing some action using the user’s privileges”. Let’s see what phpBB does about it.

CSRF basics

CSRF basics

The secret behind this is that web applications use cookies to identify the user. Also, cookies get automatically added to every request sent to the cookie’s domain – regardless of the cause of the request. So, if a webpage tells your browser: send a request to that domain, with the parameters X, it will do it — and add your cookie, telling the target domain who you are. Hence, the request gets treated as if you had issued it willingly, using your privileges.

What can be done about it?

Sadly, there is no silver bullet to get rid of CSRF once and for all. But on the other hand, we offer a whole toolkit of measures in phpBB 3.0. So, let’s give you a short tour of our measures:

Referrer Validation

phpBB offers you the option to validate the HTTP Referrer header of incoming POST requests. This is a transparent way of offering a weak CSRF protection. Naturally this does not work at all for requests triggered from the same domain, nor will it work if users use browsers that send no referrer. Moreover, it is easy to suppress the referrer for GET requests, which is why only POST requests get any protection at all.

Usage: N/A
Protects: POST requests only
Security: Rather weak
Pro: Completely transparent.
Contra: POST only, not very secure, users might not send a referrer.

Link Hash

For the protection of GET requests, for instance the bookmark function, we have added link hashes in 3.0.3. While links, i.e. actions via GET, should not alter the application state, it can’t be helped for some lightweight operations. For such operations we have link hashes. The idea is that by adding some secret to every valid (state changing) link, we make it impossible (within the limits of cryptography) for attackers to create valid requests. An attacker would have to know the secret, otherwise the software can tell valid from malicious actions.
Usage:
To use a link hash, you first have to generate it by using the generate_link_hash function. This function takes a single argument – the action that is to be hashed. The rules for the argument are as follows:

  • It should not be completely constant, as that does reduce security.
  • All invocations of this function on the same page should use the same or few different values. Generating a new hash is expensive, so re-use.
  • The php file handling the request needs to “know” the value that was used; i.e. they have to match

This argument is then added to the protected link as “hash”, i.e.

Code: Select all
...&hash=" . generate_link_hash("{$mode}_$match_id"))

To later check the link hash, the function check_link_hash is used, with the submitted hash and the value that was used to generate the link as arguments. I.e.

Code: Select all
$token = request_var('hash', '');

check_link_hash($token, "{$mode}_$match_id")

If that returns true, all is well. Otherwise: something fishy might be going on.
Protects: Intended for GET
Security: Reasonable
Pro: Works for links, rather secure, quick for user
Contra: Links have to be altered to include hash.

Form Tokens

The bread-and-butter CSRF protection are form tokens. These form tokens are conceptually the same as link hashes, but are passed via a hidden form field instead of using a GET parameter. Form tokens expire after a time, which can be set in the ACP and are only valid for the given user.
Usage: They are used very similarly to link hashes: First a Token has to be generated (and added to the template variables) by calling the function add_form_key. It takes a single argument, a string describing your form – it is important to use different values for different forms.

Code: Select all
add_form_key('posting');

Then the {S_FORM_TOKEN} template variable has to be added to the form’s template. The variable contains – after the invocation of add_form_key – a set of hidden fields with all the information required.
To validate a request, check_form_key is used with the same argument that was used to generate the form token.

Code: Select all
check_form_key('posting')

Like with hashes, true means that all is well.

Protects: POST requests only, intended for reversible actions
Security: Reasonable
Pro: Transparent for user, rather secure

Contra: POST only, needs template changes

Confirm Boxes

The heavy-duty protection are confirm boxes. These boxes are meant to protect irreversible actions and also prompt the user to confirm that s/he really wants to perform the action in question. As a means to improve security, only one confirm box can be used at once. Users with several browser windows sometimes find this irritating.
Usage: The confirm box adds another step in the form submission and thus requires rather extensive changes to the script that uses it. The basic concept of the usage is a if statement, where the THEN part is for performing the action and the ELSE part is for assembling all the data that is needed to reach the same state in the script. The guard is the function confirm_box with the argument true, the ELSE part uses the same function, but with different arguments. These are: false (to show that we are setting up a new confirm box), a language string describing the action and the HTML for hidden fields. The requirement here is that the script reaches the exact same state with the hidden fields as it had when it first hit the confirm_box.

Code: Select all
if (confirm_box(true))

{


// Perform actual action

}

else

{

$s_hidden_fields = array(

'foo' => $bar,


);

confirm_box(false, $user->lang['Explanation'], build_hidden_fields($s_hidden_fields));

}

The confirm_box function:
Protects: Irreversible actions
Security: Strong

Pro: Secure, Gives feedback
Contra: Just one at a time; User interaction required

24 Responses to “Fighting CSRF”

Posted by typefreak on January 14th, 2009 at 5:20 pm:

About the “Confirm Boxes”:

Actually, the way you currently describe them ads a very weak sense of security, as it is quite easy to forge two post request with, say, two seconds between them.
If the code generating the $s_hidden_fields array is known, and being open-source, it is, the resulting hidden fields can be easily calculated, completely surpassing the ‘added’ defence.

In order for the ‘Confirm Boxes’ to be actually effective, BOTH stages need to be combined with a correct implementation of ‘Form Tokens’.

Posted by Kellanved on January 14th, 2009 at 5:29 pm:

The code is known, but the resulting value can – to the best of my knowledge – not be easily guessed. In effect, it is a token with the challenge being stored in the database, thus giving less information to attackers.
Also, there is exactly one correct response; normal form tokens are not that strict.

Posted by typefreak on January 14th, 2009 at 6:18 pm:

Ah, I see now. The security is found within the confirm_box() function itself, making a random token required for the second stage. That’s indeed difficult to circumvent.

I expected the confirm_box() function just to generate the form with the given fields. Looking at the code, thats obviously not the case 🙂 Thanks for your reply.

Posted by skyhook on January 14th, 2009 at 10:08 pm:

I’m not too familiar with this vulnerability but I really hope it’s not too serious.

Posted by EXreaction on January 15th, 2009 at 3:35 am:

Actually, even with all that protection, running a CSRF on phpBB3 is relatively easy, provided you have a few things.

1. The board must have incorrect cookie settings so the session_id is stored in the URL.
2. You must have access to an IP address within the range allowed for the session check.

If you do not have both of those, the attack becomes very difficult. So make sure your cookie settings are correct and the session ID is never in the URL when browsing the forum (it is fine, and required for the ACP). Also make sure your Session IP validation is at least A.B.C (the default) or All. If it is set to All it could cause issues for some of the users with dynamic IP addresses, but a CSRF is, AFAIK, not possible unless the one attacking also has access to your same IP address (say at a public wifi terminal).

Speaking about public Wifi, NEVER administrate your board over one and NEVER log in anywhere unless you are using something like a encrypted VPN or you are accessing an SSL (HTTPS) website.

Posted by EXreaction on January 15th, 2009 at 3:43 am:

Also, I’d like to add a bit to that yet. 😛

If you are not currently logged on as an administrator (the part where it asks you again for your password to the ACP), a CSRF attack really can not harm you because the attacker would need to know your password to do anything in the ACP.

About the most that a CSRF could do against you if you are not logged in as an administrator is change some profile information (not your email address or password however), and, at the very most, delete/edit/add posts.

For those with multiple administrators, remember that each one of them makes it that much easier for someone to perform a CSRF attack, so do not give anyone more permission than they need (especially not user administration unless absolutely needed).

Posted by Kellanved on January 15th, 2009 at 11:55 am:

EXreaction,
knowing the SID is not even remotely enough for a CSRF.

~H

Posted by EXreaction on January 16th, 2009 at 6:23 pm:

If you know the Session ID and have an IP address within the range of the person you are trying to attack, a CSRF can be done quite easily (I’ve tried it out myself in the past).

Posted by Kellanved on January 16th, 2009 at 8:28 pm:

Sorry, but I doubt that. It is pretty much impossible to use a SID for a Cross Site Request Forgery.
You might have performed a session hijacking, using the same computer, but not a CSRF.

~H

Posted by Pony99CA on January 17th, 2009 at 4:55 pm:

I have to say that I found this article very difficult to follow. I’ve read your articles before (specifically on old hacks and CAPTCHAs) and liked them, so I don’t know if you wrote this one too quickly or assumed we knew the subject better or were just having a bad day. 🙂

I’m not a Web developer, but I am a software developer with over 15 years experience, so it’s not like I’m incapable of following logic.

Here’s what I specifically though could be improved.

First, you claimed that CSRF was getting “more and more attention”. What does that mean? Is that just general discussion on the Web, or in the phpBB support forums? Or is the attention more from hackers producing attacks, especially against phpBB?

I occasionally read security related news and I haven’t noticed more attention on CSRF. It’s mostly been about SQL injection and iFrame attacks against legitimate sites. So maybe some links to this attention would be useful.

Second, the CSRF basics section was ridiculously short. How about telling us how users might encounter this and what necessary conditions are required for it to happen? For example, if I have a phpBB site open, because this is a cross-site attack, I assume that I need a malicious site open in the same browser, correct? Can hackers exploit only features of the phpBB page I’m on, or any phpBB function?

If these basics would have made the article too long, maybe a blog post about them before posting this one would have been a good idea (and still is). At the very least, a link to discussion of CSRF basics would have been useful.

Third, I wasn’t clear what the article was telling us. Are these features already implemented in phpBB 3 and actively used by default? Is the infrastructure (like the link hash and form key functions) already there but we need code mods to actually use them? Or is the infrastructure not even there and you’re showing us generically what we need to do to add protection?

If this is code users need to add, maybe showing a specific example in the phpBB 3 code base would have made things more obvious. This seems to have been especially true of the confirm box example.

Maybe you could do another blog entry about CSRF basics or at least update this one based on the above suggestions.

Thanks,
Steve

Posted by Mr. Bond on January 17th, 2009 at 7:38 pm:

Pony99CA,
“Third, I wasn’t clear what the article was telling us. Are these features already implemented in phpBB 3 and actively used by default? Is the infrastructure (like the link hash and form key functions) already there but we need code mods to actually use them? Or is the infrastructure not even there and you’re showing us generically what we need to do to add protection?

If this is code users need to add, maybe showing a specific example in the phpBB 3 code base would have made things more obvious. This seems to have been especially true of the confirm box example.”

As Kellanved said: “But on the other hand, we offer a whole toolkit of measures in phpBB 3.0. So, let’s give you a short tour of our measures,” these functions such as confirm_box() and check_form_key() / add_form_key() are all in phpBB3 and are used to prevent CSRF attacks in phpBB3 🙂

I found the article very easy to follow but that may be because I use these functions quite often within phpBB3.

-Bond

Posted by EXreaction on January 17th, 2009 at 10:00 pm:

“Sorry, but I doubt that. It is pretty much impossible to use a SID for a Cross Site Request Forgery.
You might have performed a session hijacking, using the same computer, but not a CSRF.”

Session hijacking and a CSRF are basically the same thing. I call it a CSRF when something can be done by a script automatically (and what I have been talking about is done automatically), and yes, it is session hijacking, a CSRF is session hijacking, just an automatic one.

You do not need the same computer to perform sesion hijacking.

Posted by TerraFrost on January 18th, 2009 at 1:19 am:

First, you claimed that CSRF was getting “more and more attention”. What does that mean? Is that just general discussion on the Web, or in the phpBB support forums? Or is the attention more from hackers producing attacks, especially against phpBB?

General discussion on the Web and the webapp security, in general, I imagine. Indeed, the general interest has materialized in the form of a Firefox extension designed to address CSRF:

http://ha.ckers.org/blog/20090117/request-policy-firefox-extention/

Second, the CSRF basics section was ridiculously short. How about telling us how users might encounter this and what necessary conditions are required for it to happen? For example, if I have a phpBB site open, because this is a cross-site attack, I assume that I need a malicious site open in the same browser, correct? Can hackers exploit only features of the phpBB page I’m on, or any phpBB function?

In-so-far as is known, phpBB really isn’t exploitable. As for what an exploit would look like were one feasible… say no CSRF exploit protection were in place. If you then visited “evil website” (while logged into your phpBB; you don’t need to have it open in your browser for you to be logged in), that website could use a prepopulated HTML form and submit it via POST to your board. That’d then result in “evil website” making a post through your account.

Third, I wasn’t clear what the article was telling us. Are these features already implemented in phpBB 3 and actively used by default? Is the infrastructure (like the link hash and form key functions) already there but we need code mods to actually use them? Or is the infrastructure not even there and you’re showing us generically what we need to do to add protection?

The infrastructure is already present.

“Sorry, but I doubt that. It is pretty much impossible to use a SID for a Cross Site Request Forgery.
You might have performed a session hijacking, using the same computer, but not a CSRF.”

Session hijacking and a CSRF are basically the same thing. I call it a CSRF when something can be done by a script automatically (and what I have been talking about is done automatically), and yes, it is session hijacking, a CSRF is session hijacking, just an automatic one.

You do not need the same computer to perform sesion hijacking.

If you’re on the same LAN as another phpBB user and are able to sniff packets and get their sid and use that to perform actions as the owner of that sid… that’s not really “cross site”. If, in the setup you described in this post, you had a site on the same LAN that looked at the HTTP Referer to get the sid and then went off and did its own thing with it… would that be CSRF or session hijacking? In that event, it would be “cross site” even though it wouldn’t involve “evil website” making your browser do HTTP requests. Either term could work, I guess, although, imho, session hijacking would be the more appropriate term, all the same.

Posted by Techie-Micheal on January 18th, 2009 at 4:40 am:

Session hijacking and a CSRF are basically the same thing. I call it a CSRF when something can be done by a script automatically (and what I have been talking about is done automatically), and yes, it is session hijacking, a CSRF is session hijacking, just an automatic one.

You do not need the same computer to perform sesion hijacking.

Not quite. While I see your point, as in order to perform actions as the user, the user needs to have a session, the difference is that you don’t have their session.

For example, let’s say I have a malicious page on my website that you visit while you are logged in to your bank. I ride your session, executing my commands as you, but I never get to actually see your session.

Session hijacking, on the other hand, I get to see your session and essentially become you, as opposed to the human proxy deal going on with CSRF.

Posted by EXreaction on January 18th, 2009 at 11:19 pm:

Well, yes, I guess it really isn’t cross site what I have been talking about. But if you could say, post messages on paypal and it did not confirm messages, would you consider someone posting the link paypal.com?send_to=me&amount=500 as an image link a CSRF? It would be taking place on the same site, so it wouldn’t really be cross site…but the results would still be the same.

I guess it would only be considered session hijacking, although it is still a direct attack on the site using an automated script. You do not need to be on the same lan as the other person, you just need to be within the set IP range (by default that is A.B.C.X). Although it would only give a tiny, tiny chance other than not being on the same lan, it is possible.

Also, the method I used was using the remote avatars, but it could also be done with regular [img] bbcodes.

Posted by Kellanved on January 19th, 2009 at 3:32 pm:

Pony99CA : yes, indeed. The article was written in a hurry and I am thinking about drawing up a slower-paced version.

EXreaction: The two things have nothing to do with each other whatsoever. CSRF is about tricking the victim’s browser into sending data to achieve something. The defense against it – adding secrets into valid submissions – is the topic of the post.
Session hijacking is about using the victim’s session.

Yes, both lead to actions performed using someone else’s account. But the article is just about one of them.

~H

Posted by EXreaction on January 23rd, 2009 at 12:52 am:

Yes, I suppose you are correct. CSRF would only cover the really simple attacks like paypal.com?send_to=attacker&amount=500. But I can’t imagine too many sites being vulnerable to that.

As long as you would check if the page was submitted and required $_POST exclusively (or at least just for the submit button), I don’t think CSRF’s are an issue.

Posted by Kellanved on January 23rd, 2009 at 11:41 am:

CSRF is a huge issue and probably the #1 kind of vulnerability right now. POST doesn’t help a bit, it’s not much harder to send POST requests to other pages.
It’s not an issue if the API is used right – something this post was supposed to point out 😉

~H

Posted by EXreaction on January 23rd, 2009 at 7:22 pm:

I did a little bit of reading quick and noticed it mentioned Javascript and Flash could be used on wikipedia. I had never thought of that, good to know. 🙂

Posted by Techie-Micheal on January 25th, 2009 at 9:29 pm:

Amazon.com is vulnerable to CSRF. They refuse to fix it. At least, as of March of 2007. So yes, this is pretty significant that something like phpBB has a good API that mitigates CSRF.

Posted by RedScourge on March 30th, 2009 at 4:49 pm:

I designed a login system once, which combined a few things like this to prevent hijacking/csrf:

It was an AJAX based login where at the time of the request, it grabs some values from the server; a hashing salt value a server timestamp, and an ID in the DB that stores the timestamp and salt. It then uses a JS SHA256 library to hash the password entered combined with the timestamp and salt, it then posts back the hashed result, then posts back the hash result, salt, and timestamp used. The server rejects it if the timestamp is 10+ seconds ago, and login attempts on the same account are not allowed within 10 seconds, so the issued info cannot be ‘replayed’ by someone sniffing the traffic.

This usage of this AJAX technique and the SHA256 js library ensures that you do not necessarily need SSL in order to perform a hijack-proof login, though of course is not encrypting any subsequent data once logged in without SSL.

The caveat is that the server must have received the user’s password at least at registration and if they submitted a password change, so it would be wise to have this done on SSL-protected pages, or at very least on a trusted network.

I may be forgetting some of the specifics of it as I made it quite a while ago, but I’m sure it could be made even more secure, and perhaps simpler.

Posted by RedScourge on March 30th, 2009 at 4:51 pm:

er…it only posts back the hashed result once

Posted by runxc1 on November 9th, 2009 at 6:38 pm:

I recently wrote about the same subject (CSFR) and I am finding that a lot of people are worried about XSS even though this may be a larger issue.

Posted by Lucinda Peery on May 23rd, 2010 at 2:11 pm:

Yeah, Nice Information. Thx for sharing this 😀

Commenting is disabled for this blog post