Skip to content

Commit 766ebcf

Browse files
committed
Malicious RDP server security fixes
This commit includes fixes for a set of 21 vulnerabilities in rdesktop when a malicious RDP server is used. All vulnerabilities was identified and reported by Eyal Itkin. * Add rdp_protocol_error function that is used in several fixes * Refactor of process_bitmap_updates * Fix possible integer overflow in s_check_rem() on 32bit arch * Fix memory corruption in process_bitmap_data - CVE-2018-8794 * Fix remote code execution in process_bitmap_data - CVE-2018-8795 * Fix remote code execution in process_plane - CVE-2018-8797 * Fix Denial of Service in mcs_recv_connect_response - CVE-2018-20175 * Fix Denial of Service in mcs_parse_domain_params - CVE-2018-20175 * Fix Denial of Service in sec_parse_crypt_info - CVE-2018-20176 * Fix Denial of Service in sec_recv - CVE-2018-20176 * Fix minor information leak in rdpdr_process - CVE-2018-8791 * Fix Denial of Service in cssp_read_tsrequest - CVE-2018-8792 * Fix remote code execution in cssp_read_tsrequest - CVE-2018-8793 * Fix Denial of Service in process_bitmap_data - CVE-2018-8796 * Fix minor information leak in rdpsnd_process_ping - CVE-2018-8798 * Fix Denial of Service in process_secondary_order - CVE-2018-8799 * Fix remote code execution in in ui_clip_handle_data - CVE-2018-8800 * Fix major information leak in ui_clip_handle_data - CVE-2018-20174 * Fix memory corruption in rdp_in_unistr - CVE-2018-20177 * Fix Denial of Service in process_demand_active - CVE-2018-20178 * Fix remote code execution in lspci_process - CVE-2018-20179 * Fix remote code execution in rdpsnddbg_process - CVE-2018-20180 * Fix remote code execution in seamless_process - CVE-2018-20181 * Fix remote code execution in seamless_process_line - CVE-2018-20182
1 parent b4ee02d commit 766ebcf

16 files changed

Lines changed: 270 additions & 69 deletions

File tree

asn.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
/* Parse an ASN.1 BER header */
2424
RD_BOOL
25-
ber_parse_header(STREAM s, int tagval, int *length)
25+
ber_parse_header(STREAM s, int tagval, uint32 *length)
2626
{
2727
int tag, len;
2828

bitmap.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -785,15 +785,15 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
785785
replen = revcode;
786786
collen = 0;
787787
}
788-
while (collen > 0)
788+
while (indexw < width && collen > 0)
789789
{
790790
color = CVAL(in);
791791
*out = color;
792792
out += 4;
793793
indexw++;
794794
collen--;
795795
}
796-
while (replen > 0)
796+
while (indexw < width && replen > 0)
797797
{
798798
*out = color;
799799
out += 4;
@@ -815,7 +815,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
815815
replen = revcode;
816816
collen = 0;
817817
}
818-
while (collen > 0)
818+
while (indexw < width && collen > 0)
819819
{
820820
x = CVAL(in);
821821
if (x & 1)
@@ -835,7 +835,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
835835
indexw++;
836836
collen--;
837837
}
838-
while (replen > 0)
838+
while (indexw < width && replen > 0)
839839
{
840840
x = last_line[indexw * 4] + color;
841841
*out = x;

cliprdr.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ cliprdr_process(STREAM s)
115115
uint16 type, status;
116116
uint32 length, format;
117117
uint8 *data;
118+
struct stream packet = *s;
118119

119120
in_uint16_le(s, type);
120121
in_uint16_le(s, status);
@@ -123,6 +124,11 @@ cliprdr_process(STREAM s)
123124

124125
DEBUG_CLIPBOARD(("CLIPRDR recv: type=%d, status=%d, length=%d\n", type, status, length));
125126

127+
if (!s_check_rem(s, length))
128+
{
129+
rdp_protocol_error("cliprdr_process(), consume of packet from stream would overrun", &packet);
130+
}
131+
126132
if (status == CLIPRDR_ERROR)
127133
{
128134
switch (type)

constants.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,10 @@ enum RDP_INPUT_DEVICE
481481
#define FILE_DELETE_ON_CLOSE 0x00001000
482482
#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000
483483

484+
/* [MS-RDPBCGR], TS_BITMAP_DATA, flags */
485+
#define BITMAP_COMPRESSION 0x0001
486+
#define NO_BITMAP_COMPRESSION_HDR 0x0400
487+
484488
/* RDP5 disconnect PDU */
485489
#define exDiscReasonNoInfo 0x0000
486490
#define exDiscReasonAPIInitiatedDisconnect 0x0001

cssp.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
648648
STREAM s;
649649
int length;
650650
int tagval;
651+
struct stream packet;
651652

652653
s = tcp_recv(NULL, 4);
653654

@@ -673,6 +674,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
673674

674675
// receive the remainings of message
675676
s = tcp_recv(s, length);
677+
packet = *s;
676678

677679
#if WITH_DEBUG_CREDSSP
678680
streamsave(s, "tsrequest_in.raw");
@@ -689,6 +691,12 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
689691
if (!ber_in_header(s, &tagval, &length) ||
690692
tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
691693
return False;
694+
695+
if (!s_check_rem(s, length))
696+
{
697+
rdp_protocol_error("cssp_read_tsrequest(), consume of version from stream would overrun",
698+
&packet);
699+
}
692700
in_uint8s(s, length);
693701

694702
// negoToken [1]
@@ -710,7 +718,14 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
710718
if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING)
711719
return False;
712720

713-
token->end = token->p = token->data;
721+
if (!s_check_rem(s, length))
722+
{
723+
rdp_protocol_error("cssp_read_tsrequest(), consume of token from stream would overrun",
724+
&packet);
725+
}
726+
727+
s_realloc(token, length);
728+
s_reset(token);
714729
out_uint8p(token, s->p, length);
715730
s_mark_end(token);
716731
}

lspci.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/* -*- c-basic-offset: 8 -*-
22
rdesktop: A Remote Desktop Protocol client.
33
Support for the Matrox "lspci" channel
4-
Copyright (C) 2005 Matrox Graphics Inc.
4+
Copyright (C) 2005 Matrox Graphics Inc.
5+
Copyright 2018 Henrik Andersson <hean01@cendio.se> for Cendio AB
56
67
This program is free software: you can redistribute it and/or modify
78
it under the terms of the GNU General Public License as published by
@@ -132,6 +133,12 @@ lspci_process(STREAM s)
132133
unsigned int pkglen;
133134
static char *rest = NULL;
134135
char *buf;
136+
struct stream packet = *s;
137+
138+
if (!s_check(s))
139+
{
140+
rdp_protocol_error("lspci_process(), stream is in unstable state", &packet);
141+
}
135142

136143
pkglen = s->end - s->p;
137144
/* str_handle_lines requires null terminated strings */

mcs.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,16 @@ mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens,
4444
static RD_BOOL
4545
mcs_parse_domain_params(STREAM s)
4646
{
47-
int length;
47+
uint32 length;
48+
struct stream packet = *s;
4849

4950
ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
51+
52+
if (!s_check_rem(s, length))
53+
{
54+
rdp_protocol_error("mcs_parse_domain_params(), consume domain params from stream would overrun", &packet);
55+
}
56+
5057
in_uint8s(s, length);
5158

5259
return s_check(s);
@@ -87,13 +94,15 @@ static RD_BOOL
8794
mcs_recv_connect_response(STREAM mcs_data)
8895
{
8996
uint8 result;
90-
int length;
97+
uint32 length;
9198
STREAM s;
92-
99+
struct stream packet;
93100
s = iso_recv(NULL);
94101
if (s == NULL)
95102
return False;
96103

104+
packet = *s;
105+
97106
ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);
98107

99108
ber_parse_header(s, BER_TAG_RESULT, &length);
@@ -106,6 +115,12 @@ mcs_recv_connect_response(STREAM mcs_data)
106115

107116
ber_parse_header(s, BER_TAG_INTEGER, &length);
108117
in_uint8s(s, length); /* connect id */
118+
119+
if (!s_check_rem(s, length))
120+
{
121+
rdp_protocol_error("mcs_recv_connect_response(), consume connect id from stream would overrun", &packet);
122+
}
123+
109124
mcs_parse_domain_params(s);
110125

111126
ber_parse_header(s, BER_TAG_OCTET_STRING, &length);

orders.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,11 +1260,17 @@ process_secondary_order(STREAM s)
12601260
uint16 flags;
12611261
uint8 type;
12621262
uint8 *next_order;
1263+
struct stream packet = *s;
12631264

12641265
in_uint16_le(s, length);
12651266
in_uint16_le(s, flags); /* used by bmpcache2 */
12661267
in_uint8(s, type);
12671268

1269+
if (!s_check_rem(s, length + 7))
1270+
{
1271+
rdp_protocol_error("process_secondary_order(), next order pointer would overrun stream", &packet);
1272+
}
1273+
12681274
next_order = s->p + (sint16) length + 7;
12691275

12701276
switch (type)

parse.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ typedef struct stream
4040
#define s_pop_layer(s,h) (s)->p = (s)->h;
4141
#define s_mark_end(s) (s)->end = (s)->p;
4242
#define s_check(s) ((s)->p <= (s)->end)
43-
#define s_check_rem(s,n) ((s)->p + n <= (s)->end)
43+
#define s_check_rem(s,n) (s_check(s) && (n <= (s)->end - (s)->p))
4444
#define s_check_end(s) ((s)->p == (s)->end)
4545
#define s_length(s) ((s)->end - (s)->data)
4646
#define s_reset(s) ((s)->end = (s)->p = (s)->data)

proto.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ RD_BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, ch
173173
char *directory, RD_BOOL reconnect);
174174
void rdp_reset_state(void);
175175
void rdp_disconnect(void);
176+
void rdp_protocol_error(const char *message, STREAM s);
176177
/* rdpdr.c */
177178
int get_device_index(RD_NTHANDLE handle);
178179
void convert_to_unix_filename(char *filename);
@@ -233,7 +234,7 @@ void tcp_run_ui(RD_BOOL run);
233234
/* asn.c */
234235
RD_BOOL ber_in_header(STREAM s, int *tagval, int *length);
235236
void ber_out_header(STREAM s, int tagval, int length);
236-
RD_BOOL ber_parse_header(STREAM s, int tagval, int *length);
237+
RD_BOOL ber_parse_header(STREAM s, int tagval, uint32 *length);
237238
void ber_out_integer(STREAM s, int value);
238239

239240
/* xclip.c */

0 commit comments

Comments
 (0)