I'm currently working on a PoC for a CSRF attack, which should be possible due to the lax CORS configuration. I have a permission to attack.

Now the following code should send a OPTIONS request, which includes all the details required by the browser to send the actual CSRF.


    function createCORSRequest(method, url){
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr){
        xhr.open(method, url, true);
    } else if (typeof XDomainRequest != "undefined"){
        xhr = new XDomainRequest();
        xhr.open(method, url);
    } else {
        xhr = null;
    return xhr;

    var url = 'https://api.example.com/path';
    var xhr = createCORSRequest('POST', url);
    xhr.withCredentials = true;
    xhr.setRequestHeader('Content-Type', "application/json");


The browser sends a OPTIONS request and the server answers accordingly:

OPTIONS request:

OPTIONS /path HTTP/1.1
Host: api.example.com
User-Agent: Agent
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
origin: null
Connection: close
Cache-Control: max-age=0


HTTP/1.1 200 OK
Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, PATCH, DELETE
Access-Control-Allow-Origin: *
Date: Fri, 21 Sep 2018 07:25:06 GMT
Content-Length: 0
Connection: close

But the actual POST request is never sent. I'm not very good with JS and stitched the XHR part together from different StackExchange posts. A variation of this worked for me for a different web-application.

Why doesn't the browser send the CSRF POST request?

  • 3
    Credentialed requests aren't permitted with wildcard values for the Access-Control-Allow-Origin header, regardless of what other headers are provided. See developer.mozilla.org/en-US/docs/Web/HTTP/CORS for the details of that. – Matthew Sep 21 '18 at 8:05
  • Right @Matthew, thanks for the comment! If the Access-Control-Allow-Origin would specify the attackers domain, this would fail anyways as the Access-Control-Allow-Credentials header isn't set in the OPTIONS response, correct? – SaAtomic Sep 21 '18 at 8:18

I've identified the issue. The CORS settings don't allow "withCredentials" as the server doesn't respond with Access-Control-Allow-Credentials: true, which is why the POST request isn't made.

Furthermore, as stated by @Matthew, with a wildcard for Access-Control-Allow-Origin, the Authorization header can't be sent.

  • One option might be to see if you can send a request with credentials that won’t get preflighted. – user18519 Sep 21 '18 at 11:55
  • @user18519 what do you mean? If I make an xhr with custom header a preflight request will be made. The point is that the page uses the authorization header, which requires the Access-Control-Allow-Credentials response header and a specific origin. – SaAtomic Sep 21 '18 at 12:29
  • I don’t believe Authorization counts as a custom header. I see that you’re setting the content-type though. Does the server require it? Often they parse it as json no matter what you put. – user18519 Sep 21 '18 at 12:31
  • @user18519 The Content-Type is fine. The browser sends the defined Content-Type after the preflight request, just not with xhr.withCredentials = true;. Which I'd require, as the Authorization header is used. – SaAtomic Sep 21 '18 at 12:33
  • I would reread the documentation on allow-credentials. I know it’s possible to send with credentials and without it preflighting. – user18519 Sep 21 '18 at 12:39

The attack is possible , you do not need CORS and you do not need XHR to exploit , try the tricky json CSRF via swf file.


  • Thanks for the response! I'm trying to create a PoC .swf for the application. The swf doesn't send the Authorization header, right? or am I missing something? – SaAtomic Sep 21 '18 at 9:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.