Trustwave's 2024 Financial Services Threat Reports Highlight Alarming Trends in Insider Threats & Phishing-as-a-Service. Learn More
Get access to immediate incident response assistance.
Get access to immediate incident response assistance.
Trustwave's 2024 Financial Services Threat Reports Highlight Alarming Trends in Insider Threats & Phishing-as-a-Service. Learn More
Hi everyone, how are you? I know the times are strange but we should fight together, support each other and hopefully, everything will be fine by the end!
I might be a little bit late to the party but I thought the release of CVE-2020-0796, aka SMBGhost, was an excellent opportunity to add a new part to my series on Windows Debugging. It will give us a chance to add on to the knowledge we've gathered in the first parts and discuss something new and current.
The CVE-2020-0796 was officially disclosed (after some confusion) on March, 13th 2020 and affects Windows Server/10 x86/x64/ARM64 builds 1903 and 1909. Microsoft described it as '’wormable" due to the fact that it could allow for unauthenticated and arbitrary remote code execution. This gives it the capacity to spread automatically over the network and in turn, makes it a very interesting vulnerability to analyze.
In this blog, we will use our lab set up on the first blog post and some techniques discussed in the second, so again, an excellent chance to put together some things we've learned from the last posts for some actual work.
There is already a lot of information out there about SMBGhost including a great post from Synacktiv, but I'll try to be as much educative as possible and present some basic aspects as well.
One approach to discover what is the vulnerability that was patched is comparing the old binary to the patched one. Using tools like IDA Pro + BinDiff we are able to determine what was changed on the file and then do a static analysis on the modifications to identify and understand the vulnerability.
To start, we can follow the strategy below (thank you hugsy!):
We know by fact that the binary responsible for the SMB server is the srv2.sys. Open the srv2.sys unpatched version and then compare it to the patched one.
We can see that there are only a few functions distinguishing from each other. One in special: Srv2DecompressData, let's compare the function flow.
So, here it is the vulnerability, there is a buffer allocation right after a mathematical operation (add) utilizing both arguments controlled by the user, unfiltered, and that could trigger an overflow as well as an underflow.
00000001C0017EC8 mov rax, qword ptr [rsp+58h+Header.ProtocolId]
00000001C0017ECD xor edx, edx
00000001C0017ECF shr rax, 20h ; OriginalCompressedSegmentSize
00000001C0017ED3 shr rcx, 20h ; OffsetOrLength|
00000001C0017ED7 add ecx, eax
00000001C0017ED9 call cs:__imp_SrvNetAllocateBuffer
To understand where these arguments are placed in the communication, we have to go back to the protocol specifications for understanding.
The OriginalCompressedSegmentSize is used to determine the size of the uncompressed data and OffsetOrLength is for chaining compressed packets as explicit on the official document:
There are no security checks on those parameters since OriginalCompressedSegmentSize and OffsetOrLength are 32 bits unsigned long, we can send unexpected values on those parameters and these will trigger abnormal behaviour at the application, in this case crash the system causing the famous BSoD.
There are few PoCs available for testing purposes, at this point *only* causing BSoD. We can use any and debug the SMB with WinDBG to check how it behaves internally.
I used this PoC which is very straight-forward. It uses the smbprotocol library to construct the packet and defines the highest possible value for OffsetOrLength (0xffffffff) described on smbprotocol/connection.py:
1448: def _compress(self, b_data, session):
1449: header = SMB2CompressionTransformHeader()
1450: header['original_size'] = len(b_data)
1451: header['offset'] = 4294967295
1452: header['data'] = smbprotocol.lznt1.compress(b_data)
I set a breakpoint on the function and ran the PoC:
Breakpoint 0 hit
srv2!Srv2DecompressData+0x6f:
fffff805`3e1f7ecf 48c1e820 shr rax,20h
0: kd> u
srv2!Srv2DecompressData+0x6f:
fffff805`3e1f7ecf 48c1e820 shr rax,20h
fffff805`3e1f7ed3 48c1e920 shr rcx,20h
fffff805`3e1f7ed7 03c8 add ecx,eax
fffff805`3e1f7ed9 4c8b15489a0200 mov r10,qword ptr [srv2!_imp_SrvNetAllocateBuffer (fffff805`3e221928)]
fffff805`3e1f7ee0 e84be82b00 call srvnet!SrvNetAllocateBuffer (fffff805`3e4b6730)
fffff805`3e1f7ee5 488bd8 mov rbx,rax
fffff805`3e1f7ee8 4885c0 test rax,rax
fffff805`3e1f7eeb 750a jne srv2!Srv2DecompressData+0x97 (fffff805`3e1f7ef7)
0: kd> r
rax=000001ac424d53fc rbx=ffff850dfa3f9710 rcx=ffffffffffff0001
rdx=0000000000000000 rsi=ffffffffffffffff rdi=ffff850dfa3f9710
rip=fffff8053e1f7ecf rsp=fffffb85e531de70 rbp=0000000000000001
r8=0000000000000000 r9=0000000000000000 r10=0000000000000000
r11=0000000000000002 r12=0000000000000000 r13=ffff850df9381240
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei pl zr na po nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00040246
[..]
DTARGET: Refreshing KD connection
*** Fatal System Error: 0x00000050
(0xFFFF850EFBEC605F,0x0000000000000000,0xFFFFF80536AEB6F7,0x0000000000000002)
Break instruction exception - code 80000003 (first chance)
A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.
A fatal system error has occurred.
For analysis of this file, run !analyze -v
The data will trigger the BSoD while executing srvnet!SmbCompressionDecompress.
It seems that this vulnerability also affects the client (see analysis from McAfee's blog). In that case, the function on the client is triggered in the mrxsmb.sys file.
I really enjoyed taking a look at something like this. It's a very classic vulnerability with a huge risk to the system. We were also able to use some old posts from these series and apply our knowledge on a real vulnerability in a modern Windows system. That's awesome!
The vulnerability could be very hard to be exploited due to the protections in kernel as KASLR, but maybe I'll prepare something for next post. As you can see, I'm not following any specific order but if you feel that I could write about something, let me know! Thank you!
Trustwave is a globally recognized cybersecurity leader that reduces cyber risk and fortifies organizations against disruptive and damaging cyber threats. Our comprehensive offensive and defensive cybersecurity portfolio detects what others cannot, responds with greater speed and effectiveness, optimizes client investment, and improves security resilience. Learn more about us.
Copyright © 2024 Trustwave Holdings, Inc. All rights reserved.