Exploit Archeology – Exploiting an old unknown Server Side Browser


I was recently hacking on a Bug Bounty target and identified an interesting API endpoint which would render user supplied HTML, and execute any included JavaScript. Exploiting Server Side Browser bugs has been a focus of mine for the past couple of years, so I set out to exploit this newly identified feature. This blog post details my journey into researching and exploiting what turned out to be a decade old Server Side Browser.

The first step was to identify the Browser engine and version in use, this is usually a pretty simple task, of checking the User-Agent header of requests for external resources. So I sent an HTML payload into the target service with an img tag loading an image from a server I control (Side note: I use https://github.com/ajxchapman/reserv for all my server request bug hunting). This revealed the User-Agent of:

Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) Safari/538.1

… which is really not very helpful. You’d usually expect to see a Chrome/124.0.0.0, Firefox/125.0, or similar in there at least somewhere, which can disclose the Browser engine and version. No such luck here.

However, since I had JavaScript execution, I could concretely identify the Engine through browser specific APIs, e.g Error.captureStackTrace for Chrome, document.preferredStyleSheetSet for Firefox, and webkitConvertPointFromPageToNode for WebKit (Safari). In this case it appeared to be a WebKit based Engine.

From this, my first (and as it turned out, first incorrect) assumption was it was probably PhantomJS. I’d previously written an exploit for CVE-2014-1303, so packaged that up and sent it into the HTML service. No result… although I tried to two or three (or seven) more times just to be safe.

Begrudgingly accepting that it wasn’t PhantomJS, I set out to work out what approximate version of WebKit it was running. To do this, the Browser Comparison feature of caniuse.com came in really handy. Selecting several Safari versions, I could easily compare the feature support for each version:

There are some discrepancies with the data from caniuse.com and MDN, using both of these sources a basic script could be created to determine the rough version of WebKit in use:

var version;
version = !version && typeof fetch == "function" ? "Safari WebKit 10.1" : version;
version = !version && typeof String.prototype.includes == "function" ? "Safari WebKit 9" : version;
version = !version && typeof document.currentScript == "object" ? "Safari WebKit 8" : version;
version = !version && typeof window.requestAnimationFrame == "function" ? "Safari WebKit 7" : version;

console.log(version);

This revealed that the service was using WebKit that corresponds to Safari ~8, with an absolute date circa 2014 to 2015. Yes, nearly a decade old! Time to get my hands dirty and dust off my vulnerability excavation tools.

Now that an approximate WebKit version and code development timeframe was known, I could go digging for old vulnerability reports, PoCs and exploits. Searches for WebKit vulnerabilities around that time came up with a lot of results for Sony PlayStation Jailbreaks. PS Vita had been released in 2011, and PS4 in 2013, and a common entrypoint to Jailbreaking these devices was WebKit. This was great news for me, as there were a fair number of PS Jailbreaks exploiting WebKit versions from around the time I was looking.

Hours of reading various Jailbreaking community sites, forums, wikis and GitHub repositories revealed several viable vulnerability candidates, from authors with names such as qwertyoruiop, Fire30 and RKX1209. Unfortunately for me, most of these main characters in the ~2015 PS Jailbreak scene were fond of writing illegible exploits, using minimal (and sometimes downright incomprehensible) comments and undefined static offsets all over the place. Some of the code was truely from another era.

I eventually unearthed one viable looking exploit with a clear writeup by a hacker known as xyz. The exploit targeted a Use After Free (UaF) vulnerability in the WebKit JSArray::sortCompactedVector function. Further searching did not identify a CVE related to this issue though, so I approached with some trepidation.

The JSArray::sortCompactedVector exploit writeup from xyz included a basic PoC, which could be used to confirm whether the target service was vulnerable or not:

var almost_oversize = 0x3000;
var foo = Array.prototype.constructor.apply(null, new Array(almost_oversize));
var o = {};
o.toString = function () { foo.push(12345); return ""; }
foo[0] = 1;
foo[1] = 0;
foo[2] = o;
foo.sort();

So I batched this up in a



Source link