accepted fixed
reward decided
$5,000
reward decided
$5,000
Hello Google VRP, Thanks for BugSWAT/hofplz! :)
I just got back home and I have an XSS on Gmail to report! The XSS has some limitations: it is blocked by CSP on Chrome/Firefox (but not Edge/IE11) and it requires to predict or access a window.random() value.
POC link: https://opnsec.com/google/gmail.html
Steps to reproduce: Open the POC link in Edge/IE11 (or Chrome/Firefox, the CSP logs will show the blocked XSS) and follow the instructions:
Click to Open Gmail in new window
Open the dev console (F12) in the Gmail window and enter:
addEventListener("message",function(e){console.log(e.data)})
In the console logs, you will see many messages similar to this:
[CHANNEL_NAME]|c:[[["h_h",true,null,true,true]],null]
or
[CHANNEL_NAME]|cp:[[["h_chm","preld","https://hangouts.google.com/webchat/u/0/frame...#epreld"]],null]
where [CHANNEL_NAME]
is a 6 (or 5) alphanumeric random value. (You will also see similar message with a longer [CHANNEL_NAME] but use only the 6 or 5 chars [CHANNEL_NAME])
Copy the [CHANNEL_NAME] value
Paste the channel value in the POC page
Click to send a postMessage to the Gmail window
The XSS executes on https://mail.google.com/ (If not, check the console log where you should see that CSP prevented an iframe to load with a "javascript:" src.)
Browser/OS: Tested on Edge/IE11 on Windows 10 (and on Chrome/Firefox but blocked by CSP)
Technical details:
The basis of this vulnerability is that https://mail.google.com/mail/u/0/#inbox loads an iframe at https://hangouts.google.com/webchat/u/0/load named "gtn-roster-iframe-id". The Hangouts iframe then sends a postMessage to the main window mail.google.com with a URL, and mail.google.com loads that URL in another iframe. mail.google.com doesn't check if the URL contains a javascript handler. In addition, mail.google.com doesn't check the message origin or source. That means that any window/iframe can send arbitrary javascript/data handlers URL by postMessage to the mail.google.com page to execute XSS. This is blocked by CSP rules "script-src nonce" and "frame-src". However, this is not blocked by Edge/IE11 and, anyway, who would want to rely on CSP for the security of its website! ;-)
There is another problem: when mail.google.com loads the "gtn-roster-iframe", mail.google.com generates a random Channel name of 6 or 5 chars and shares it with "gtn-roster-iframe" by postMessage to distinguish messages of this channel from other postMessages with other iframes. Brute-forcing the 6/5 chars value seems not realistic because the postMessage api seems not fast enough (around 1ms from what I read). This random number is generated using Math.random(), which is not a crypto secure random generator, is not protected against crypto attacks and should not be used for security. This means that an attacker could potentially predict the value of Math.random() and then use it for the XSS injection (for example: http://ifsec.blogspot.com/2012/09/of-html5-security-cross-domain.html). My understanding is that to do this, an attacker should 1. test Math.random() on its domain to learn the state of the seed, 2. predict the next state of the seed, 3. open the mail.google.com window and predict the value of Math.random().
There is another way to get the random value. The mail.google.com regularly sends the random value to the "gtn-roster-iframe" by postMessage using "*" as target. This means that if an attacker can redirect the "gtn-roster-iframe" to his own domain, he will have access to the random value with the postMessages sent by mail.google.com, without cracking the Math.random() function. To redirect the "gtn-roster-iframe", the attacker needs to have an iframe in the parent hierarchy of the "gtn-roster-iframe". The mail.google.com window has "x-frame-options: SAMEORIGIN". This means that if we can control any iframe embed in mail.google.com, we could embed the gmail inbox page in our iframe, then redirect the "gtn-roster-iframe" to our domain, access the channel random value and send the postMessage with XSS payload. I didn't find a way to control an iframe in mail.google.com. However, the beta "AMP4email" features might be interesting, potentially allowing this XSS to be sent by email, and I would love to test this feature in advance!
Some Source code snippets: generates the random channel name:
d.cn = Math.floor(2147483648 * Math.random()).toString(36);
https://hangouts.google.com/_/scs/chat-static/_/js/k=chat.smh.en_US.0f_8uxbjzhI.O/am=DA/rt=j/d=0/rs=AGNGyv2x37Hc72SqLZJ2az5GSiqA9HacTA/m=b
loads the iframe URL sent by postMessage
this.Ea("mc").appendChild(this.Ca.Ea());
https://mail.google.com/_/scs/mail-static/_/js/k=gmail.main.en.iWSjMX4rTqI.O/am=_p8Qw3hA_r7P8TGctzECHA6GojAA7P-PII_Kvu1vTAhAlCVw5A-P_5vxBfj_R7oZAAAAAAAAAAAAAAAAAAAAXIEmWg/rt=j/d=1/exm=Av2a7c,CTcde,EVZC0d,Gz34U,IiBrJf,J03Die,Kgu6Te,M25vPb,MHpzHf,MMhUM,MigGy,N35dyc,NVcOs,OIxRw,PZhDZb,PaBahd,Ps3HAc,RI4GO,Sz7W7c,Trl7bc,UZdBGe,Uq2DTd,VOAugd,WI7wt,YesRdb,aEgFwf,coi,cs,dFpypf,f,hif4bd,igbF5,jGPO6,kDVnwb,kL0rjf,lUPpNd,lhJ7R,mE4mJ,m_i,ml,o2ajQe,pA5mjb,pauPV,puPi7e,rMQdJc,spc,spit,spl,sps,spt,t,u7EXMd,uuoH9c,vXhLBe,w0FYpd,wvjFZd,yWJZbc/ed=1/im=1/rs=AHGWq9BLc708OM8Pyk5N0Y9_IbyrtxwSAw/m=sm
To fix the issue, mail.google.com should check the origin and the source of the postMessage before loading the iframe. In addition, it should validates the URL to only accept URL starting with https://
Attack scenario: Let me know if you know how to perform the cross domain Math.random() prediction attack on a modern browser, I would be very interested about it!
Also, you mentionned during BugSWAT that you were considering opening the AMP4email Gmail features to bug hunters, I would also be very interested to test it.
Best,
Enguerran