Talos Vulnerability Report

TALOS-2017-0402

Cesanta Mongoose MQTT SUBSCRIBE Topic Length Information Leak

October 31, 2017
CVE Number

CVE-2017-2895

Summary

An exploitable arbitrary memory read vulnerability exists in the MQTT packet parsing functionality of Cesanta Mongoose 6.8. A specially crafted MQTT SUBSCRIBE packet can cause an arbitrary out-of=bounds memory read potentially resulting in information disclosure and denial of service. An attacker needs to send a specially crafted MQTT packet over the network to trigger this vulnerability.

Tested Versions

Cesanta Mongoose 6.8

Product URLs

https://cesanta.com/

CVSSv3 Score

8.2 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H

CWE

CWE-190: Integer Overflow or Wraparound

Details

Mongoose is a monolithic library implementing a number of networking protocols, including HTTP, MQTT, MDNS and others. It is designed with embedded devices in mind and as such is used in many IoT devices and runs on virtually all platforms.

While parsing an MQTT packet SUBSCRIBE command, topic string size as encoded in the packet is trusted without any additional validation. This arbitrary length value is used in pointer arithmetic and can cause out-of-bounds memory access. The vulnerability occurs in function mg_mqtt_next_subscribe_topic:

int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg,
                              struct mg_str *topic, uint8_t *qos, int pos) {
 unsigned char *buf = (unsigned char *) msg->payload.p + pos;

 if ((size_t) pos >= msg->payload.len) {
 return -1;


 topic->len = buf[0] << 8 | buf[1];         [1]
 topic->p = (char *) buf + 2;
 *qos = buf[2 + topic->len];                [2]
 return pos + 2 + topic->len + 1;

In the above code, at [1] two bytes from message buffer are read as topic->len and then immediatelly used at [2] to calculate offset to qos. No check is performed to insure it would be inside the bounds of the buffer which is limited in size. This issue can be triggered multiple times and with careful control of the memory layout could be abused to leak memory and cause denial of service.

The vulnerability can be triggered by sending the supplied proof of concept packet to the sample mqtt_broker application supplied with the library.

Crash Information

Address Sanitizer output:
==118728==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x619000014986 at pc 0x00000051e4c5 bp 0x7fffffffaf50 sp        
0x7fffffffaf48
READ of size 1 at 0x619000014986 thread T0
  #0 0x51e4c4  (/home/user/mongoose/examples/mqtt_broker/mqtt_broker+0x51e4c4)
  #1 0x515174  (/home/user/mongoose/examples/mqtt_broker/mqtt_broker+0x515174)
  #2 0x4fa825  (/home/user/mongoose/examples/mqtt_broker/mqtt_broker+0x4fa825)
  #3 0x4fea17  (/home/user/mongoose/examples/mqtt_broker/mqtt_broker+0x4fea17)
  #4 0x50a8e7  (/home/user/mongoose/examples/mqtt_broker/mqtt_broker+0x50a8e7)
  #5 0x50efa8  (/home/user/mongoose/examples/mqtt_broker/mqtt_broker+0x50efa8)
  #6 0x4fc145  (/home/user/mongoose/examples/mqtt_broker/mqtt_broker+0x4fc145)
  #7 0x4eb5ea  (/home/user/mongoose/examples/mqtt_broker/mqtt_broker+0x4eb5ea)
  #8 0x7ffff683882f  (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
  #9 0x419978  (/home/user/mongoose/examples/mqtt_broker/mqtt_broker+0x419978)


AddressSanitizer can not describe address in more detail (wild memory access suspected).
SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/user/mongoose/examples/mqtt_broker/mqtt_broker+0x51e4c4)
Shadow bytes around the buggy address:
  0x0c327fffa8e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffa8f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffa900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffa910: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffa920: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c327fffa930:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffa940: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffa950: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffa960: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffa970: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffa980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  ddressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  ==118728==ABORTING

Timeline

2017-08-30 - Vendor Disclosure
2017-10-31 - Public Release

Credit

Discovered by Aleksandar Nikolic of Cisco Talos.