Microsoft has announced that they will be releasing a Chromium based Edge browser.Chromium(in case you did not know) is an open source browser Google developed, Google Chrome is based on Chromium and soon Microsoft Edge will be based on Chromium as well. On theth of August, ********** Microsoft announced a new bug bounty programfor this new Chromium based Edge Browser. The rules of the program state that only Microsoft owned code will be eligible under this bounty. Meaning the attack surface is very small, but to make up for it Microsoft is offering twice the reward (relative to bounty rewards for EdgeHTML). This means a single eligible bug in this new browser could be worth up to $ (*******************************************************************************************************************************************************, 001. In this writeup, I will explain how I managed to earn $ 40, by finding 3 distinct bugs in this new browser. I was also pleasantly surprised to find out that I reported the first valid bug in this program. Here’s how.
New Tab Page (NTP) XSS
The New Tab Page (or NTP) is the first page you see when you open a browser or open a new tab. Of course there are many exceptions to that but I am speaking strictly with default settings. The one thing that is unique about the NTP in the new Edge is that it’s actually an online website located at:'https://ntp.msn.com/edge/ntp?locale=en&dsp=1&sp=Bing'
You see, Firefox has an internal
‘about: home’ / ‘about: newtab’page. Google Chrome has an offline'chrome-search: //local-ntp/local-ntp.html'. All this is important because remember, we are looking for new things Microsoft is doing with Chromium in order to qualify for their bounty. This bug was found completely by mistake. You see, when I first opened the new Edge I never thought much of the NTP. I went straight to features that are truly unique in this Edge (relative to Chromium), one such feature is calledCollections, although at the time it was out of scope and only enabled through flags. I still wanted to see if I can break it for when it will come into scope. Collections are like a more robust and feature-filled bookmark, once you add a website into Collections it will take the title, description and an image and add it and display it in the style of aTwitter card. So one of the tests was to see if once I save a webpage that has a title with HTML tags, will the Collections side bar render the HTML in the title? Answer was no. So after a while I decided to go to bed. The next morning when I opened the new Edge browser for another round, I was greeted with the following NTP:Do you see it? That small, bold, letter 'a'? What happened was, because its a new browser, almost any website I visit will become a 'top site' and included in the NTP top sites section without sanitizing the title. Even better was the fact that nothing was stopping me from executing Javascript, so a simple XSS vector worked. Here is a video of it: **********************)
You may be wondering why this is significant. So what I have XSS on NTP? Well, the NTP is actually a higher privileged page. The way we can test this on Chromium based browsers is by looking inside the
Collections, although at the time it was out of scope and only enabled through flags. I still wanted to see if I can break it for when it will come into scope. Collections are like a more robust and feature-filled bookmark, once you add a website into Collections it will take the title, description and an image and add it and display it in the style of aTwitter card. So one of the tests was to see if once I save a webpage that has a title with HTML tags, will the Collections side bar render the HTML in the title? Answer was no. So after a while I decided to go to bed. The next morning when I opened the new Edge browser for another round, I was greeted with the following NTP:Do you see it? That small, bold, letter 'a'? What happened was, because its a new browser, almost any website I visit will become a 'top site' and included in the NTP top sites section without sanitizing the title. Even better was the fact that nothing was stopping me from executing Javascript, so a simple XSS vector worked. Here is a video of it: **********************)
You may be wondering why this is significant. So what I have XSS on NTP? Well, the NTP is actually a higher privileged page. The way we can test this on Chromium based browsers is by looking inside the‘chrome’Javascript object. Here is a clarifying image comparing the
‘chrome’
object from a normal website with one from the Edge settings page. ) Clearly’edge: // settings / profiles’contains more functions in this object and these extra functions are the high privileged functions we are interested in abusing when we can reach them from normal, non-privileged, web content. So far, we managed to inject Javascript into a higher privileged context from normal web content thus achieving Elevation of Privilege (EoP). Now let’s explore what we can actually do in this privileged context.
EoP to Potential RCE
I got lucky again. Remember that privileged functions can be found within the
‘chrome’
Javascript object. So that’s exactly what I did, I looked for any new objects or functions within the
‘chrome’object in hopes I can abuse one to further exploit this EoP bug. I found an undocumented object at
‘chrome.qbox’
, I could not find any website that discusses it in any detail. I connected that this must be a unique Microsoft object. But what is it? Let’s watch the video: **************************)
I found a peculiar function at
‘chrome.qbox.navigate’
that, through error messages, I found out expects an object of type
‘qbox.NavigationItem’. After a few back and forths, I found out that I can pass a JSON object into this function with this JSON object at least containing a
) ‘url’ and’id’. This is the minimum I needed to make it so it did not throw any errors. ************************** (chrome.qbox.navigate) {id: (0) , url: (********************, ********************************}) ******************
That’s nice, but it did not do anything. I was expecting some sort of popup to appear or new window, anything. But nothing. So I played around with the values of each of
‘id’
and ‘url’
, until finally I executed the following:************************** (chrome.qbox.navigate) {id:
, url: (null) })I execute it and the Chromium Edge browser disappears, I check the crashdump folder and find the following:
************************** ( a4. (c):**************************** (Accessible - code c) ****************************************************************************************************************************************************************************************** ((first / second chance not available) ntdll! NtDelayExecution 0x (**************************************************************************************************************************************************************: ffd`9fddc ****************************************************************************************** c3 ret"Probably a near NULL" I thought. (which means its most likely unexploitable though there are exceptions I believe, no pun intended)
************************** (rax= (ff) ********************************************************************************************* (ba) ****************************************************************************************************** rbx=(**************************************************************************************************************************************************************************** (ff) ******************************************************************************************** (ba) ************************************************************************************************************** (rcx= (ff) ******************************************************************************************** (ba) ***************************************************************************************************************rdx=(rsi=
ds: () ****************************************************************************** (=????????????????) Resetting default scope FAULTING_IP: msedge! ChromeMain e (ffd`) ************************************************************************************* (b) (b) **************************************************************************************************************************************************************************** mov rax, qword ptr [rdx] EXCEPTION_RECORD: (.exr -1) ExceptionAddress: (ffd) ************************************************************************************ (b) (msedge! ChromeMain 0x (********************************************************************************************************************************************************************************* (00) ********************************************************************************************* ExceptionCode: c (Access violation) ExceptionFlags: 000001 00 NumberParameters: 2 Parameter [0]: (******************************************************************************************************************************************************************************** (********************************************************************************************************************************************************************************** 000001 0 Parameter [1]: ffffffffffffffffAttempt to read from address ffffffffffffffffDEFAULT_BUCKET_ID: INVALID_POINTER_READ PROCESS_NAME: msedge.exe ******************
Nope, this looks like an exploitable crash to me. I’m not a memory bug guy, so I had to go re-read theMDN doc on exploitable crashes. I slowly but surely realized what I have found. I played around with the vulnerable privileged
‘qbox.navigate’
function and managed to produce different crash signatures which indicated I most certainly have an exploitable crash (RCE) on my hands, from web! Here is what the semi-final PoC looked like (exploiting the crash is a whole different topic, this just crashes the browser with an exploitable crash for PoC):**************************
**************************************************** (test) ********************q ******************************************************This was confirmed by Microsoft and in fact the past two bugs (XSS and crash) were separated into two bugs and so I got $ (************************************************************************************************************************************************************, ********************************************************************************************************************************************************************************** for one and $ (*******************************************************************************************************************************************************************, ********************************************************************************************************************************************************************************* for the other. So technically I found the first two bugs in the new Edge!
Taking Over The NTP One thing stood out in the previous bugs is that it pretty much relied on XSSing the
'ntp.msn.com'website in order to work from web content. So why not treat
'ntp.msn.com'as a target for some good old web application pentesting. All I needed was an XSS and I would technically have a browser bug since I'm XSSing a privileged page, so I did exactly that. If you visit
and tried to find some bugs on'https://ntp.msn.com/compass/antp?locale=qab&dsp=1&sp=qabzz'
I noticed that it looks sort of like a normal NTP except it does not load properly, this is somewhat expected but important in this exploit. You see, the normal NTP page'https://ntp.msn.com/edge/ntp?locale=en&dsp=1&sp=Bing'
would almost always load using some sort of cache mechanism, even the source code from it is different than the broken one. I ran Burp suite'https://ntp.msn.com/compass/antp? locale=qab & dsp=1 & sp=qabzz '. I ended up finding that if I set a cookie named
'domainId'( shout out to
ParamMiner) then it will be reflected in the broken NTP page (and not the normal NTP page) within a script tag. There is no sanitization as far as quotes go so I was able to inject code using this cookie variable. The great thing about cookies is that you can set cookies that are visible in all subdomains of a given host. So all I need is to find an XSS in any MSN subdomain and I will have the ability to use that to set a cookie and then get JS execution in the broken NTP page. Some reconing and searching later, I was able to find such an XSS within’http://technology.za.msn.com’. This website is now removed because at the time it seemed to be an old forgotten subdomain with very old technologies used. I quickly found out that basically you have to send a speci ally crafted POST request which will result in an error message in this website and within this error it reflects the variable value that resulted in the error without sanitization. The XSS is triggered using the following HTTP request:
************************** POST /pebble.asp?relid=(HTTP / 1.1) Host: technology.za.msn.com User-Agent: Mozilla / 5.0 (Windows NT 0; Win****************************************************************************************************************; x 67; rv: (0) Gecko / (Firefox /) .0 Accept: text / html, application / xhtml xml, application / xml; q=0.9, * / *; q=0.8 Accept-Language: en-US, en; q=0.5 Accept-Encoding: gzip, deflate Content-Type: application / x-www-form-urlencoded Content-Length: 15 Origin: http://technology.za.msn.com Connection: close Referer: http://technology.za.msn.com/pebble.asp?relid=Cookie: PublisherUserProfile=userprofileid=(CC% 2D) **************************************************************************************** (% 2D) **************************************************************************************************************************************** (F9% 2DAE) ****************************************************************************************************************************************************** (% 2D) ******************************************************************************* (E) ******************************************************************************************************** A4; PublisherSession=uid=DIN2DWDWDFWWW7L3OHA5N6; ASPSESSIONIDSCCQSRDS=EOJQQDDFGGGEEPCPNFOBL; _ga=GA1.q. (**********************************************************************. ; _gid=GA1.q. (************************************************************************. ; _gat=1; __utma=2qq (qq6.) ********************************************************************************************************************************************************** (qqqq) **********************************************************************************************. ****************************************************************************************************** (qqqq) *******************************************************************************************. ********************************************************************************** (qqq.qqqqqq) ************************************************************************************************************. 1; __utmb=1. ******************************************************************************************************************************************************************** 21062224016; __utmc=1840897607; __utmz=(****************************************************************************. . 1.1.utmcsr=(direct) | utmccn=(direct) | utmcmd=(none); __utmt=1; __gads=ID=qqqq5dd 2019 qqqb4: T=(**************************************************************************: S=ALNI_MZUnsEhqqqqjxzklxqqqqqJHo1A Upgrade-Insecure-Requests: 1 startnum=80 ‘
********************xss
GIPHY App Key not set. Please check settings