Skip to content

Incorrect offset calculation leading to DOS

Moderate
akallabeth published GHSA-rrrv-3w42-pffh Aug 31, 2023

Package

FreeRDP

Affected versions

<= 2.10.0 , <=3.0.0-beta2

Patched versions

2.11.0, 3.0.0-beta3

Description

Summary

Clients only, Integer underflow leading to DOS (e.g. abort due to WINPR_ASSERT with default compilation flags)

Affected

FreeRDP based clients only. FreeRDP proxy not affected as image decoding is not done by proxy (data passthrough)

Details

When an insufficient blockLen is provided, and proper length validation is not performed, an Integer Underflow occurs, leading to a Denial of Service (DOS) vulnerability.

PoC

FreeRDP/libfreerdp/codec/rfx.c

Lines 1095 to 1168 in 8fc7062

while (ok && Stream_GetRemainingLength(s) > 6)
{
wStream subStreamBuffer;
wStream* subStream;
size_t extraBlockLen = 0;
/* RFX_BLOCKT */
Stream_Read_UINT16(s, blockType); /* blockType (2 bytes) */
Stream_Read_UINT32(s, blockLen); /* blockLen (4 bytes) */
WLog_Print(context->priv->log, WLOG_DEBUG, "blockType 0x%" PRIX32 " blockLen %" PRIu32 "",
blockType, blockLen);
if (blockLen < 6)
{
WLog_Print(context->priv->log, WLOG_ERROR, "blockLen too small(%" PRIu32 ")", blockLen);
return FALSE;
}
if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, blockLen - 6))
return FALSE;
if (blockType > WBT_CONTEXT && context->decodedHeaderBlocks != RFX_DECODED_HEADERS)
{
WLog_Print(context->priv->log, WLOG_ERROR, "incomplete header blocks processing");
return FALSE;
}
if (blockType >= WBT_CONTEXT && blockType <= WBT_EXTENSION)
{
/* RFX_CODEC_CHANNELT */
UINT8 codecId;
UINT8 channelId;
if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 2))
return FALSE;
extraBlockLen = 2;
Stream_Read_UINT8(s, codecId); /* codecId (1 byte) must be set to 0x01 */
Stream_Read_UINT8(s, channelId); /* channelId (1 byte) 0xFF or 0x00, see below */
if (codecId != 0x01)
{
WLog_Print(context->priv->log, WLOG_ERROR, "invalid codecId 0x%02" PRIX8 "",
codecId);
return FALSE;
}
if (blockType == WBT_CONTEXT)
{
/* If the blockType is set to WBT_CONTEXT, then channelId MUST be set to 0xFF.*/
if (channelId != 0xFF)
{
WLog_Print(context->priv->log, WLOG_ERROR,
"invalid channelId 0x%02" PRIX8 " for blockType 0x%08" PRIX32 "",
channelId, blockType);
return FALSE;
}
}
else
{
/* For all other values of blockType, channelId MUST be set to 0x00. */
if (channelId != 0x00)
{
WLog_Print(context->priv->log, WLOG_ERROR,
"invalid channelId 0x%02" PRIX8 " for blockType WBT_CONTEXT",
channelId);
return FALSE;
}
}
}
subStream =
Stream_StaticInit(&subStreamBuffer, Stream_Pointer(s), blockLen - (6 + extraBlockLen));
Stream_Seek(s, blockLen - (6 + extraBlockLen));

Send rfx packet with

  1. WBT_CONTEXT <= blockType <= WBT_EXTENSION
  2. blockLen == 7
  3. blockLen - (6 + extraBlockLen) is7 - (6 + 2) == 0xFFFFFFFF cause integer underflow

Patch

subStream = 
 	    Stream_StaticInit(&subStreamBuffer, Stream_Pointer(s), blockLen - (6 + extraBlockLen)); 
if (!Stream_SafeSeek(s, blockLen - (6 + extraBlockLen)))
{
	return FALSE;
}

Impact

DOS

Log

cmdId: RDPGFX_CMDID_EVICTCACHEENTRY (0x0008) flags: 0x1337 pduLength: 10
cmdId: RDPGFX_CMDID_EVICTCACHEENTRY (0x0008) flags: 0x1337 pduLength: 10
cmdId: RDPGFX_CMDID_DELETEENCODINGCONTEXT (0x0003) flags: 0x1337 pduLength: 14
cmdId: RDPGFX_CMDID_WIRETOSURFACE_1 (0x0001) flags: 0x1337 pduLength: 38
[19:37:52:704] [20912:6ba7b000] [ERROR][com.freerdp.gdi] - [gdi_SurfaceCommand]: surfaceId=50168, codec=RDPGFX_CODECID_CAVIDEO [3], contextId=0, format=PIXEL_FORMAT_BGRX32, left=11913, top=13572, right=11927, bottom=13607, width=14, height=35 length=13, data=0x60b00009f019, extra=0x0
[19:37:52:704] [20912:6ba7b000] [ERROR][com.freerdp.codec.rfx] - [rfx_process_message]: blockType 0xCCC3 blockLen 7
[19:37:52:704] [20912:6ba7b000] [ERROR][com.freerdp.codec] - [rfx_process_message]: rfx_process_message context->decodedHeaderBlocks => 00

[19:37:52:704] [20912:6ba7b000] [ERROR][com.freerdp.codec] - [rfx_process_message]: blockLen = 7, extraBlockLen = 2, remain = 5
[19:37:52:704] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_int_assert]: Stream_GetRemainingCapacity(s) >= _offset [/Users/sprout/Desktop/pwn2car/FreeRDP/winpr/include/winpr/stream.h:Stream_Seek:120]
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 0: 0   libwinpr3.3.0.0.dylib               0x000000010631ee24 winpr_execinfo_backtrace + 336
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 1: 1   libwinpr3.3.0.0.dylib               0x000000010631895c winpr_backtrace + 24
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 2: 2   libwinpr3.3.0.0.dylib               0x0000000106318cb8 winpr_log_backtrace_ex + 304
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 3: 3   libfreerdp3.3.0.0.dylib             0x0000000105862738 winpr_int_assert + 168
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 4: 4   libfreerdp3.3.0.0.dylib             0x0000000105865448 Stream_Seek + 144
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 5: 5   libfreerdp3.3.0.0.dylib             0x0000000105864264 rfx_process_message + 4848
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 6: 6   libfreerdp3.3.0.0.dylib             0x00000001059bb65c gdi_SurfaceCommand_RemoteFX + 1756
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 7: 7   libfreerdp3.3.0.0.dylib             0x00000001059b343c gdi_SurfaceCommand + 1364
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 8: 8   libfreerdp-client3.3.0.0.dylib      0x0000000104b96f5c rdpgfx_decode + 652
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 9: 9   libfreerdp-client3.3.0.0.dylib      0x0000000104b827b0 rdpgfx_recv_wire_to_surface_1_pdu + 5360
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 10: 10  libfreerdp-client3.3.0.0.dylib      0x0000000104b8000c rdpgfx_recv_pdu + 1064
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 11: 11  libfreerdp-client3.3.0.0.dylib      0x0000000104b7f140 rdpgfx_on_data_received + 1096
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 12: 12  libfreerdp-client3.3.0.0.dylib      0x0000000104b02634 dvcman_call_on_receive + 360
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 13: 13  libfreerdp-client3.3.0.0.dylib      0x0000000104b024a0 dvcman_receive_channel_data + 1092
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 14: 14  libfreerdp-client3.3.0.0.dylib      0x0000000104afee88 drdynvc_process_data + 716
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 15: 15  libfreerdp-client3.3.0.0.dylib      0x0000000104afd0fc drdynvc_order_recv + 824
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 16: 16  libfreerdp-client3.3.0.0.dylib      0x0000000104afcb40 drdynvc_virtual_channel_event_data_received + 1180
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 17: 17  libfreerdp-client3.3.0.0.dylib      0x0000000104afb828 drdynvc_virtual_channel_open_event_ex + 432
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 18: 18  libfreerdp3.3.0.0.dylib             0x0000000105ab48a0 freerdp_channels_data + 1488
[19:37:52:705] [20912:6ba7b000] [FATAL][com.freerdp.winpr.assert] - [winpr_log_backtrace_ex]: 19: 19  libfreerdp3.3.0.0.dylib             0x0000000105b66154 freerdp_channel_process + 1764
[19:37:52:705] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [fatal_handler]: Caught signal 'Abort trap: 6' [6]
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 0: 0   libwinpr3.3.0.0.dylib               0x000000010631ee24 winpr_execinfo_backtrace + 336
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 1: 1   libwinpr3.3.0.0.dylib               0x000000010631895c winpr_backtrace + 24
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 2: 2   libwinpr3.3.0.0.dylib               0x0000000106318cb8 winpr_log_backtrace_ex + 304
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 3: 3   libwinpr3.3.0.0.dylib               0x0000000106318b7c winpr_log_backtrace + 44
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 4: 4   libfreerdp3.3.0.0.dylib             0x000000010591bf34 fatal_handler + 460
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 5: 5   libsystem_platform.dylib            0x000000018c466a24 _sigtramp + 56
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 6: 6   libsystem_pthread.dylib             0x000000018c437c28 pthread_kill + 288
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 7: 7   libsystem_c.dylib                   0x000000018c345ae8 abort + 180
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 8: 8   libfreerdp3.3.0.0.dylib             0x0000000105862740 rfx_message_free + 0
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 9: 9   libfreerdp3.3.0.0.dylib             0x0000000105865448 Stream_Seek + 144
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 10: 10  libfreerdp3.3.0.0.dylib             0x0000000105864264 rfx_process_message + 4848
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 11: 11  libfreerdp3.3.0.0.dylib             0x00000001059bb65c gdi_SurfaceCommand_RemoteFX + 1756
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 12: 12  libfreerdp3.3.0.0.dylib             0x00000001059b343c gdi_SurfaceCommand + 1364
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 13: 13  libfreerdp-client3.3.0.0.dylib      0x0000000104b96f5c rdpgfx_decode + 652
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 14: 14  libfreerdp-client3.3.0.0.dylib      0x0000000104b827b0 rdpgfx_recv_wire_to_surface_1_pdu + 5360
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 15: 15  libfreerdp-client3.3.0.0.dylib      0x0000000104b8000c rdpgfx_recv_pdu + 1064
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 16: 16  libfreerdp-client3.3.0.0.dylib      0x0000000104b7f140 rdpgfx_on_data_received + 1096
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 17: 17  libfreerdp-client3.3.0.0.dylib      0x0000000104b02634 dvcman_call_on_receive + 360
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 18: 18  libfreerdp-client3.3.0.0.dylib      0x0000000104b024a0 dvcman_receive_channel_data + 1092
[19:37:52:706] [20912:6ba7b000] [ERROR][com.freerdp.utils.signal] - [winpr_log_backtrace_ex]: 19: 19  libfreerdp-client3.3.0.0.dylib      0x0000000104afee88 drdynvc_process_data + 716

Severity

Moderate

CVE ID

CVE-2023-39350

Weaknesses

No CWEs

Credits