Hacker & Security Analyst at HackerOne

CORS Exploitation: Data exfiltration when allowed origin is set to NULL

septembre 15, 2017Yassine ABOUKIR1 Comment

The present article will be discussing a particular case regarding exploitation of CORS misconfigurations which I stumbled across during a security audit so I had to dig and research about it in order to finalize a working proof of concept for the client. If you do not have knowledge in this matter I would advise you to read first my previous article in this regards that you can find here.

Each time we test for CORS security flaws we usually fuzz the Origin header in the HTTP request and then inspect the server response to see if they does domains whitelist check or not, otherwise cross-domain requests would have been allowed from any origin, thus opening them to content exfiltration attacks.

In a typical test, this would look something like:

GET /apiakey HTTP/1.1

Host: example.com

Origin: evil.com

Connection: close


HTTP/1.1 200 OK

Access-control-allow-credentials: true
Access-control-allow-origin: evil.com

Above response indicates that evil.com has full access to authenticated content. A hacker would then simply send a cross-domain request from evil.com to exfiltrate the APIKey as a result.

However, our particular situation is when you change the origin header similar to the above example but the allowed origin as stated in the response would be different. See:

GET /apiakey HTTP/1.1

Host: example.com

Origin: evil.com

Connection: close


HTTP/1.1 200 OK

Access-control-allow-credentials: true
Access-control-allow-origin: null


If you carefully noticed, this time our origin was not reflected back in the whitelisted origins so we instead got : null.

Exploiting this particular one is not straightforward and pretty tricky because sending null in the origin header is not practically possible except in two instances:

The request is issued from a file on a user’s computer rather than from a hosted web page which is not very helpful in our case since an attacker would need to upload the exploit page to a server he owns and send out the link to the victim.


If a cross-origin resource redirects to another resource at a new origin, the browser will set the value of the Origin header to null after redirecting.

We are interested in the latter. Let us break down the statement for clarification purpose:

Attacker.com sends cross-domain request to http://www.attacker.com/302.php

302.php has whitelisted the attacker and then responds with Temporary Redirection 302 to http://www.example.com/apikey

Cross-domain request from Attacker.com follows the redirect to example.com and sets Origin to null.

Last thing we know, our targeted APIkey will be extracted from the victim’s end and sent back to http://www.attacker.com

Briefly, exploiting similar situations requires passing through a 302 redirection in order to set Origin as null. I hope reading this short article was valuable and helpful to you and if you have any feedback please feel free to express yourself in a comment.

UPDATE: It appears there is as well another way around this particular situation thanks to a friend of mine Arbaz Hussain. It is quite simple and easy than the one I described above. Exploitation would be using an iframe combined with data: just as follows:

This is a pretty cool trick and it does not require much of an effort to carry out. I knew it works for disabling referer header but I had not idea it could work in the case of Origin. It’s not until I published the article that Arbaz reached out to me to share his knowledge, so please feel free to post any feedback or additional information you have below.






This article has one Comment
  1. Hussam
    26 août 2018

    Salam Yassine,
    it is weird that the first method is not working,
    I read a few resources on setting null origins when following redirects,
    but both chrome and firefox are setting the right origin.

    do you see the same thing or it is just me?


Leave a Reply

Prove you are not a Bot * Le temps imparti est dépassé. Merci de saisir de nouveau le CAPTCHA.