Project: libtorrent (arvidn/libtorrent), language: c++
Vulnerability instance: libtorrent.cve-2017-9847
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/arvidn/libtorrent/issues/2099
## Description:
Issue: arvidn/libtorrent#2099
Title: heap-based buffer overflow in function bdecode(bdecode.cpp:702)
State: closed
Created by: owl337
Created at: 2017-06-23 10:13:48+00:00

Issue Body:
**Please provide the following information**

libtorrent version (or branch):
the latest version (1.1.3)

platform/architecture:
linux/x86
compiler and compiler version:
clang3.8

please describe what symptom you see, what you would expect to see instead and
how to reproduce it.
Summary: 

There is a heap based buffer overflow in the libtorrent library. 

POC download:  https://github.com/owl337/pocs/blob/master/torrent_poc1.rar

Description:

The debugging information is as follows:
 
$ ./mineSimple POC1

=================================================================
==29209==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000eff2 at pc 0x7fc040e3c26a bp 0x7ffc3f6ac820 sp 0x7ffc3f6ac818
READ of size 1 at 0x60200000eff2 thread T0
    #0 0x7fc040e3c269  (../../lib/libtorrent-rasterbar.so.9+0x1cb269)
    #1 0x7fc041c743f6  (../../lib/libtorrent-rasterbar.so.9+0x10033f6)
    #2 0x4df1b6  (/home/icy/real/libtorrent-libtorrent-1_1_3/install/fuzz/libtorrent-fuzz-master/simple_client1+0x4df1b6)
    #3 0x4dea5f  (/home/icy/real/libtorrent-libtorrent-1_1_3/install/fuzz/libtorrent-fuzz-master/simple_client1+0x4dea5f)
    #4 0x7fc03ed3da3f  (/lib/x86_64-linux-gnu/libc.so.6+0x20a3f)
    #5 0x437398  (/home/icy/real/libtorrent-libtorrent-1_1_3/install/fuzz/libtorrent-fuzz-master/simple_client1+0x437398)

0x60200000eff2 is located 0 bytes to the right of 2-byte region [0x60200000eff0,0x60200000eff2)
allocated by thread T0 here:
    #0 0x4dd7e2  (/home/icy/real/libtorrent-libtorrent-1_1_3/install/fuzz/libtorrent-fuzz-master/simple_client1+0x4dd7e2)
    #1 0x7fc040fe0812  (../../lib/libtorrent-rasterbar.so.9+0x36f812)

Shadow bytes around the buggy address:
  0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c047fff9df0: fa fa fa fa fa fa fa fa fa fa 00 fa fa fa[02]fa
  0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e40: 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):
  Addressable:           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
==29209==ABORTING

This vulnerability was triggered in function parse_int() at line  bdecode.cpp:136.

 133         char const* parse_int(char const* start, char const* end, char delimiter
 134                 , boost::int64_t& val, bdecode_errors::error_code_enum& ec)
 135         {
 136                 while (start < end && *start != delimiter)
 137                 {
 138                         if (!numeric(*start))
 139                         {
  ...
 702         int bdecode(char const* start, char const* end, bdecode_node& ret
 703                 , error_code& ec, int* error_pos, int depth_limit, int token_limit)
 704         {
  ...
 832                                 default:
 833                                 {
 ...
 841                                         ++start;
 842                                         bdecode_errors::error_code_enum e = bdecode_errors::no_error;
 843                                         start = parse_int(start, end, ':', len, e);
  ...


Credits:

This vulnerability is detected by team OWL337, with our custom fuzzer collAFL. Please contact ganshuitao@gmail.com   and chaoz@tsinghua.edu.cn if you need more info about the team, the tool or the vulnerability.










Comments:
Comment by ssiloti on 2017-06-24 02:54:20+00:00:
At first glance it looks like a pretty simple case of a missing range check. @arvidn are you already looking at this? If not I'll take care of it.

---

Comment by arvidn on 2017-06-24 14:50:54+00:00:
I started working on a patch last night, but didn't finish it.

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
mkdir -p build
cd build
cmake -DBUILD_SHARED_LIBS=Off ..
make -j$(nproc)

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make wget libssl-dev libgeoip-dev pkg-config
RUN git clone https://github.com/arvidn/libtorrent libtorrent
RUN git -C libtorrent checkout b06553602311f6e294fd6c0c82ba54e3d09e539e
WORKDIR $SRC/libtorrent
COPY build.sh $SRC/

Additional files: