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