Bug#964195: guacamole-client: CVE-2020-9497 and CVE-2020-9498
Markus Koschany
apo at debian.org
Fri Nov 6 22:07:18 GMT 2020
Control: tags -1 patch
Hi,
I'm attaching my patch for Stretch to this bug report. Since the
versions in Stretch and unstable are identical, it should work there
too. However I don't intend to NMU guacamole-server because I believe a
new upstream version should be packaged instead.
Regards,
Markus
-------------- next part --------------
diff -Nru guacamole-server-0.9.9/debian/patches/CVE-2020-9497-and-CVE-2020-9498.patch guacamole-server-0.9.9/debian/patches/CVE-2020-9497-and-CVE-2020-9498.patch
--- guacamole-server-0.9.9/debian/patches/CVE-2020-9497-and-CVE-2020-9498.patch 1970-01-01 01:00:00.000000000 +0100
+++ guacamole-server-0.9.9/debian/patches/CVE-2020-9497-and-CVE-2020-9498.patch 2020-11-06 22:44:56.000000000 +0100
@@ -0,0 +1,355 @@
+From: Markus Koschany <apo at debian.org>
+Date: Tue, 3 Nov 2020 13:45:20 +0100
+Subject: CVE-2020-9497 and CVE-2020-9498
+
+Bug-Debian: https://bugs.debian.org/964195
+Origin: https://github.com/apache/guacamole-server/commit/a0e11dc81727528224d28466903454e1cb0266bb
+---
+ src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c | 40 ++++++++++++++++++++++
+ .../rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c | 12 +++++++
+ src/protocols/rdp/guac_rdpdr/rdpdr_messages.c | 18 ++++++++++
+ src/protocols/rdp/guac_rdpdr/rdpdr_printer.c | 7 ++++
+ src/protocols/rdp/guac_rdpdr/rdpdr_service.c | 3 ++
+ src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c | 29 ++++++++++++++++
+ src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c | 5 +++
+ 7 files changed, 114 insertions(+)
+
+diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c
+index bfd8ead..10d41bb 100644
+--- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c
++++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c
+@@ -58,6 +58,10 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device,
+ int create_disposition, create_options, path_length;
+ char path[GUAC_RDP_FS_MAX_PATH];
+
++ /* Check remaining stream data prior to reading. */
++ if (Stream_GetRemainingLength(input_stream) < 32)
++ return;
++
+ /* Read "create" information */
+ Stream_Read_UINT32(input_stream, desired_access);
+ Stream_Seek_UINT64(input_stream); /* allocation size */
+@@ -67,6 +71,11 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device,
+ Stream_Read_UINT32(input_stream, create_options);
+ Stream_Read_UINT32(input_stream, path_length);
+
++ /* Check to make sure the stream contains path_length bytes. */
++ if(Stream_GetRemainingLength(input_stream) < path_length) {
++ return;
++ }
++
+ /* Convert path to UTF-8 */
+ guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1,
+ path, sizeof(path));
+@@ -133,6 +142,10 @@ void guac_rdpdr_fs_process_read(guac_rdpdr_device* device,
+
+ wStream* output_stream;
+
++ /* Check remaining bytes before reading stream. */
++ if (Stream_GetRemainingLength(input_stream) < 12)
++ return;
++
+ /* Read packet */
+ Stream_Read_UINT32(input_stream, length);
+ Stream_Read_UINT64(input_stream, offset);
+@@ -181,6 +194,10 @@ void guac_rdpdr_fs_process_write(guac_rdpdr_device* device,
+
+ wStream* output_stream;
+
++ /* Check remaining length. */
++ if (Stream_GetRemainingLength(input_stream) < 32)
++ return;
++
+ /* Read packet */
+ Stream_Read_UINT32(input_stream, length);
+ Stream_Read_UINT64(input_stream, offset);
+@@ -190,6 +207,11 @@ void guac_rdpdr_fs_process_write(guac_rdpdr_device* device,
+ "%s: [file_id=%i] length=%i, offset=%" PRIu64,
+ __func__, file_id, length, (uint64_t) offset);
+
++ /* Check to make sure stream contains at least length bytes */
++ if (Stream_GetRemainingLength(input_stream) < length) {
++ return;
++ }
++
+ /* Attempt write */
+ bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data, file_id,
+ offset, Stream_Pointer(input_stream), length);
+@@ -252,6 +274,10 @@ void guac_rdpdr_fs_process_volume_info(guac_rdpdr_device* device, wStream* input
+
+ int fs_information_class;
+
++ /* Check remaining length */
++ if (Stream_GetRemainingLength(input_stream) < 4)
++ return;
++
+ Stream_Read_UINT32(input_stream, fs_information_class);
+
+ /* Dispatch to appropriate class-specific handler */
+@@ -294,6 +320,10 @@ void guac_rdpdr_fs_process_file_info(guac_rdpdr_device* device, wStream* input_s
+
+ int fs_information_class;
+
++ /* Check remaining length */
++ if (Stream_GetRemainingLength(input_stream) < 4)
++ return;
++
+ Stream_Read_UINT32(input_stream, fs_information_class);
+
+ /* Dispatch to appropriate class-specific handler */
+@@ -341,6 +371,10 @@ void guac_rdpdr_fs_process_set_file_info(guac_rdpdr_device* device,
+ int fs_information_class;
+ int length;
+
++ /* Check remaining length */
++ if (Stream_GetRemainingLength(input_stream) < 32)
++ return;
++
+ Stream_Read_UINT32(input_stream, fs_information_class);
+ Stream_Read_UINT32(input_stream, length); /* Length */
+ Stream_Seek(input_stream, 24); /* Padding */
+@@ -423,6 +457,9 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i
+ if (file == NULL)
+ return;
+
++ if (Stream_GetRemainingLength(input_stream) < 9)
++ return;
++
+ /* Read main header */
+ Stream_Read_UINT32(input_stream, fs_information_class);
+ Stream_Read_UINT8(input_stream, initial_query);
+@@ -431,6 +468,9 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i
+ /* If this is the first query, the path is included after padding */
+ if (initial_query) {
+
++ if (Stream_GetRemainingLength(input_stream) < 23 + path_length)
++ return;
++
+ Stream_Seek(input_stream, 23); /* Padding */
+
+ /* Convert path to UTF-8 */
+diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c
+index a0a7a73..99711fe 100644
+--- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c
++++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c
+@@ -143,11 +143,19 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device,
+ wStream* output_stream;
+ char destination_path[GUAC_RDP_FS_MAX_PATH];
+
++ /* Check stream size prior to reading. */
++ if (Stream_GetRemainingLength(input_stream) < 6)
++ return;
++
+ /* Read structure */
+ Stream_Seek_UINT8(input_stream); /* ReplaceIfExists */
+ Stream_Seek_UINT8(input_stream); /* RootDirectory */
+ Stream_Read_UINT32(input_stream, filename_length); /* FileNameLength */
+
++ if (Stream_GetRemainingLength(input_stream) < filename_length) {
++ return;
++ }
++
+ /* Convert name to UTF-8 */
+ guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), filename_length/2,
+ destination_path, sizeof(destination_path));
+@@ -199,6 +207,10 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdpdr_device* device,
+ UINT64 size;
+ wStream* output_stream;
+
++ if (Stream_GetRemainingLength(input_stream) < 8) {
++ return;
++ }
++
+ /* Read new size */
+ Stream_Read_UINT64(input_stream, size); /* AllocationSize */
+
+diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c
+index aa11532..0ef2fbf 100644
+--- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c
++++ b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c
+@@ -150,6 +150,9 @@ void guac_rdpdr_process_server_announce(guac_rdpdrPlugin* rdpdr,
+
+ unsigned int major, minor, client_id;
+
++ if (Stream_GetRemainingLength(input_stream) < 8)
++ return;
++
+ Stream_Read_UINT16(input_stream, major);
+ Stream_Read_UINT16(input_stream, minor);
+ Stream_Read_UINT32(input_stream, client_id);
+@@ -177,6 +180,9 @@ void guac_rdpdr_process_device_reply(guac_rdpdrPlugin* rdpdr, wStream* input_str
+ unsigned int device_id, ntstatus;
+ int severity, c, n, facility, code;
+
++ if (Stream_GetRemainingLength(input_stream) < 8)
++ return;
++
+ Stream_Read_UINT32(input_stream, device_id);
+ Stream_Read_UINT32(input_stream, ntstatus);
+
+@@ -210,6 +216,9 @@ void guac_rdpdr_process_device_iorequest(guac_rdpdrPlugin* rdpdr, wStream* input
+
+ int device_id, file_id, completion_id, major_func, minor_func;
+
++ if (Stream_GetRemainingLength(input_stream) < 20)
++ return;
++
+ /* Read header */
+ Stream_Read_UINT32(input_stream, device_id);
+ Stream_Read_UINT32(input_stream, file_id);
+@@ -237,6 +246,9 @@ void guac_rdpdr_process_server_capability(guac_rdpdrPlugin* rdpdr, wStream* inpu
+ int count;
+ int i;
+
++ if (Stream_GetRemainingLength(input_stream) < 4)
++ return;
++
+ /* Read header */
+ Stream_Read_UINT16(input_stream, count);
+ Stream_Seek(input_stream, 2);
+@@ -247,9 +259,15 @@ void guac_rdpdr_process_server_capability(guac_rdpdrPlugin* rdpdr, wStream* inpu
+ int type;
+ int length;
+
++ if (Stream_GetRemainingLength(input_stream) < 4)
++ break;
++
+ Stream_Read_UINT16(input_stream, type);
+ Stream_Read_UINT16(input_stream, length);
+
++ if (Stream_GetRemainingLength(input_stream) < (length - 4))
++ break;
++
+ /* Ignore all for now */
+ guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring server capability set type=0x%04x, length=%i", type, length);
+ Stream_Seek(input_stream, length - 4);
+diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c
+index 7aca701..4880304 100644
+--- a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c
++++ b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c
+@@ -190,6 +190,9 @@ void guac_rdpdr_process_print_job_write(guac_rdpdr_device* device,
+ int status=0, length;
+ unsigned char* buffer;
+
++ if (Stream_GetRemainingLength(input_stream) < 32)
++ return;
++
+ wStream* output_stream;
+
+ Stream_Read_UINT32(input_stream, length);
+@@ -197,6 +200,10 @@ void guac_rdpdr_process_print_job_write(guac_rdpdr_device* device,
+ Stream_Seek(input_stream, 20); /* Padding */
+ buffer = Stream_Pointer(input_stream);
+
++ if (Stream_GetRemainingLength(input_stream) < length) {
++ return;
++ }
++
+ /* Create print job, if not yet created */
+ if (printer_data->bytes_received == 0) {
+
+diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c b/src/protocols/rdp/guac_rdpdr/rdpdr_service.c
+index 9be53f7..5d507ec 100644
+--- a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c
++++ b/src/protocols/rdp/guac_rdpdr/rdpdr_service.c
+@@ -137,6 +137,9 @@ void guac_rdpdr_process_receive(rdpSvcPlugin* plugin,
+ int component;
+ int packet_id;
+
++ if (Stream_GetRemainingLength(input_stream) < 4)
++ return;
++
+ /* Read header */
+ Stream_Read_UINT16(input_stream, component);
+ Stream_Read_UINT16(input_stream, packet_id);
+diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c
+index a0827d3..8b58daa 100644
+--- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c
++++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c
+@@ -61,6 +61,10 @@ void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd,
+ /* Get audio stream from client data */
+ guac_audio_stream* audio = client_data->audio;
+
++ if (Stream_GetRemainingLength(input_stream) < 20) {
++ return;
++ }
++
+ /* Format header */
+ Stream_Seek(input_stream, 14);
+ Stream_Read_UINT16(input_stream, server_format_count);
+@@ -107,6 +111,11 @@ void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd,
+ /* Remember position in stream */
+ Stream_GetPointer(input_stream, format_start);
+
++ /* Check to make sure Stream has at least 18 bytes. */
++ if (Stream_GetRemainingLength(input_stream) < 18) {
++ return;
++ }
++
+ /* Read format */
+ Stream_Read_UINT16(input_stream, format_tag);
+ Stream_Read_UINT16(input_stream, channels);
+@@ -119,6 +128,11 @@ void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd,
+ Stream_Read_UINT16(input_stream, body_size);
+ Stream_Seek(input_stream, body_size);
+
++ /* Check that Stream has at least body_size bytes remaining. */
++ if (Stream_GetRemainingLength(input_stream) < body_size) {
++ return;
++ }
++
+ /* If PCM, accept */
+ if (format_tag == WAVE_FORMAT_PCM) {
+
+@@ -220,6 +234,11 @@ void guac_rdpsnd_training_handler(guac_rdpsndPlugin* rdpsnd,
+ guac_client* client = rdpsnd->client;
+ rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data;
+
++ /* Check to make sure audio stream contains a minimum number of bytes. */
++ if (Stream_GetRemainingLength(input_stream) < 4) {
++ return;
++ }
++
+ /* Read timestamp and data size */
+ Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp);
+ Stream_Read_UINT16(input_stream, data_size);
+@@ -250,6 +269,11 @@ void guac_rdpsnd_wave_info_handler(guac_rdpsndPlugin* rdpsnd,
+ /* Get audio stream from client data */
+ guac_audio_stream* audio = client_data->audio;
+
++ /* Check to make sure audio stream contains a minimum number of bytes. */
++ if (Stream_GetRemainingLength(input_stream) < 12) {
++ return;
++ }
++
+ /* Read wave information */
+ Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp);
+ Stream_Read_UINT16(input_stream, format);
+@@ -288,6 +312,11 @@ void guac_rdpsnd_wave_handler(guac_rdpsndPlugin* rdpsnd,
+ /* Get audio stream from client data */
+ guac_audio_stream* audio = client_data->audio;
+
++ /* Verify that the stream has bytes to cover the wave size plus header. */
++ if (Stream_Length(input_stream) < (rdpsnd->incoming_wave_size + 4)) {
++ return;
++ }
++
+ /* Wave Confirmation PDU */
+ wStream* output_stream = Stream_New(NULL, 8);
+
+diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c
+index 30810ef..88e5c75 100644
+--- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c
++++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c
+@@ -104,6 +104,11 @@ void guac_rdpsnd_process_receive(rdpSvcPlugin* plugin,
+ guac_rdpsndPlugin* rdpsnd = (guac_rdpsndPlugin*) plugin;
+ guac_rdpsnd_pdu_header header;
+
++ /* Check that we have at least the 4 byte header (UINT8 + UINT8 + UINT16) */
++ if (Stream_GetRemainingLength(input_stream) < 4) {
++ return;
++ }
++
+ /* Read RDPSND PDU header */
+ Stream_Read_UINT8(input_stream, header.message_type);
+ Stream_Seek_UINT8(input_stream);
diff -Nru guacamole-server-0.9.9/debian/patches/series guacamole-server-0.9.9/debian/patches/series
--- guacamole-server-0.9.9/debian/patches/series 2016-11-30 16:18:15.000000000 +0100
+++ guacamole-server-0.9.9/debian/patches/series 2020-11-06 22:44:56.000000000 +0100
@@ -1,3 +1,4 @@
openssl-1.1.patch
fix-buildsystem.patch
fix-lfs.patch
+CVE-2020-9497-and-CVE-2020-9498.patch
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xD9AD14B9513B51E4.asc
Type: application/pgp-keys
Size: 49647 bytes
Desc: not available
URL: <http://alioth-lists.debian.net/pipermail/pkg-remote-team/attachments/20201106/c90c2fb4/attachment-0001.key>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://alioth-lists.debian.net/pipermail/pkg-remote-team/attachments/20201106/c90c2fb4/attachment-0001.sig>
More information about the pkg-remote-team
mailing list