Skip to content

Commit

Permalink
Malicious RDP server security fixes
Browse files Browse the repository at this point in the history
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
  • Loading branch information
hean01-cendio committed Jan 2, 2019
1 parent b4ee02d commit 766ebcf
Show file tree
Hide file tree
Showing 16 changed files with 270 additions and 69 deletions.
2 changes: 1 addition & 1 deletion asn.c
Expand Up @@ -22,7 +22,7 @@

/* Parse an ASN.1 BER header */
RD_BOOL
ber_parse_header(STREAM s, int tagval, int *length)
ber_parse_header(STREAM s, int tagval, uint32 *length)
{
int tag, len;

Expand Down
8 changes: 4 additions & 4 deletions bitmap.c
Expand Up @@ -785,15 +785,15 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
replen = revcode;
collen = 0;
}
while (collen > 0)
while (indexw < width && collen > 0)
{
color = CVAL(in);
*out = color;
out += 4;
indexw++;
collen--;
}
while (replen > 0)
while (indexw < width && replen > 0)
{
*out = color;
out += 4;
Expand All @@ -815,7 +815,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
replen = revcode;
collen = 0;
}
while (collen > 0)
while (indexw < width && collen > 0)
{
x = CVAL(in);
if (x & 1)
Expand All @@ -835,7 +835,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
indexw++;
collen--;
}
while (replen > 0)
while (indexw < width && replen > 0)
{
x = last_line[indexw * 4] + color;
*out = x;
Expand Down
6 changes: 6 additions & 0 deletions cliprdr.c
Expand Up @@ -115,6 +115,7 @@ cliprdr_process(STREAM s)
uint16 type, status;
uint32 length, format;
uint8 *data;
struct stream packet = *s;

in_uint16_le(s, type);
in_uint16_le(s, status);
Expand All @@ -123,6 +124,11 @@ cliprdr_process(STREAM s)

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

if (!s_check_rem(s, length))
{
rdp_protocol_error("cliprdr_process(), consume of packet from stream would overrun", &packet);
}

if (status == CLIPRDR_ERROR)
{
switch (type)
Expand Down
4 changes: 4 additions & 0 deletions constants.h
Expand Up @@ -481,6 +481,10 @@ enum RDP_INPUT_DEVICE
#define FILE_DELETE_ON_CLOSE 0x00001000
#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000

/* [MS-RDPBCGR], TS_BITMAP_DATA, flags */
#define BITMAP_COMPRESSION 0x0001
#define NO_BITMAP_COMPRESSION_HDR 0x0400

/* RDP5 disconnect PDU */
#define exDiscReasonNoInfo 0x0000
#define exDiscReasonAPIInitiatedDisconnect 0x0001
Expand Down
17 changes: 16 additions & 1 deletion cssp.c
Expand Up @@ -648,6 +648,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
STREAM s;
int length;
int tagval;
struct stream packet;

s = tcp_recv(NULL, 4);

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

// receive the remainings of message
s = tcp_recv(s, length);
packet = *s;

#if WITH_DEBUG_CREDSSP
streamsave(s, "tsrequest_in.raw");
Expand All @@ -689,6 +691,12 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
if (!ber_in_header(s, &tagval, &length) ||
tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
return False;

if (!s_check_rem(s, length))
{
rdp_protocol_error("cssp_read_tsrequest(), consume of version from stream would overrun",
&packet);
}
in_uint8s(s, length);

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

token->end = token->p = token->data;
if (!s_check_rem(s, length))
{
rdp_protocol_error("cssp_read_tsrequest(), consume of token from stream would overrun",
&packet);
}

s_realloc(token, length);
s_reset(token);
out_uint8p(token, s->p, length);
s_mark_end(token);
}
Expand Down
9 changes: 8 additions & 1 deletion lspci.c
@@ -1,7 +1,8 @@
/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
Support for the Matrox "lspci" channel
Copyright (C) 2005 Matrox Graphics Inc.
Copyright (C) 2005 Matrox Graphics Inc.
Copyright 2018 Henrik Andersson <hean01@cendio.se> for Cendio AB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -132,6 +133,12 @@ lspci_process(STREAM s)
unsigned int pkglen;
static char *rest = NULL;
char *buf;
struct stream packet = *s;

if (!s_check(s))
{
rdp_protocol_error("lspci_process(), stream is in unstable state", &packet);
}

pkglen = s->end - s->p;
/* str_handle_lines requires null terminated strings */
Expand Down
21 changes: 18 additions & 3 deletions mcs.c
Expand Up @@ -44,9 +44,16 @@ mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens,
static RD_BOOL
mcs_parse_domain_params(STREAM s)
{
int length;
uint32 length;
struct stream packet = *s;

ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);

if (!s_check_rem(s, length))
{
rdp_protocol_error("mcs_parse_domain_params(), consume domain params from stream would overrun", &packet);
}

in_uint8s(s, length);

return s_check(s);
Expand Down Expand Up @@ -87,13 +94,15 @@ static RD_BOOL
mcs_recv_connect_response(STREAM mcs_data)
{
uint8 result;
int length;
uint32 length;
STREAM s;

struct stream packet;
s = iso_recv(NULL);
if (s == NULL)
return False;

packet = *s;

ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);

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

ber_parse_header(s, BER_TAG_INTEGER, &length);
in_uint8s(s, length); /* connect id */

if (!s_check_rem(s, length))
{
rdp_protocol_error("mcs_recv_connect_response(), consume connect id from stream would overrun", &packet);
}

mcs_parse_domain_params(s);

ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
Expand Down
6 changes: 6 additions & 0 deletions orders.c
Expand Up @@ -1260,11 +1260,17 @@ process_secondary_order(STREAM s)
uint16 flags;
uint8 type;
uint8 *next_order;
struct stream packet = *s;

in_uint16_le(s, length);
in_uint16_le(s, flags); /* used by bmpcache2 */
in_uint8(s, type);

if (!s_check_rem(s, length + 7))
{
rdp_protocol_error("process_secondary_order(), next order pointer would overrun stream", &packet);
}

next_order = s->p + (sint16) length + 7;

switch (type)
Expand Down
2 changes: 1 addition & 1 deletion parse.h
Expand Up @@ -40,7 +40,7 @@ typedef struct stream
#define s_pop_layer(s,h) (s)->p = (s)->h;
#define s_mark_end(s) (s)->end = (s)->p;
#define s_check(s) ((s)->p <= (s)->end)
#define s_check_rem(s,n) ((s)->p + n <= (s)->end)
#define s_check_rem(s,n) (s_check(s) && (n <= (s)->end - (s)->p))
#define s_check_end(s) ((s)->p == (s)->end)
#define s_length(s) ((s)->end - (s)->data)
#define s_reset(s) ((s)->end = (s)->p = (s)->data)
Expand Down
3 changes: 2 additions & 1 deletion proto.h
Expand Up @@ -173,6 +173,7 @@ RD_BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, ch
char *directory, RD_BOOL reconnect);
void rdp_reset_state(void);
void rdp_disconnect(void);
void rdp_protocol_error(const char *message, STREAM s);
/* rdpdr.c */
int get_device_index(RD_NTHANDLE handle);
void convert_to_unix_filename(char *filename);
Expand Down Expand Up @@ -233,7 +234,7 @@ void tcp_run_ui(RD_BOOL run);
/* asn.c */
RD_BOOL ber_in_header(STREAM s, int *tagval, int *length);
void ber_out_header(STREAM s, int tagval, int length);
RD_BOOL ber_parse_header(STREAM s, int tagval, int *length);
RD_BOOL ber_parse_header(STREAM s, int tagval, uint32 *length);
void ber_out_integer(STREAM s, int value);

/* xclip.c */
Expand Down

0 comments on commit 766ebcf

Please sign in to comment.