Bug 1627923 (CVE-2018-16790) - CVE-2018-16790 libbson: Heap-based buffer over-read in _bson_iter_next_internal in bson-iter.c
Summary: CVE-2018-16790 libbson: Heap-based buffer over-read in _bson_iter_next_intern...
Keywords:
Status: NEW
Alias: CVE-2018-16790
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
URL:
Whiteboard: impact=moderate,public=20180911,repor...
Depends On: 1629988 1629989 1627924 1627925 1630042
Blocks: 1627926
TreeView+ depends on / blocked
 
Reported: 2018-09-11 21:29 UTC by Pedro Sampaio
Modified: 2019-06-08 23:36 UTC (History)
5 users (show)

Fixed In Version: libbson 1.13.0
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed:


Attachments (Terms of Use)
Reproducer (878 bytes, text/plain)
2018-09-12 12:44 UTC, Petr Pisar
no flags Details

Description Pedro Sampaio 2018-09-11 21:29:23 UTC
The function _bson_iter_next_internal in bson-iter.c in libbson 1.12.0, as used in MongoDB mongo-c-driver and other products, has a heap-based buffer over-read via a crafted bson buffer.

Upstream bug:

https://jira.mongodb.org/browse/CDRIVER-2819

Comment 1 Pedro Sampaio 2018-09-11 21:29:51 UTC
Created libbson tracking bugs for this issue:

Affects: epel-7 [bug 1627925]
Affects: fedora-all [bug 1627924]

Comment 2 Petr Pisar 2018-09-12 08:51:45 UTC
libbson was merged into mongo-c-driver in Fedora ≥ 29.

Comment 3 Petr Pisar 2018-09-12 12:44:01 UTC
Created attachment 1482654 [details]
Reproducer

Based on the upstream report.

Valgrind reports for libbson-1.9.5:

==9083== Conditional jump or move depends on uninitialised value(s)
==9083==    at 0x4859161: _bson_iter_next_internal (bson-iter.c:600)
==9083==    by 0x485A824: bson_iter_visit_all (bson-iter.c:1900)
==9083==    by 0x48572CF: _bson_as_json_visit_all (bson.c:3121)
==9083==    by 0x4012BF: main (in /tmp/a.out)

Valgrind reports for libbson bundled within mongo-c-driver-1.12.0:

==9084== Conditional jump or move depends on uninitialised value(s)
==9084==    at 0x4868829: _bson_iter_next_internal (bson-iter.c:634)
==9084==    by 0x486A454: bson_iter_visit_all (bson-iter.c:1934)
==9084==    by 0x4865BCA: _bson_as_json_visit_all (bson.c:3158)
==9084==    by 0x4012BF: main (in /tmp/a.out)

Both of them point uninitialized value read at:

      if (subtype == BSON_SUBTYPE_BINARY_DEPRECATED) {
         int32_t binary_len;

         if (l < 4) {
            iter->err_off = o;
            goto mark_invalid;
         }

         /* subtype 2 has a redundant length header in the data */
         memcpy (&binary_len, (iter->raw + iter->d3), sizeof (binary_len));
         binary_len = BSON_UINT32_FROM_LE (binary_len);
→        if (binary_len + 4 != l) {
            iter->err_off = iter->d3;
            goto mark_invalid;
         }
      }

While sanitizer reports a buffer overread at two different places:

      if (subtype == BSON_SUBTYPE_BINARY_DEPRECATED) {
         int32_t binary_len;

         if (l < 4) {
→           iter->err_off = o;
            goto mark_invalid;
         }

         /* subtype 2 has a redundant length header in the data */
→        memcpy (&binary_len, (iter->raw + iter->d3), sizeof (binary_len));
         binary_len = BSON_UINT32_FROM_LE (binary_len);
         if (binary_len + 4 != l) {
            iter->err_off = iter->d3;
            goto mark_invalid;
         }
      }

Comment 4 Scott Gayou 2018-09-14 15:15:06 UTC
Reduced the reproducer to something a bit more actionable. Working upstream here: https://jira.mongodb.org/browse/CDRIVER-2819, but I'll post the comment here as well.

Looks like we're running off the end of a binary buffer.

Reproducer that triggers the ASAN error can be reduced to:
{0x11, 0x0, 0x0, 0x0, 0x5, 0xe, 0x19, 0x2e, 0x0, 0x4, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}

which I believe decodes to:

0x11, 0x0, 0x0, 0x0 – Length of document is 0x11 (17) bytes
0x5, – binary data
0xe, 0x19, 0x2e, 0x0 – cstr
0x4, 0x0, 0x0, 0x0 – length of binary element (4)
0x2, – binary subtype (Binary (Old))
0x0, 0x0, 0x0, (Missing final byte)

Thus, if we change the final binary length to a 3 instead of a 4, we no longer trigger the out of bounds read.

Looking at the code now...

Comment 8 Scott Gayou 2018-09-17 20:41:59 UTC
Created mongo-c-driver tracking bugs for this issue:

Affects: fedora-all [bug 1630042]

Comment 9 Petr Pisar 2018-09-18 08:42:40 UTC
EPEL7's libbson-1.3.5 does not manifest this bug because bson_iter_next() does not read the redundant length header of BSON_SUBTYPE_BINARY_DEPRECATED by memcpy(). Otherwise the parser code is the same. I will apply the fix there. Making the parser stricter is not a bad thing.


Note You need to log in before you can comment on or make changes to this bug.