I was pentesting a Json Rest API today; the API needs a specific header to be sent:- Content-Type: application/json which doesn't allow CSRF attacks.

The only option I was left with was sending cross domain requests since there is no CORS policy set. However while trying sending xhr POSTs with the "content-type" header the browser sends OPTIONS request to the endpoint and triggers a 403 disallowing to POST. I've tried bypassing this using plain/text and other headers but none of them seems to work.

Do you have any ideas on how to proceed on this? I've heard that sending the same via an SWF file would work but have to try it out.

  • crossdomain.xml can stop flash-based cross-domain leakage
    – dandavis
    Apr 17, 2017 at 22:30
  • This SO answer has a very interesting flowchart diagram on how browser decide to do a pre-flight POST stackoverflow.com/a/29954326/204634
    – lorenzog
    Apr 18, 2017 at 12:50

1 Answer 1


You can use the following content types without CORS access:

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

You can try a couple of things:

  • Try sending valid JSON with another content type. Some implementations don't look at the content type.
  • Try sending valid form data with the correct content type. Some implementations accept multiple ways to send the data.

If the application really needs the application/json content type, it is not possible to send a cross-origin request.

  • Thanks @sjoerd , will look into it, I have a silly doubt here, why is the browser only protecting content-type application/json and triggering OPTIONS only on json and why not for other headers like application/x-www-form-urlencoded , does that mean the browser only protects JSON APIS from CORS attacks and not normal Web app Post request ?
    – StackB00m
    Apr 17, 2017 at 20:18
  • 1
    @StackB00m: Basically request that cannot be made via a FORM tag are protected by OPTIONS - i.e. those that were possible cross-domain before CORS. See this answer for more details. Apr 17, 2017 at 21:28
  • note that those requests can only arrive; they cannot transmit any response to JS without CORS, just like a hidden form tag.
    – dandavis
    Apr 17, 2017 at 22:01
  • Another trick is to smuggle the content type expected by the server in the MIME type parameters, e.g. text/plain; application/json and hope that the server only checks that the request's content type contains the expected content type. More about this trick elsewhere.
    – jub0bs
    Dec 31, 2021 at 11:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .