OWASP / CheatSheetSeries

The OWASP Cheat Sheet Series was created to provide a concise collection of high value information on specific application security topics.
https://cheatsheetseries.owasp.org
Creative Commons Attribution Share Alike 4.0 International
27.1k stars 3.8k forks source link

Update: CSRF - fix untrue statements #1329

Closed birch-jayton closed 4 months ago

birch-jayton commented 4 months ago

What is missing or needs to be updated?

This statement from the cheat sheet is provably untrue:

By default, browsers do not allow JavaScript to make cross origin requests with custom headers.

Browsers do allow JavaScript to make cross-origin requests with custom headers by default, however, it will be marked as "to be preflighted". This means an OPTIONS request will be sent to confirm CORS compliance. This means that adding customer headers via JavaScript will mitigate CSRF on the condition that the CORS config on the server forbids undesired origins. If the developer believes that browsers don't send cross-site requests with custom headers at all by default, then they are missing a key step in mitigating via custom headers. That is, making sure the server has CORS configured correctly by whitelisting allowed origins.

This statement from the cheat sheet is provably untrue:

Only JavaScript that you serve from your origin can add these headers.

Any JavaScript from any origin can add any custom header. BUT if the request is cross-origin it will be preflighted and the server can deny the request. The server asserting that the custom header is there (as this cheatsheet correctly suggests) guarantees that the CORS check is made by the options request. This is because requests with custom headers ARE ALWAYS marked as prefligthed by the browser. This statement can mislead the reader into thinking that only their trusted clients can send requests with their custom headers. That is not true.

This statement is possibly misleading:

This defense relies on the browser's same-origin policy (SOP) restriction that only JavaScript can be used to add a custom header, and only within its origin.

While only JavaScript can add custom headers (form submissions can not), the statement "only within its origin" isn't necessarily true as I stated above. This defense relies on guaranteeing that incoming requests have been preflighted. Not because JavaScript forbids outside origins from adding the header (which isn't true as I stated above)

How should this be resolved?

These statements should be removed or rewritten. The "Custom Header" mitigation technique is a great and cheap mitigation, however, the cheat sheet should be accurate as to why the mitigation works.

These CheatSheets are a great resource and I am invested in helping. Please allow me to submit a PR. Thanks!

kwwall commented 4 months ago

I'm personally fine with you submitting PRs, but 2 things to concern me here:

  1. Let's call it false or if you prefer, "provably false', but not 'provably untrue'. We don't need doublespeak here; that just confuses things, especially to those for whom English may not be their native language.
  2. Regarding the 2nd false statement that you are attempting to explain, I think there is some ambiguity. You wrote:

    Any JavaScript from any origin can add any custom header. BUT if the request is cross-origin it will be preflighted and the server can deny the request. (Emphasis mine.)

For the 2nd point, I think we need to be more specific. It is not enough to know what z browser is able to do (which essentially the meaning of 'can'_, but that it actually does. And more importantly, is this something that all browsers do or only some them? I'm not trying to split semantic hairs here. We need to understand exactly how browsers operate in this context if they see this and whether or not the all work in an identical fashion. So please address that when you write up the PR.

birch-jayton commented 4 months ago

I'm personally fine with you submitting PRs, but 2 things to concern me here:

  1. Let's call it false or if you prefer, "provably false', but not 'provably untrue'. We don't need doublespeak here; that just confuses things, especially to those for whom English may not be their native language.

  2. Regarding the 2nd false statement that you are attempting to explain, I think there is some ambiguity. You wrote:

Any JavaScript from any origin can add any custom header. BUT if the request is cross-origin it will be preflighted and the server can deny the request. (Emphasis mine.)

For the 2nd point, I think we need to be more specific. It is not enough to know what z browser is able to do (which essentially the meaning of 'can'_, but that it actually does. And more importantly, is this something that all browsers do or only some them? I'm not trying to split semantic hairs here. We need to understand exactly how browsers operate in this context if they see this and whether or not the all work in an identical fashion. So please address that when you write up the PR.

Great points! Thank you! I'll make sure to address that in my PR. Thanks

mackowski commented 4 months ago

Awesome! @birch-jayton I understand that you will cover also #1309 right?