Headline
CVE-2023-39350: Incorrect offset calculation leading to DOS
FreeRDP is a free implementation of the Remote Desktop Protocol (RDP), released under the Apache license. This issue affects Clients only. Integer underflow leading to DOS (e.g. abort due to WINPR_ASSERT
with default compilation flags). 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. This issue has been addressed in versions 2.11.0 and 3.0.0-beta3. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Affected versions
<= 2.10.0 , <=3.0.0-beta2
Patched versions
2.11.0, 3.0.0-beta3
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
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
- WBT_CONTEXT <= blockType <= WBT_EXTENSION
- blockLen == 7
- 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
Related news
Gentoo Linux Security Advisory 202401-16 - Multiple vulnerabilities have been discovered in FreeRDP, the worst of which could result in code execution. Versions greater than or equal to 2.11.0 are affected.
Ubuntu Security Notice 6401-1 - It was discovered that FreeRDP did not properly manage certain inputs. A malicious server could use this issue to cause FreeRDP clients to crash, resulting in a denial of service, or possibly obtain sensitive information. It was discovered that FreeRDP did not properly manage certain inputs. A malicious server could use this issue to cause FreeRDP clients to crash, resulting in a denial of service, or possibly execute arbitrary code.