CVE-2018-8789
Information- Case #1
File: winpr\libwinpr\sspi\NTLM\ntlm_message.c
Function: ntlm_read_message_fields_buffer()
When reaching this function, “fields->BufferOffset” is already controlled by an attacker and can be in the range: 0 - 0xFFFFFFFF.
The sanitation check that makes sure that there are enough input bytes has an Integer-Overflow, and can be bypassed.
fields->BufferOffset = 0xFFFFFF80
+
fields->Len = 0x00000100
------------------------------------
checked condition = 0x00000080
Later on, the call to “Stream_SetPosition(s, fields->BufferOffset)” will set the input stream to point at a potentially unmapped memory address.
Subsequent reads from the input stream will cause an access violation, thus crashing the client.
Code Snippet:
int ntlm_read_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
{
if (Stream_GetRemainingLength(s) < 8)
return -1;
Stream_Read_UINT16(s, fields->Len); /* Len (2 bytes) */
Stream_Read_UINT16(s, fields->MaxLen); /* MaxLen (2 bytes) */
Stream_Read_UINT32(s, fields->BufferOffset); /* BufferOffset (4 bytes) */
return 1;
}
...
int ntlm_read_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
{
if (fields->Len > 0)
{
if ((fields->BufferOffset + fields->Len) > Stream_Length(s))
return -1;
fields->Buffer = (PBYTE) malloc(fields->Len);
if (!fields->Buffer)
return -1;
Stream_SetPosition(s, fields->BufferOffset);
Stream_Read(s, fields->Buffer, fields->Len);
}
return 1;
}
ASAN Output:
[14:48:55:025] [16164:16165] [INFO][com.freerdp.client.common.cmdline] - loading channelEx cliprdr
ASAN:SIGSEGV
=================================================================
==16164==ERROR: AddressSanitizer: SEGV on unknown address 0x61110001d0c0 (pc 0x7f816f4ed070 bp 0x7f81628f9280 sp 0x7f81628f8a08 T1)
#0 0x7f816f4ed06f (/lib/x86_64-linux-gnu/libc.so.6+0x16006f)
#1 0x7f8171dfb5d0 in __asan_memcpy (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x8c5d0)
#2 0x7f816f88b55c in ntlm_read_ChallengeMessage (/usr/local/lib/libwinpr2.so.2+0x13455c)
#3 0x7f816f895b3c in ntlm_InitializeSecurityContextA (/usr/local/lib/libwinpr2.so.2+0x13eb3c)
#4 0x7f816f89d730 in winpr_InitializeSecurityContextA (/usr/local/lib/libwinpr2.so.2+0x146730)
#5 0x7f81701b4d55 in nla_recv_pdu (/usr/local/lib/libfreerdp2.so.2+0xffd55)
#6 0x7f81702425cf in rdp_recv_callback (/usr/local/lib/libfreerdp2.so.2+0x18d5cf)
#7 0x7f8170256a50 in transport_check_fds (/usr/local/lib/libfreerdp2.so.2+0x1a1a50)
#8 0x7f8170242ecf in rdp_check_fds (/usr/local/lib/libfreerdp2.so.2+0x18decf)
#9 0x7f817022aa50 in rdp_client_connect (/usr/local/lib/libfreerdp2.so.2+0x175a50)
#10 0x7f817020d969 in freerdp_connect (/usr/local/lib/libfreerdp2.so.2+0x158969)
#11 0x449a44 in xf_client_thread (/home/XXX/FreeRDP-2.0.0-rc3/xfreerdp+0x449a44)
#12 0x7f816f879ec5 in thread_launcher (/usr/local/lib/libwinpr2.so.2+0x122ec5)
#13 0x7f816f1776b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)
#14 0x7f816f49441c in clone (/lib/x86_64-linux-gnu/libc.so.6+0x10741c)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 ??
Thread T1 created by T0 here:
#0 0x7f8171da5253 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x36253)
#1 0x7f816f879bf4 in winpr_StartThread (/usr/local/lib/libwinpr2.so.2+0x122bf4)
#2 0x7f816f87a4b7 in CreateThread (/usr/local/lib/libwinpr2.so.2+0x1234b7)
#3 0x446f7f in xfreerdp_client_start (/home/XXX/FreeRDP-2.0.0-rc3/xfreerdp+0x446f7f)
#4 0x4079d0 in main (/home/XXX/FreeRDP-2.0.0-rc3/xfreerdp+0x4079d0)
#5 0x7f816f3ad82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
==16164==ABORTING
Information - Case #2
File: winpr\libwinpr\sspi\NTLM\ntlm_av_pairs.c
Function: ntlm_av_pair_get_next_pointer()
The iteration loop inside “ntlm_av_pair_get” fails to sanitize the “next_offset” field.
An attacker can supply a maliciously large offset, thus shifting the loop to read “input” from outside of the input buffer.
Setting the iteration loop to point at a potentially unmapped memory address will cause an access violation, thus crashing the client.
Code Snippet:
NTLM_AV_PAIR* ntlm_av_pair_get_next_pointer(NTLM_AV_PAIR* pAvPair)
{
return (NTLM_AV_PAIR*)((PBYTE) pAvPair + ntlm_av_pair_get_next_offset(pAvPair));
}
NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId)
{
NTLM_AV_PAIR* pAvPair = pAvPairList;
if (!pAvPair)
return NULL;
while (1)
{
if (ntlm_av_pair_get_id(pAvPair) == AvId)
return pAvPair;
if (ntlm_av_pair_get_id(pAvPair) == MsvAvEOL)
return NULL;
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
}
return NULL;
}
ASAN Output:
[14:54:23:624] [16233:16234] [INFO][com.freerdp.client.common.cmdline] - loading channelEx cliprdr
ASAN:SIGSEGV
=================================================================
==16233==ERROR: AddressSanitizer: SEGV on unknown address 0x60e000016cc3 (pc 0x7f686993fb0f bp 0x7f685c9f9280 sp 0x7f685c9f9280 T1)
#0 0x7f686993fb0e in ntlm_av_pair_get (/usr/local/lib/libwinpr2.so.2+0x126b0e)
#1 0x7f686994d005 in ntlm_read_ChallengeMessage (/usr/local/lib/libwinpr2.so.2+0x134005)
#2 0x7f6869957b3c in ntlm_InitializeSecurityContextA (/usr/local/lib/libwinpr2.so.2+0x13eb3c)
#3 0x7f686995f730 in winpr_InitializeSecurityContextA (/usr/local/lib/libwinpr2.so.2+0x146730)
#4 0x7f686a276d55 in nla_recv_pdu (/usr/local/lib/libfreerdp2.so.2+0xffd55)
#5 0x7f686a3045cf in rdp_recv_callback (/usr/local/lib/libfreerdp2.so.2+0x18d5cf)
#6 0x7f686a318a50 in transport_check_fds (/usr/local/lib/libfreerdp2.so.2+0x1a1a50)
#7 0x7f686a304ecf in rdp_check_fds (/usr/local/lib/libfreerdp2.so.2+0x18decf)
#8 0x7f686a2eca50 in rdp_client_connect (/usr/local/lib/libfreerdp2.so.2+0x175a50)
#9 0x7f686a2cf969 in freerdp_connect (/usr/local/lib/libfreerdp2.so.2+0x158969)
#10 0x449a44 in xf_client_thread (/home/XXX/FreeRDP-2.0.0-rc3/xfreerdp+0x449a44)
#11 0x7f686993bec5 in thread_launcher (/usr/local/lib/libwinpr2.so.2+0x122ec5)
#12 0x7f68692396b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)
#13 0x7f686955641c in clone (/lib/x86_64-linux-gnu/libc.so.6+0x10741c)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 ntlm_av_pair_get
Thread T1 created by T0 here:
#0 0x7f686be67253 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x36253)
#1 0x7f686993bbf4 in winpr_StartThread (/usr/local/lib/libwinpr2.so.2+0x122bf4)
#2 0x7f686993c4b7 in CreateThread (/usr/local/lib/libwinpr2.so.2+0x1234b7)
#3 0x446f7f in xfreerdp_client_start (/home/XXX/FreeRDP-2.0.0-rc3/xfreerdp+0x446f7f)
#4 0x4079d0 in main (/home/XXX/FreeRDP-2.0.0-rc3/xfreerdp+0x4079d0)
#5 0x7f686946f82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
==16233==ABORTING
Attachments:
CVE-2018-8789_PoC_1.py
CVE-2018-8789_PoC_2.py
private_no_pass.key
selfsigned.crt
References:
https://research.checkpoint.com/reverse-rdp-attack-code-execution-on-rdp-clients
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8789
https://github.com/FreeRDP/FreeRDP/commit/eb57ed3a3059cea8576eaa91ccd6b3a3fd959f41
https://github.com/FreeRDP/FreeRDP/commit/2ee663f39dc8dac3d9988e847db19b2d7e3ac8c6