Is checking the referrer enough to protect against a cross site request forgery attack? I know the referrer can be spoofed, but is there any way for the attacker to do that FOR the client? I know tokens are the norm, but would this work?
Is checking the referrer enough to protect against a cross site request forgery attack? I know the referrer can be spoofed, but is there any way for the attacker to do that FOR the client? I know tokens are the norm, but would this work?
Yes it is. if you take some precautions.
This is a 12 years old question which is first result to appear so i'm going to answer it. in this 12 years things has changed a lot. so while it could have been a poor choice back then, now it's an easy to implement and a reliable solution.
Main source of doubt about using referrer was if there was no referrer header in the request. this can happen in multiple occasions like attacker omitting referrer, requesting from a secure page to an insecure one, Proxies or users omitting it by choice or omitting it by meta tags.
in all cases above you should strictly ignore and fail requests without a valid referrer. it's obvious why you should fail when attacker omits the header and you can simply not omit it in meta tags in your page. if user decides to omit it by choice, well it's their choice and it will break functionality, just the way disabling cookies or javascript would break most websites.
Sending request from a secure page to an insecure one is not a big deal either. because in this 12 years. web has changed a lot and most websites don't need to deal with insecure endpoints at all actually if you do, you wont have that assuring lock logo appearing in the address bar.
Talking about secure endpoints, there is no worry about proxies or ISPs omitting the header either, because whole request including headers is encrypted and interceptors simply cant check headers let alone modify them unless they have access to user's device which overall makes it a very rare case.
But cant referrer be faked ?
Faking a referrer is a both easy and hard thing to do. it's feasibility depends on who you trust in the process. lets consider this awful strategy:
User logs in to website example.com and example.com/login checks if user is a valid user and then redirects user to example.com/sensitive, the example.com/sensitive page then evaluates referrer and if it is from example.com/login, prints sensitive data. this is awful because user can easily fake the referrer on his/her own browser. but whole idea of protection against CSRF attack is not for cases when you don't trust the user. it's for when you don't trust the request to be genuinely sent from the user. which means in order to fake the referrer the attacker needs to somehow modify user's device and honestly if the attacker has that access they wont bother with sending third-party requests after all.
So, nothing to worry about ? Almost.
there are two tricky situations with easy solutions that comes to mind.
A. not checking the referrer properly. what it means ? assuming that your domain is example.com and you are just checking whether example.com exists in referrer string or not. then you can falsely consider example.com.evil.com as a genuine request. the solution is to check for example.com/ in SERVER_NAME which includes your domain no the whole address. (i checked this in my local PHP server and worked fine. you might need to test with your own environment and find another solution if this is not applicable)
B. Taking into account redirects from your own website. if your website has an endpoint to redirect to external resources like this : example.com/redirect?url=extenal.com
an attacker can exploit it and make requests like this example.com/redirect?url=example.com/sensitive
to solve this problem it's better not to change state (modifying database records, etc) with GET requests. as precautions you can also check if the request is from your redirect endpoint or not and also not to redirect to your own domain in your redirect endpoint.