Why bother requiring CSRF token on POST requests? - security

My understanding is that CSRF prevents an attacker using an <img> tag to get the victim's browser to send a request that would be authenticated using the session cookie. Given that <img>s are always submitted using a GET request, not POST, then why is it necessary to require a CSRF token in a POST request?
Also, the attacker wouldn't be able to submit a form in the webpage without being able to run code (ie. an XSS attack), in which case they can circumvent your CSRF protections anyway.

The attacker can host a form on their own site, but it does not require the form to be submitted by the user. They can use JavaScript to do this:
<form method="post" action="http://www.example.com/executeAction">
<input type="hidden" name="action" value="deleteAllUsers">
</form>
<script>document.forms[0].submit()</script>
IFrame injection is more of a XSS vulnerability. A XSS vulnerability is more serious than a CSRF one because more damage can be done and it will always override any CSRF protection you have. Make sure you are always correctly encoding output for the context that the output is in (e.g. encode for HTML or for JavaScript as appropriate).
Check out the Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet - their best recommendation is to use the Synchronizer Token Pattern which seems similar to the link in your answer but can work in combination with cookies.
Also, here's a link to the XSS (Cross Site Scripting) Prevention Cheat Sheet.

Cross Site Request Forgery is when a site (let's say evil.example.com) can force a visiting user to make requests to another site (let's say example.com). It's not really forcing a user since embedding a image that (HTTP GET request) or POST request via form submission or javascript is not that difficult.
You should not make state or data changes via HTTP GET requests. img tags (get request) shouldn't be able to make any kind of change what so ever. If you allow this ... stop it. :)
POST requests need to contain a value that is not guessable by a remote attacker. Typically this is a per request random value.
So yes, CSRF is a a demonstrated, known vulnerability that you should bother protecting against.

Having done some further investigation:
It's possible for the attacker to host a <form> on their own site which submits to the target site (your site). All they need to do is get the victim to submit this form and it'll be submitted with their cookies and potentially their authentication.
It's also possible for the attacker to inject an <iframe> into your site, which would then be able to display this malicious <form>.
I'm thinking that a token-based approach is a better solution for my use case.

Related

Difference between CSRF and HPP (HTTP Parameter Pollution)?

I went through this link to understand about HPP (HTTP Parameter Pollution) attacks.
In HPP attacks it seems like, attacker modifies the HTTP parameters and sends the modified URL to the victim. Isn't this same as CSRF attacks? If not can somebody tell me what is the difference between CSRF & HPP?
HTTP Parameter Pollution is when your application makes a back-end HTTP request to another system and these parameters can be manipulated by input into your main application. HPP is defined by the fact the attacker causes a duplicate parameter name to be passed to the back-end request, which overrides the parameter value being explicitly passed by the application. A similar vulnerability, HTTP Parameter Injection is defined by the attacker adding a new parameter to the back-end request which is interpreted by the other system. So HPI causes a new parameter to be added, whereas HPP causes an existing parameter to be ignored or interpreted in a new way.
See my answer here for a solid example of HPP.
CSRF doesn't require any back-end HTTP request. This is a front-end request, but made by the victim without their knowledge. It basically means that a malicious request is made using the victim's browser and the victim's authorisation cookies. It could be as simple as a hidden image on the attacker's page:
<img src="https://bank.example.com/transfer_money?toAmount=999&toAccount=12345678" />
This will be triggered whenever the victim visits the attacker's page (e.g. following a link emailed to them, or something posted on a forum).
See my answer here for another example using the POST method.
Sometimes a HPP vulnerability can be exploited via CSRF. For example, one that requires the victim to be the one logged into the system that is exploitable via HPP. e.g. the POST to https://www.example.com/transferMoney.php could be made by the attacker's site, passing the toAccount=9876 POST parameter causing the victim to transfer money to an unauthorised account using their autorisation cookie for www.example.com.
Regarding the article in your question, I don't think that is a realistic HPP attack because any actions that cause a state change should be implemented via the POST method and not a GET link as the article demonstrates, so you wouldn't actually get an action link being constructed from the current page (but hey, anything is possible). This is why HPP is really more around back-end requests in practice.
From what the linked article describes, it seems that HPP is a specific type of injection attack, where you modify the request parameters in order to modify the contents of the returned page. In a sense, its a more generalized version of a reflected XSS attack; whereas with XSS you are attempting to inject and execute malicious javascript through tampering with a request, in HPP you are trying to modify any data (in the example given, data used to generate URLs) to inject malicious data.
The term CSRF, however, is usually used to describe an attack where an entirely valid request is sent to a server in a context that leads to unexpected or unwanted behavior. The somewhat standard example would be tricking a user into clicking a link on your site, which sends a request to the user's banking site (as the user) to transfer money from their account to yours.
There is nothing preventing an attacker from using a HPP or XSS attack with a CSRF attack. An XSS or HPP attack takes advantage of a lack of validation in the processing of user input that is later returned as part of a response, while a CSRF attack takes advantage of "sequence breaking" in application flow to cause unintended behavior.

are precautions against CSRF needed for view-only pages?

All the examples of CSRF exploits tend to be against pages which process the incoming request.
If the page doesn't have a form processing aspect do I need to worry about CSRF ?
The situation I'm looking # :
the page in question contains sensitive data
as such users need to establish a session to view the page
... my understanding is that a malicious page will be able to redirect a client to this page by embedding a link to it, however since there's no action on the target to perform there's no harm that can result, right ?
There's no way for said malicious site can view the sensitive page, correct ?
Why I ask: I want the url to the page with sensitive data to have a 'simple' URL which allows people to email the link to other people (who will in turn need a session to view the page). The token-based solution I've seen for most CSRF solutions remove this possibility, and so I'd like to avoid them if possible.
There's no way for said malicious site can view the sensitive page, correct ?
Correct in terms of CSRF.
The blog you linked is talking about Cross-Origin Script Inclusion, which is a different animal. To be vulnerable to XOSI your sensitive page would have to be interpretable as JavaScript, and you'd have to be either serving it without a proper HTML MIME type, or the browser would have to be an old one that didn't enforce type checking on scripts.
You might also potentially worry about clickjacking, where another site includes yours in a frame and overlays misleading UI elements. There are some sneaky ways that has been used to extract sensitive data (see the next generation clickjacking paper and this amusing info leak in Firefox) so you may wish to disallow framing with the X-Frame-Options header.
Why I ask: I want the url to the page with sensitive data to have a 'simple' URL which allows people to email the link to other people (who will in turn need a session to view the page). The token-based solution I've seen for most CSRF solutions remove this possibility
You definitely shouldn't be putting a CSRF token in a GET URL. Apart from the ugliness, and breakage of navigation, URLs are easy to leak from the browser or other infrastructure, potentially compromising the confidentiality of the token.
Normal practice is not to put CSRF protection on side-effect-free actions.
In general, CSRF is independent from whether the request causes any side effects or not. The CWE describes CSRF (CWE-352) as follows:
The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
So CSRF is a general request intention authenticity problem.
However, although CSRF is not really feasible without any effects other than data retrieval as the same-origin policy restricts the attacker from accessing the response, the attacker could exploit another vulnerability to profit from retrieval-only requests as well and gain access to sensitive data.

Synchronizer token pattern: How does it prevent combination of XSS and CSRF?

I have been looking into the OWASP recommendation to prevent CSRF attacks (https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet).
Now, what I do not understand is how this would prevent an attack that is a combination of an XSS and a CSRF attack. Let's say we have the following attack scenario:
Attacker is able to perform a stored XSS attack, so that the script that the attacker inserts on the website is executed everytime a user visits the page.
This script will completely redesign the DOM, for example instead of the original form where a user needs to give some irrelevant information, the attacker's script redesigns it so that this form will be redesigned to a form where a user with admin privileges is added. Note that the user will not see this, as the labels of the fields will remain the same. Only the POST will be different.
The attacker knows that this website uses anti-CSRF tokens. Looking at the OWASP recommendation: '(..)application should include a hidden input parameter with a common name such as "CSRFToken"', the attacker knows that most websites will have a hidden field with this id somewhere on the page.
the attacker makes sure the value of this field is also submitted in the fake POST. Even though the attacker doesn't know the value of this hidden field, it can specify in the POST that this value should be sent with the request. This is possible, as the user's DOM has been modified, the request will come from the user's browser, the user's cookies will also be sent with the request.
The user submits the form, and the fake user is created.
It seems to me this cannot be prevented by just using a CSRF token. Or is an implicit assumption of the synchronizer pattern that XSS attacks have been neutralized?
Or is an implicit assumption of the synchronizer pattern that XSS attacks have been neutralized?
Yes. If your website is attacked in this way then it is an XSS attack rather than CSRF. CSRF simply means the request is made "cross site", whereas in your example the request is on the same site - it is just the scripting that is "cross site".

what's the scenario of stealing information with XSS on a POST request

I understand the scenario of stealing information with XSS on a GET post as below workflow:
Hacker identifies a page from a web application with vulnerability of being XSS injected through query string parameters.
Hacker composes a url with XSS injected query string appended.
Hacker sends the url to a victim, for example, by email.
Victim receives the mail and clicks on the url (suppose the victim has less knowledge of security).
The opened web page has XSS injected, any further action on the page could result in a security issue.
This is possible because clicking on the url link will open the web page in GET mode. So, I am wondering if the page is XSS vulnerable for POST request, will it be a security issue? I could not figure out a "reasonable" attack workflow.
So, I am wondering if the page is XSS vulnerable for POST request, will it be a security issue?
Of course it would be. Why should the method via which external code is embedded matter at all? That it does happen is the problem, not how.
I could not figure out a "reasonable" attack workflow.
Consider a simple HTML form, that gets pre-populated with the previous user input after a failed server-side validation.
If this pre-popuplating allows XSS (basically meaning, escaping all data before outputting it in an HTML context was neglected) – then I could easily set up a form in my own page, have its action attribute point to your form handling address, and pass any data I like via hidden fields – and have to user send that data to your server via a simple submit button, that is maybe formated to look just like a normal link, and only saying “click here to go to example.com”. The user expects that to just ”normally” open a page like any other link – but in reality it send values that triggers displaying the form with pre-populated fields again.
Et voilà, XSS attack successfully performed.
(All that under the premise that the target site does not have additional security against “foreign” form data in place.)
The attacker could also build a 'data:' URL containing an auto-submitting form:
data:text/html;base64,PGh0bWw+CiAgPGJvZHkgb25sb2FkPSJkb2N1bWVudC5mb3Jtc1swXS5zdWJtaXQoKSI+CiAgICA8Zm9ybSBtZXRob2Q9InBvc3QiIGFjdGlvbj0iaHR0cDovL2xvY2FsaG9zdCI+CiAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9ImVybnN0IiB2YWx1ZT0iPHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4iPgogICAgPC9mb3JtPgo8L2h0bWw+
which is equivalent to navigating to a page containing this markup:
<html>
<body onload="document.forms[0].submit()">
<form method="post" action="...">
<input type="hidden" name="ernst" value="<script>alert('XSS')</script>">
</form>
</html>
Just went through this exact issue while performing a penetration test for a client. When reporting, we usually try to show a proof of concept exploit using a GET request as this is much easier. Remember too that some servers may allow you to change a POST to a GET request. Some servers will also accept POST parameter values in a URL. In my most recent experience, the server would only accept a request as a POST with the input entered into the form fields. The only thing that stopped an XSS attack was the fact that they had Cross Site Request Forgery prevention in place (via ViewState). So, in this case, it is simply a reflection fault. Still not good, but not as bad. You should ALWAYS use both ingress and egress filtering and NEVER trust user-controllable data.

XSS as attack vector even if XSS data not stored?

I have a question about XSS
Can forms be used as a vector for XSS even if the data is not stored in the database and used at a later point?
i.e. in php the code would be this:
<form input="text" value="<?= #$_POST['my_field'] ?>" name='my_field'>
Showing an alert box (demonstrate that JS can be run) on your own browser is trivial with the code above. But is this exploitable across browsers as well?
The only scenario I see is where you trick someone into visiting a certain page, i.e. a combination of CSRF and XSS.
"Stored in a database and used at a later point": the scenario I understand about CSS is where you're able to post data to a site that runs JavaScript and is shown on a page in a browser that has greater/different privileges than your own.
But, to be clear, this is not wat I'm talking about above.
Yes, it's still an attack vector.
What you need to consider is:
Can an authenticated user be tricked into viewing this page with maliciously-crafted data?
The answer is this case is yes (assuming you have authenticated users). Because it's possible to direct someone to your site and pass in malicious variables to that field.
Yeah, it's still an attack vector, although impact is more situational.
Here's a contrived scenario that expands on previous answers if the form requires authentication to reach (and is easier if the site doesn't care if forms are submitted via POST or GET):
1) Attacker uses CSRF to login the victim using the attacker's credentials (e.g. <iframe src=http://../login?id=...&pass=..."></iframe>). This way the attacker brings the form to the victim and it doesn't matter if the victim doesn't have an account.
2) Attacker uses another CSRF to execute XSS against the form, which asks the victim for some credentials, etc. (This is where some convincing social engineering needs to occurr or the attacker has some useful JavaScript to use within the browser's Same Origin for the site.)
Another contrived scenario in which the vulnerable form performs some important action, like transfer money between accounts:
0) Vulnerable form uses hidden form fields with random values to prevent CSRF. The attacker doesn't know what the values are and can't set up a proper attack.
1) Attacker creates a CSRF payload that includes JavaScript to read a form's random csrf tokens (i.e. pull them from the browser's DOM).
2) Victim logs into site.
3) Attacker lures victim to CSRF payload, CSRF bootstraps the form request with the correct csrf tokens because it's executing in the victim's browser, within the victim site's Same Origin, and using the victim's auth session. The attacker doesn't need to know the csrf tokens, just be able to manipulate the form fields that store them.
4) Attacker benefits from having the victim submit the form -- no pop-ups or social engineering necessary aside from luring the victim to the CSRF payload, but the form needs to do something "useful" for the attacker.
i think what you are mean is, since User 2 cannot be showing previous data added by User 1, so can the XSS happen? So if User 1 hack the URL so that some $_GET params got displayed on the webpage as well (and then even, change it to a tinyurl), and spread this URL saying that it is really worthwhile to see this page, etc, then it might be possible.
So it is still better to escape all params when displaying the page.
That is absolutely a valid form of XSS. XSS comes in two forms - stored and reflected. Reflected is much more common, but stored has the potential to be more damaging. Reflected XSS is usually used as part of a social engineering attack. An attacker creates a URL like the following:
http://host.com/page.php?my_field=malicious_code
They will often shorten the URL with tinyutl or bit.ly, and get it out with the usual social engineering methods (email, message board, twitter, hijacked facebook accounts, etc.)

Resources