Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CORS: Why there aren't a pre-flight request for POST with Content-Type:text/plain

Tags:

security

cors

After reading a lot about CORS and pre-flight requests I still don't quite get why there are some exceptions for doing a pre-flight. Why does it matter if the Content-Type is 'text/plain' or 'application/json'?

If I get it right, the value of CORS is to restrict the returned data (It doesn't care if the POST destroyed the database, it only cares that the browser can't read the output of that operation). But if that's true (and probably It's not) why there are pre-flight requests at all? Wouldn't suffice to just check for a header like 'Access-Control-Allow-Cross-Origin-Request: true' in the response?

The best answer so far I found in the: CORS - What is the motivation behind introducing preflight requests? question, but it's still a bit confusing for me.

like image 525
Israel Fonseca Avatar asked Sep 14 '16 20:09

Israel Fonseca


1 Answers

Why does it matter if the Content-Type is 'text/plain' or 'application/json'?

The three content types (enctype) supported by a form are as follows:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

If a form is received by a handler on the web server, and it is not one of the above content types then it can be assumed that it was an AJAX request that sent the form, and not an HTML <form /> tag.

Therefore, if an existing pre-CORS system is using the content type as a method of ensuring that the request is not cross-site in order to prevent Cross-Site Request Forgery (CSRF), then the authors of the CORS spec did not want to introduce any new security vulnerabilities into existing websites. They did this by insisting such requests initiate a preflight to ensure both the browser and the server are CORS compatible first.

It doesn't care if the POST destroyed the database, it only cares that the browser can't read the output of that operation

Exactly right. By default browsers obey the Same Origin Policy. CORS relaxes this restriction, allowing another Origin to read responses from it made by AJAX.

why there are pre-flight requests at all?

As said, to ensure that both client and server are CORS compatible and it is not just an HTML form being sent that has always been able to be submitted cross domain.

e.g. this has always worked. A form on example.com POSTing to example.org:

<form method="post" action="//example.org/handler.php" />

Wouldn't suffice to just check for a header like 'Access-Control-Allow-Cross-Origin-Request: true' in the response?

Because of the CSRF vector. By checking that the browser can send a preflight, it ensures that the cross-origin request is authorised before the browser will send it (by examining CORS response headers). This enables the browser to protect the current user's session - remember that the attacker here is not the one running the browser, the victim is running the browser in a CSRF attack, therefore a manipulated browser that doesn't properly check CORS headers or spoofs a preflight would be of no advantage for an attacker to run themselves. Similarly, the preflight enables CSRF mitigations such as custom headers to work.

To summerise:

HTML form cross-origin

  • Can only be sent with certain enctype's
  • Cannot have custom headers
  • Browser will just send it without preflight because everything about a <form> submission will be standard (or "simple" as CORS puts it)
  • If server handler receives a request from such a form it will act upon it

AJAX cross-origin

  • Only possible via CORS
  • Early version of some browsers, like IE 8 & 9 could send cross-origin requests, but not with non-standard headers or enctype's
  • Can have custom headers and enctype's in fully supported browsers
  • In order to ensure that a cross-origin AJAX request is not spoofing a same-origin AJAX request (remember that cross-origin didn't used to be possible), if the AJAX request is not simple then the browser will send a preflight to ensure this is allowed
  • If server handler receives a request it will act upon it, but only if it has passed preflight checks because the initial request will be made with the OPTIONS verb and not until the browser agrees that the server is talking CORS will it send the actual GET or POST
like image 107
SilverlightFox Avatar answered Sep 25 '22 19:09

SilverlightFox