-
Notifications
You must be signed in to change notification settings - Fork 6
Report Google
Hello, Google security team!
We found a DOM clobbering gadget in scripts hosted on apis.google.com that is wildly used in the websites that embed Google products (e.g. Google Drive). The gadget would directly lead to cross-site scripting and be able to bypass the in-place mitigation mechanism (e.g. CSP and XSS sanitizer). The cross-site scripting vulnerability may further help attackers to leak sensitive information (e.g. Google API Keys) used in the websites.
DOM Clobbering is a type of scriptless injection attack where the attacker injects a piece of non-script, seemingly benign HTML markups in the webpage and leverages the gadgets (pieces of js code) living in the existing javascript code to transform it into executable code. More for information about DOM Clobbering, here are some references:
[1] https://scnps.co/papers/sp23_domclob.pdf [2] https://research.securitum.com/xss-in-amp4email-dom-clobbering/
We recently discovered a DOM clobbering gadget within scripts sourced from apis.google.com. I believe the script gadget lives in several scripts (i.e. urls) that share the same functionality. For clarity, I have included an example URL below:
The critical issue resides in function Ff on line 99, where var e = document.scripts is intended to retrieve all script tags from the document. However, this can be overridden by an attacker’s HTML markup (e.g., <iframe name="scripts"></iframe>) that sets the name attribute to scripts. This allows the attacker to manipulate textContent values, passing them as arguments to function Df. This function dynamically constructs and executes a new function using the provided textContent, leading to potential malicious actions.
Ff = function(a) {
Af(!0);
var b = window.___gcfg
, c = zf("cu")
, d = window.___gu;
b && b !== d && (Ef(c, b),
window.___gu = b);
b = zf("cu");
var e = document.scripts || document.getElementsByTagName("script") || [];
d = [];
var f = [];
f.push.apply(f, zf("us"));
for (var h = 0; h < e.length; ++h)
for (var k = e[h], l = 0; l < f.length; ++l)
k.src && 0 == k.src.indexOf(f[l]) && d.push(k);
0 == d.length && 0 < e.length && e[e.length - 1].src && d.push(e[e.length - 1]);
for (e = 0; e < d.length; ++e)
d[e].getAttribute("gapi_processed") || (d[e].setAttribute("gapi_processed", !0),
(f = d[e]) ? (h = f.nodeType,
f = 3 == h || 4 == h ? f.nodeValue : f.textContent || "") : f = void 0,
(f = Df(f)) && b.push(f));
a && Ef(c, a);
d = zf("cd");
a = 0;
for (b = d.length; a < b; ++a)
Cf(Af(), d[a], !0);
d = zf("ci");
a = 0;
for (b = d.length; a < b; ++a)
Cf(Af(), d[a], !0);
a = 0;
for (b = c.length; a < b; ++a)
Cf(Af(), c[a], !0)
};
Df = function(a) {
if (a && !/^\s+$/.test(a)) {
for (; 0 == a.charCodeAt(a.length - 1); )
a = a.substring(0, a.length - 1);
try {
var b = window.JSON.parse(a)
} catch (c) {}
if ("object" === typeof b)
return b;
try {
b = (new Function("return (" + a + "\n)"))()
} catch (c) {}
if ("object" === typeof b)
return b;
try {
b = (new Function("return ({" + a + "\n})"))()
} catch (c) {}
return "object" === typeof b ? b : {}
}
}
The working payload:
<iframe name="scripts" src>alert(document.cookie)</iframe>
<iframe name="scripts" src>alert(document.cookie)</iframe>
The identified gadget enables attackers to circumvent existing XSS sanitizers that fail to adequately filter the name or id attributes in user-supplied HTML markup. For instance, a script payload embedded within the body of an <iframe> tag without the <script> tag wrapped up is treated as plain text rather than an executable script, thus avoiding direct parsing by script parsers.
Furthermore, due to the dynamic generation of code from the trusted domain apis.google.com, the gadget can also bypass Content Security Policy (CSP) settings. Websites that load these scripts typically do not block them, considering the source domain as safe (script-src 'self' https://apis.google.com). This oversight allows potentially malicious scripts to be executed under the guise of trusted content.
The activation of the identified gadget requires no additional user interaction. It is observed that the gadget triggers automatically when a website attempts to load Google product iframes, such as the Google Drive picker or Google Maps. During this process, any HTML markup injected by an attacker is activated immediately and effectively, exploiting the vulnerability without further actions from the user.
In general, websites that 1/ render user-supplied, non-script HTML markup without proper sanitization of name or id attributes 2/ embed Google products or use Google client APIs, will be vulnerable to cross-site scripting vulnerability.
A notable example is HackMD.io, a popular collaborative markdown platform with 8.9k stars for its open-sourced version on GitHub, which is vulnerable to this gadget. By clicking the compromised shared note on HackMD.io, the victim's cookies can be exposed. With further manipulation, an attacker could potentially access more sensitive information stored in Google Drive for users who have granted HackMD.io access to their Google services.
The PoC on HackMD.io (will alert user cookie):
https://hackmd.io/TUFuY73CTl-Q4U4ZvNDuVQ
Additionally, the script containing this gadget is so widely used not only in third-party websites but also across various google.com domains. It affects several heavily utilized Google products, including Google Maps, Google Docs, Google Mail, and Google Calendar, among others.
- https://www.google.com/maps/
- https://docs.google.com/presentation
- https://mail.google.com/
- https://calendar.google.com/
- https://www.google.com/
- https://docs.google.com/document
- ...
Due to its widespread prevalence and exploitability, this gadget should be regarded as a severe security threat requiring immediate attention.
A specific code modification to mitigate this issue involves replacing document.scripts with the DOM API method getElementsByTagName('script'). This change prevents the gadget from being triggered by attacker-injected HTML markups that could overshadow document.scripts.
Additionally, implementing type checking on the queried DOM nodes can provide an extra layer of security.
The gadget leads to cross-site scripting (XSS) attacks by allowing attackers to inject scriptless HTML markups into websites that embeds Google products, particularly those loading scripts from apis.google.com. Beyond basic exploits such as stealing first-party cookies, this vulnerability can lead to more severe outcomes. For instance, attackers could deceive users into leaking sensitive data stored in their Google services, like Google Drive.
HackMD.io, a popular collaborative markdown platform, allows users to incorporate certain scriptless HTML markups into their notes. Despite having XSS sanitizers and robust Content Security Policy (CSP) rules in place, the platform's integration with Google services creates a point of vulnerability. The CSP for HackMD.io is as follows:
default-src 'none'; script-src 'self' vimeo.com https://gist.github.com www.slideshare.net 'unsafe-eval' https://assets.hackmd.io https://www.google.com https://apis.google.com https://docs.google.com https://accounts.google.com https://www.dropbox.com https://www.google-analytics.com https://stats.g.doubleclick.net https://secure.quantserve.com https://rules.quantcount.com https://pixel.quantserve.com https://static.hotjar.com https://script.hotjar.com https://www.googletagmanager.com https://cdn.ravenjs.com https://browser.sentry-cdn.com https://js.stripe.com 'nonce-c0a2b900-27db-4a06-936b-71be4559702b' 'sha256-EtvSSxRwce5cLeFBZbvZvDrTiRoyoXbWWwvEVciM5Ag=' 'sha256-NZb7w9GYJNUrMEidK01d3/DEtYztrtnXC/dQw7agdY4=' 'sha256-L0TsyAQLAc0koby5DCbFAwFfRs9ZxesA+4xg0QDSrdI=' 'sha256-8HvL1KRq6jEwDkuVgxMDK7Gag1vnT70L0Lfoa1E3YsY=' 'sha256-81acLZNZISnyGYZrSuoYhpzwDTTxi7vC1YM4uNxqWaM=' https://tally.so https://tracks.hackmd.io https://plausible.io; img-src * data: blob:; style-src 'self' 'unsafe-inline' https://assets-cdn.github.com https://github.githubassets.com https://assets.hackmd.io https://www.google.com https://fonts.gstatic.com; font-src 'self' data: https://public.slidesharecdn.com https://assets.hackmd.io https://script.hotjar.com; object-src *; media-src *; frame-src *; child-src *; connect-src *; base-uri 'none'; form-action 'self' https://www.paypal.com; upgrade-insecure-requests
HackMD.io allows users to synchronize (upload and save) their markdown notes to Google Drive. This synchronization process inadvertently allows the gadget to be loaded, presenting an attack vector. By embedding malicious payloads into shared notes, an attacker can directly steal cookies from any victim viewing the note. Furthermore, if the victim has granted HackMD.io access to their Google Drive, they could be further manipulated into leaking files stored there.
Due to its wide prevalence and the ease with which it can be exploited, this gadget represents a significant security threat. It broadens the attack surface of websites and necessitates immediate remedial action to protect users and their data.
![]()
- Related Works
- HTML Injection
- DOM Clobbering
- Evaluation
- Discussion
- Others