HexBrain

Internet Bug Bounty · Report #227344

CVE-2017-8798 - miniupnp getHTTPResponse chunked encoding integer signedness error

Validstatus
highseverity
2upvotes
12 Nov 2019disclosed

How it was found

Integer signedness error in miniupnpc [1] allows remote attackers to cause a denial of service condition (access violation and heap corruption) via specially crafted HTTP response

An integer signedness error was found in miniupnp's miniwget allowing an unauthenticated remote entity typically located on the local network segment to trigger a heap corruption or an access violation in miniupnp's http response parser when processing a specially crafted chunked-encoded response to a request for the xml root description url.

  • affects
  • all versions >= v1.4.20101221 (released 21/12/2010; ~6 years ago)
  • all configurations as its a core part of the library
  • impact
  • DoS (access violation due to buffer overread memcpy)
  • Heap Overwrite (pot. race RCE in multithreaded envs)
  • requirements
    • no user interaction, unauth, low complexity
  • how widespread is this software?
  • miniupnpc is compiled into a wide range of network applications and embedded device firmware.
  • blockchain clients: bitcoind and almost all forks, CPP ethereum, ...
  • p2p filesharing applications: qBittorrent, Transmission, ...
  • network device firmware: dlink, linksys, probably synology or anything that allows IGD management / portforwarding
  • numerous hits for miniwget on google or github. closed source obviously not included but its likely to find this lib packed with embedded devices.
  • disclosure
  • provided detailed description, PoC and patch
  • status: fixed; within 8 days.

The vulnerable component is a HTTP file download method called miniwget (precisely getHTTPResponse) that fails to properly handle invalid chunked-encoded HTTP responses. The root cause is a bounds check that mistakenly casts an unsigned attacker-provided chunksize to signed int leading to an incorrect decision on the destination heap buffer size when copying data from the server response to an internal buffer. The attacker controls both the size of the internal buffer as well as the number of bytes to copy. In order for this attack to succeed, the number of bytes to copy must be negative.

attacker controls:

  • int content_length
  • unsigned int chunksize
  • bytestocopy if (int) chunksize is negative (or at least < n-i ~ 1900 bytes)
  • length of content_buf if bytestocopy is negative

In the end, the attacker has almost full control of the following two methods

  • realloc(content_buf, content_length)
  • memcpy(content_buf+x, http_response, chunksize)

affected methods (almost all exposed API):

    basically all `miniwget*` and `UPNP_*` methods.
    * getHTTPResponse (vulnerable)
      * miniwget3
       * miniwget2
        * miniwget
        * miniwget_getaddr
         * UPNP_GetIGDFromUrl
         * UPNP_GetValidIGD
          * UPnP_selectigd
      * UPNP_Get*
      * UPNP_Check*
      * UPNP_Delete*
      * UPNP_Update*
      * UPNP_Add*

This vulnerability is easily exploitable with an attacker being on the same network segment/multicast domain by answering SSDP discovery requests (1) (or sending notification requests) providing an URL to the attacker controlled webserver. Answering this request (2) makes upnp clients download a description file from that webserver (3)(4) in order to learn more about the capabilities of the Internet Gateway Device (IGD). By providing a negative chunk length in the chunked-encoded answer (4) to this request the malicious webserver triggers the vulnerability. This way one malicous client could exploit all other clients in the same multicast domain. (Funny sidenote: I had to implement a target ip filter otherwise the PoC would attract devices like a magnet and crash all of them)

      client (miniupnpc)                         server (poc.py)
          |                                         |
          |                                         |
          | SSDP:  Discovery - M-SEARCH             |
      1.  | --------------------------------------> |
          |                                         |
          | SSDP:  Reply - Location Header          |
      2.  | <-------------------------------------- |
          |                                         |
          | SCPD:  GET (Location Header/xxxx.xml)   |
      3.  | --------------------------------------> |
          |                                         |
          | SCPD:  HTTP chunked-encoded reply       |
      4.  | <-------------------------------------- |
          |                                         |

Note: the vulnerability is basically not bound to the adjacent network since miniwget could also be used to download arbitrary files on the internet. This is just the most common/typical vector, otherwise the CVSS score would be higher.

Disclosure

coordinated disclosure and reported to the miniupnp project owner, provided detailed vulnerability analysis, a one-click exploit all PoC and a minimal patch. The patch was accepted with minor changes. Fixed within a few days of first contact (May 1st ->May 9th).

details and the actual research material that was securely shared with the miniupnp project is going to be be pushed to the following github repository once vendors picked up the changes: https://github.com/tintinweb/pub/tree/master/pocs/cve-2017-8798

Vendor response [2] and Patch [3]

❤ Thanks to miniupnp for treating this with priority.

[1] http://miniupnp.free.fr [2] http://miniupnp.free.fr/files/changelog.php?file=miniupnpc-2.0.20170509.tar.gz [3] https://github.com/miniupnp/miniupnp/commit/f0f1f4b22d6a98536377a1bb07e7c20e4703d229

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original