CVE-2021-30712
A memory corruption vulnerability exists in the SMB Server Apple macOS 11.1. A specially crafted SMB packet can trigger the use of an uninitialized stack variable which can lead to memory corruption and denial of service. This vulnerability can be triggered by sending a malicious packet to the vulnerable server.
Apple macOS 11.2
4.2 - CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:L
CWE-824 - Access of Uninitialized Pointer
macOS is a series of proprietary operating systems developed by Apple with macOS 11.2, with Big Sur being the latest.
Server Message Block (SMB) is a network file sharing protocol widely used in Windows network environments and macOS contains a proprietary implementation of both server and client components. SMB is often used in office and enterprise environments for file and printer sharing.
Three distinct versions and multiple dialects of SMB protocol are supported by macOS’ SMB server. This vulnerability is present in SMB2 and newer versions of the protocol, more specifically in the IOCTL_REQUEST
processing.
While processing the IOCTL_REQUEST
packets, function smb2_dispatch_ioctl_request
is invoked with supplied packet bytes as its arguments. It in turn calls smb2::extract(uchar *&,uchar * const&,smb2::ioctl_request &,uchar * const&)
which extracts different fields from the packet into IOCTL_REQUEST
structure. Among other structure fields, values for inputOffset
, inputLength
and inputBuffer
are extracted. Value inputOffset
specifies an offset to IOCTL input buffer from the beginning of the packet while inputLength
specifies its size. Pointer inputBuffer
is supposed to point to the beginning of the buffer, as instructed by inputOffset
. However, taking a closer look at the code reveals the following (pseudo-code, relevant parts):
inputOffset = **packet_pointer | (*(*packet_pointer + 2LL) << 16) | (*(*packet_pointer + 3LL) << 24); [1]
lioctl_request->InputOffset = inputOffset;
inputCount = *(v12 + 4) | (*(v12 + 6) << 16) | (*(v12 + 7) << 24); [2]
lioctl_request->InputCount = inputCount;
if ( inputCount <= *packet_end - inputBuffer ) [3]
{
result = 1; [4]
if ( inputCount )
{
result = 0; [5]
if ( inputBuffer >= v4 && inputBuffer <= *packet_end )
{
lioctl_request->Buffer = inputBuffer; [6]
*v7 += inputCount;
result = 1;
}
}
}
}
return result;
First, at [1], inputOffset
is extracted, followed by inputCount
at [2]. At [3], a sanity check is made to make sure the buffer doesn’t end outside the packet and a success return value is set at [4]. If, however, inputCount
isn’t zero, return value is set to error and another check is performed at [5]. Check at [5] ensures that the inputBuffer
isn’t outside the packet and function finally ends.
Seemingly, all the necessary checks are performed to ensure data is sanitized, but there exists a path where return result is set to 1 ( SUCCESS ) and lioctl_request->Buffer
pointer remains uninitialized. This pointer actually resides on the calling function’s stack, is uninitialized and contains random data. When it is subsequently used, it can lead to a crash or further memory corruption if contents can be controlled.
One way to make this pointer uninitialized while this function succeed is to set inputCount
to be exactly zero. This will make the comparison at [3] to pass which sets the result to 1 (SUCCSESS), but since inputCount
is 0, the check at [4] will fail and no further processing occurs, leaving lioctl_request->Buffer
uninitialized.
This can be observed in the debugger. To demonstrate control over the uninitialized stack area, the attached PoC constructs a special, compound, SMB command. To be able to control the stack contents, we need to find a function that gives us control of its own stack. A prime candidate for this is smb2_dispatch_tree_connect
function and it really is perfect for this task because it has a very large stack frame and directly copies packet data onto its stack. This is the same function that contains a stack buffer overflow that is described in TALOS-2021-1246. In short, the start of the smb2_dispatch_tree_connect
can be abbreviated to:
__int64 __fastcall smb2_dispatch_tree_connect(smb_request *smbRequest, unsigned __int8 *treeConnectBuffer, unsigned __int8 *a3)
{
smb_request *smbRequest_local; // r15
....
__int16 wcSharePath[1024]; // [rsp+50h] [rbp-840h]
void *tree_connect_request_extracted[2];
if ( !smb2::extract(&pTreeConnectBuffer, &v22, tree_connect_request_extracted, &smbRequest->smb_packet_start) ){
return v4;
}
....
memcpy(wcSharePath, v6, (2 * v6_length));
...
In short, the above memcpy
call allows us to cleanly initialize 2048 bytes on the stack with arbitrary contents. The supplied PoC does this by sending a TREE_CONNECT
request with a very long share patch consisting of bytes with value 0x81.
The reason to construct a compound SMB command that first issues TREE_CONNECT
followed by IOCTL_REQUEST
is because parts of the compound command will be executed in the same thread, on the same stack, one right after the other. That means that stack frame for function smb2_dispatch_ioctl_request
(where our uninitialized pointer resides) begins exactly at the same place as stack frame for smb2_dispatch_tree_connect
which we have almost complete control over. This gives us an opportunity to control the contents of the uninitialized pointer and abuse this vulnerability. We can observe this in the debugger by placing breakpoints at important locations. First, we will observe memcpy
being called inside smb2_dispatch_tree_connect
:
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081b7ce0 smbd`smb2_dispatch_tree_connect(smb_request&, unsigned char*, unsigned char*) + 165
smbd`smb2_dispatch_tree_connect:
-> 0x1081b7ce0 <+165>: call 0x108220f96 ; symbol stub for: memcpy
0x1081b7ce5 <+170>: mov word ptr [rbp + 2*rbx - 0x840], 0x0
0x1081b7cef <+180>: lea eax, [rbx - 0x80000000]
0x1081b7cf5 <+186>: mov qword ptr [rbp - 0x860], r12
Target 0: (smbd) stopped.
(lldb) register read $rdi
rdi = 0x000000029cdc94d0
(lldb) ni
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081b7ce5 smbd`smb2_dispatch_tree_connect(smb_request&, unsigned char*, unsigned char*) + 170
smbd`smb2_dispatch_tree_connect:
-> 0x1081b7ce5 <+170>: mov word ptr [rbp + 2*rbx - 0x840], 0x0
0x1081b7cef <+180>: lea eax, [rbx - 0x80000000]
0x1081b7cf5 <+186>: mov qword ptr [rbp - 0x860], r12
0x1081b7cfc <+193>: mov dword ptr [rbp - 0x858], eax
Target 0: (smbd) stopped.
(lldb) mem read 0x000000029cdc94d0
0x29cdc94d0: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc94e0: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
(lldb) mem read 0x000000029cdc94d0+1000
0x29cdc98b8: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc98c8: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
(lldb) mem read 0x000000029cdc94d0+1808
0x29cdc9be0: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9bf0: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
(lldb)
In the above we can see the stack is initialized to 0x81, especially at offset 1808 where our uninitialized pointer will be. Continuing execution till smb2_dispatch_ioctl_request
is called and we can examine the stack once again:
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081d3d27 smbd`smb2_dispatch_ioctl(smb_request&, unsigned char*, unsigned char*) + 12
smbd`smb2_dispatch_ioctl:
-> 0x1081d3d27 <+12>: push rbx
0x1081d3d28 <+13>: sub rsp, 0x218
0x1081d3d2f <+20>: mov r14, rdi
0x1081d3d32 <+23>: mov rax, qword ptr [rip + 0x74357] ; (void *)0x00007fff92150d00: __stack_chk_guard
Target 0: (smbd) stopped.
(lldb)
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081d3d28 smbd`smb2_dispatch_ioctl(smb_request&, unsigned char*, unsigned char*) + 13
smbd`smb2_dispatch_ioctl:
-> 0x1081d3d28 <+13>: sub rsp, 0x218
0x1081d3d2f <+20>: mov r14, rdi
0x1081d3d32 <+23>: mov rax, qword ptr [rip + 0x74357] ; (void *)0x00007fff92150d00: __stack_chk_guard
0x1081d3d39 <+30>: mov rax, qword ptr [rax]
Target 0: (smbd) stopped.
(lldb)
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081d3d2f smbd`smb2_dispatch_ioctl(smb_request&, unsigned char*, unsigned char*) + 20
smbd`smb2_dispatch_ioctl:
-> 0x1081d3d2f <+20>: mov r14, rdi
0x1081d3d32 <+23>: mov rax, qword ptr [rip + 0x74357] ; (void *)0x00007fff92150d00: __stack_chk_guard
0x1081d3d39 <+30>: mov rax, qword ptr [rax]
0x1081d3d3c <+33>: mov qword ptr [rbp - 0x30], rax
(lldb) mem read $rsp -c 0x218
0x29cdc9ad0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x29cdc9ae0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x29cdc9af0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x29cdc9b00: dc 8f 84 a1 02 00 00 00 70 9b dc 9c 02 00 00 00 �..�....p.�.....
0x29cdc9b10: 38 5f 11 92 ff 7f 00 00 06 00 00 00 00 00 00 00 8_..�...........
0x29cdc9b20: 50 9b dc 9c 02 00 00 00 98 ab 6b 6b ff 7f 00 00 P.�......�kk�...
0x29cdc9b30: f4 00 00 00 00 00 00 00 90 cf 9f a0 02 00 00 00 �........�.�....
0x29cdc9b40: 06 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 ................
0x29cdc9b50: a0 9c dc 9c 02 00 00 00 45 0d 69 6b ff 7f 00 00 �.�.....E.ik�...
0x29cdc9b60: e8 8e 84 a1 02 00 00 00 03 00 00 00 00 00 00 00 �..�............
0x29cdc9b70: e4 06 0d 72 cc 92 0e 80 55 ab 11 28 d4 49 68 cf �..r�...U�.(�Ih�
0x29cdc9b80: 1d c0 76 8c f5 f8 84 09 2a 03 f3 bc 0f d3 75 06 .�v.��..*.�.�u.
0x29cdc9b90: 78 1a 25 08 01 00 00 00 00 00 00 00 00 00 00 00 x.%.............
0x29cdc9ba0: d0 fe 54 9f 02 00 00 00 01 00 00 00 00 00 00 00 ��T.............
0x29cdc9bb0: f0 9b dc 9c 02 00 00 00 59 19 ba 68 ff 7f 00 00 �.�.....Y.�h�...
0x29cdc9bc0: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9bd0: 00 00 00 00 00 00 00 00 28 1b 25 08 01 00 00 00 ........(.%.....
0x29cdc9be0: 81 81 81 81 81 81 81 81 78 1a 25 08 01 00 00 00 ........x.%.....
0x29cdc9bf0: 90 9c dc 9c 02 00 00 00 68 11 ba 68 ff 7f 00 00 ..�.....h.�h�...
0x29cdc9c00: 00 20 2b 08 01 00 00 00 78 1a 25 08 01 00 00 00 . +.....x.%.....
0x29cdc9c10: d0 fe 54 9f 02 00 00 00 10 1a 25 08 01 00 00 00 ��T.......%.....
0x29cdc9c20: 00 00 00 00 00 00 00 00 d0 fe 54 9f 02 00 00 00 ........��T.....
0x29cdc9c30: 00 00 00 00 00 00 00 00 0f 28 1f 08 01 00 00 00 .........(......
0x29cdc9c40: 14 00 00 00 0c 00 00 00 3d 00 00 00 be 02 00 00 ........=...�...
0x29cdc9c50: bd 02 00 00 bf 02 00 00 64 00 00 00 ff 7f 00 00 �...�...d...�...
0x29cdc9c60: 57 dd 1e 08 81 81 81 81 81 81 81 81 00 00 00 00 W�..............
0x29cdc9c70: 10 00 00 00 00 00 00 00 99 27 1f 08 01 00 00 00 .........'......
0x29cdc9c80: 00 00 00 00 00 00 00 00 76 00 9f 6f 1a b9 85 74 ........v..o.�.t
0x29cdc9c90: d0 fe 54 9f 02 00 00 00 50 00 00 00 00 00 00 00 ��T.....P.......
0x29cdc9ca0: 00 00 00 00 00 00 00 00 10 00 84 a1 02 00 00 00 ...........�....
0x29cdc9cb0: f0 9c dc 9c 02 00 00 00 ee 0e 1f 08 01 00 00 00 �.�.....�.......
0x29cdc9cc0: 00 00 00 00 00 00 00 00 78 9d dc 9c 02 00 00 00 ........x.�.....
0x29cdc9cd0: 50 00 00 00 00 00 00 00 10 00 84 a1 02 00 00 00 P..........�....
0x29cdc9ce0: 00 00 00 00 00 00 00 00
(lldb) memory read 0x29cdc94d0 -c 256
0x29cdc94d0: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc94e0: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc94f0: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9500: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9510: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9520: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9530: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9540: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9550: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9560: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9570: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9580: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc9590: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc95a0: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc95b0: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
0x29cdc95c0: 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 ................
(lldb)
First, we step into smb2_dispatch_ioctl
until sub rsp, 0x218
where stack is allocated and then we look up contents of the stack. Command mem read $rsp -c 0x218
reveals that the stack contents are no longer neatly initialized as before, but still contain series of 0x81 bytes here and there. Second, memory read shows that most of the stack is still intact. Continuing execution leads to smb2::extract(uchar *&,uchar * const&,smb2::ioctl_request &,uchar * const&)
which will extract the IOCTL_REQUEST
structure and leave lioctl_request->Buffer
uninitialized (but initialized by previous packet to 0x8181818181818181). Since IOCTL code in the PoC is set to FSCTL_VALIDATE_NEGOTIATE_INFO
, next first time lioctl_request->Buffer
is reused will be during a call to smb2::extract(unsigned char *&, unsigned char * const&, smb2::validate_negotiate_info_request &, unsigned char * const&)
. We can observe the following in the debugger:
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = breakpoint 2.24
frame #0: 0x00000001081f6b9c smbd`smb2::extract(unsigned char*&, unsigned char* const&, smb2::validate_negotiate_info_request&, unsigned char* const&)
smbd`smb2::extract:
-> 0x1081f6b9c <+0>: push rbp
0x1081f6b9d <+1>: mov rbp, rsp
0x1081f6ba0 <+4>: mov rax, qword ptr [rdi]
0x1081f6ba3 <+7>: mov rcx, qword ptr [rsi]
Target 0: (smbd) stopped.
(lldb) memory read $rdi
0x29cdc9be0: 81 81 81 81 81 81 81 81 50 cf 9f a0 02 00 00 00 ........P�.�....
0x29cdc9bf0: 90 9c dc 9c 02 00 00 00 68 11 ba 68 ff 7f 00 00 ..�.....h.�h�...
(lldb) memory read $rsi
0x29cdc9ba0: f3 cf 9f a0 02 00 00 00 39 00 00 00 04 02 14 00 ��.�....9.......
0x29cdc9bb0: 1f 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................
(lldb) ni
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081f6b9d smbd`smb2::extract(unsigned char*&, unsigned char* const&, smb2::validate_negotiate_info_request&, unsigned char* const&) + 1
smbd`smb2::extract:
-> 0x1081f6b9d <+1>: mov rbp, rsp
0x1081f6ba0 <+4>: mov rax, qword ptr [rdi]
0x1081f6ba3 <+7>: mov rcx, qword ptr [rsi]
0x1081f6ba6 <+10>: sub rcx, rax
Target 0: (smbd) stopped.
(lldb)
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081f6ba0 smbd`smb2::extract(unsigned char*&, unsigned char* const&, smb2::validate_negotiate_info_request&, unsigned char* const&) + 4
smbd`smb2::extract:
-> 0x1081f6ba0 <+4>: mov rax, qword ptr [rdi]
0x1081f6ba3 <+7>: mov rcx, qword ptr [rsi]
0x1081f6ba6 <+10>: sub rcx, rax
0x1081f6ba9 <+13>: cmp rcx, 0x18
Target 0: (smbd) stopped.
(lldb)
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081f6ba3 smbd`smb2::extract(unsigned char*&, unsigned char* const&, smb2::validate_negotiate_info_request&, unsigned char* const&) + 7
smbd`smb2::extract:
-> 0x1081f6ba3 <+7>: mov rcx, qword ptr [rsi]
0x1081f6ba6 <+10>: sub rcx, rax
0x1081f6ba9 <+13>: cmp rcx, 0x18
0x1081f6bad <+17>: jl 0x1081f6c11 ; <+117>
Target 0: (smbd) stopped.
(lldb)
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081f6ba6 smbd`smb2::extract(unsigned char*&, unsigned char* const&, smb2::validate_negotiate_info_request&, unsigned char* const&) + 10
smbd`smb2::extract:
-> 0x1081f6ba6 <+10>: sub rcx, rax
0x1081f6ba9 <+13>: cmp rcx, 0x18
0x1081f6bad <+17>: jl 0x1081f6c11 ; <+117>
0x1081f6baf <+19>: mov r8d, dword ptr [rax]
Target 0: (smbd) stopped.
(lldb) memory read $rax
error: memory read failed for 0x8181818181818000
(lldb) ni
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081f6ba9 smbd`smb2::extract(unsigned char*&, unsigned char* const&, smb2::validate_negotiate_info_request&, unsigned char* const&) + 13
smbd`smb2::extract:
-> 0x1081f6ba9 <+13>: cmp rcx, 0x18
0x1081f6bad <+17>: jl 0x1081f6c11 ; <+117>
0x1081f6baf <+19>: mov r8d, dword ptr [rax]
0x1081f6bb2 <+22>: lea rcx, [rax + 0x4]
Target 0: (smbd) stopped.
(lldb)
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081f6bad smbd`smb2::extract(unsigned char*&, unsigned char* const&, smb2::validate_negotiate_info_request&, unsigned char* const&) + 17
smbd`smb2::extract:
-> 0x1081f6bad <+17>: jl 0x1081f6c11 ; <+117>
0x1081f6baf <+19>: mov r8d, dword ptr [rax]
0x1081f6bb2 <+22>: lea rcx, [rax + 0x4]
0x1081f6bb6 <+26>: mov qword ptr [rdi], rcx
Target 0: (smbd) stopped.
(lldb)
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = instruction step over
frame #0: 0x00000001081f6baf smbd`smb2::extract(unsigned char*&, unsigned char* const&, smb2::validate_negotiate_info_request&, unsigned char* const&) + 19
smbd`smb2::extract:
-> 0x1081f6baf <+19>: mov r8d, dword ptr [rax]
0x1081f6bb2 <+22>: lea rcx, [rax + 0x4]
0x1081f6bb6 <+26>: mov qword ptr [rdi], rcx
0x1081f6bb9 <+29>: mov dword ptr [rdx], r8d
Target 0: (smbd) stopped.
(lldb)
Process 52252 stopped
* thread #24, queue = 'com.apple.root.default-qos', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x00000001081f6baf smbd`smb2::extract(unsigned char*&, unsigned char* const&, smb2::validate_negotiate_info_request&, unsigned char* const&) + 19
smbd`smb2::extract:
-> 0x1081f6baf <+19>: mov r8d, dword ptr [rax]
0x1081f6bb2 <+22>: lea rcx, [rax + 0x4]
0x1081f6bb6 <+26>: mov qword ptr [rdi], rcx
0x1081f6bb9 <+29>: mov dword ptr [rdx], r8d
Target 0: (smbd) stopped.
(lldb) register read rax
rax = 0x8181818181818181
(lldb) bt
* thread #24, queue = 'com.apple.root.default-qos', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
* frame #0: 0x00000001081f6baf smbd`smb2::extract(unsigned char*&, unsigned char* const&, smb2::validate_negotiate_info_request&, unsigned char* const&) + 19
frame #1: 0x00000001081d406b smbd`smb2_dispatch_ioctl(smb_request&, unsigned char*, unsigned char*) + 848
frame #2: 0x00000001081d9abe smbd`smb2_dispatch_compound(smb_transport*, unsigned char*, unsigned char*) + 1358
frame #3: 0x00000001081c51a1 smbd`invocation function for block in smb_transport::dispatch() + 54
frame #4: 0x00007fff6b8186c4 libdispatch.dylib`_dispatch_call_block_and_release + 12
frame #5: 0x00007fff6b819658 libdispatch.dylib`_dispatch_client_callout + 8
frame #6: 0x00007fff6b827aa8 libdispatch.dylib`_dispatch_root_queue_drain + 663
frame #7: 0x00007fff6b828097 libdispatch.dylib`_dispatch_worker_thread2 + 92
frame #8: 0x00007fff6ba739f7 libsystem_pthread.dylib`_pthread_wqthread + 220
frame #9: 0x00007fff6ba72b77 libsystem_pthread.dylib`start_wqthread + 15
Above shows that the uninitialized value indeed ends up being used as lioctl_request->Buffer
and ultimately leads to invalid memory read causing a crash and denial of service.
It should be noted that above demonstrated crash is unreliable and extremely sensitive to configuration , users, available shares, but most importantly binary version. The ability to cause a crash or otherwise abuse this issue is largely dependent on stack variable ordering and therefore could be changed by the compiler. Nevertheless, even if not causing a crash, triggering the vulnerability can still be observed in the debugger by following uninitialized stack values from smb2_dispatch_tree_connect
to smb2_dispatch_ioctl_request
. Additionally, differences in memory layout can cause the rest of the code to take a different path which can be observed over the network.
2021-03-02 - Vendor Disclosure
2021-05-25 - Vendor Patched
2021-06-01 - Public Release
Discovered by Aleksandar Nikolic of Cisco Talos.