Permalink
Browse files

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
  • Loading branch information...
hean01-cendio committed Jan 16, 2019
1 parent 1f13bf5 commit 4dca546d04321a610c1835010b5dad85163b65e1
Showing with 250 additions and 71 deletions.
  1. +1 −1 asn.c
  2. +4 −4 bitmap.c
  3. +6 −0 cliprdr.c
  4. +3 −0 constants.h
  5. +16 −1 cssp.c
  6. +8 −1 lspci.c
  7. +18 −2 mcs.c
  8. +6 −0 orders.c
  9. +2 −1 proto.h
  10. +132 −60 rdp.c
  11. +11 −0 rdpdr.c
  12. +11 −0 rdpsnd.c
  13. +12 −0 seamless.c
  14. +17 −0 secure.c
  15. +1 −1 stream.h
  16. +2 −0 types.h
2 asn.c
@@ -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;

@@ -794,15 +794,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;
@@ -824,7 +824,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)
@@ -844,7 +844,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;
@@ -118,6 +118,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);
@@ -127,6 +128,11 @@ cliprdr_process(STREAM s)
logger(Clipboard, Debug, "cliprdr_process(), type=%d, status=%d, length=%d", 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)
@@ -751,6 +751,9 @@ enum RDP_DESKTOP_ORIENTATION
#define ENC_SALTED_CHECKSUM 0x0010
#define NO_BITMAP_COMPRESSION_HDR 0x0400

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

/* orderFlags, [MS-RDPBCGR] 2.2.7.1.3 */
#define NEGOTIATEORDERSUPPORT 0x0002
#define ZEROBOUNDSDELTASSUPPORT 0x0008
17 cssp.c
@@ -595,6 +595,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
STREAM s;
int length;
int tagval;
struct stream packet;

s = tcp_recv(NULL, 4);

@@ -622,6 +623,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)

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

// parse the response and into nego token
if (!ber_in_header(s, &tagval, &length) ||
@@ -632,6 +634,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]
@@ -653,7 +661,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);
}
@@ -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
@@ -134,6 +135,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 */
20 mcs.c
@@ -45,9 +45,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);
@@ -89,8 +96,9 @@ mcs_recv_connect_response(STREAM mcs_data)
{
UNUSED(mcs_data);
uint8 result;
int length;
uint32 length;
STREAM s;
struct stream packet;
RD_BOOL is_fastpath;
uint8 fastpath_hdr;

@@ -99,6 +107,8 @@ mcs_recv_connect_response(STREAM mcs_data)

if (s == NULL)
return False;

packet = *s;

ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);

@@ -112,6 +122,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);
@@ -1259,11 +1259,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)
@@ -164,6 +164,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);
@@ -224,7 +225,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);
void ber_out_sequence(STREAM s, STREAM contents);

Oops, something went wrong.

0 comments on commit 4dca546

Please sign in to comment.