Bug 1672419 (CVE-2019-7310) - CVE-2019-7310 poppler: heap-based buffer over-read in XRef::getEntry in XRef.cc
Summary: CVE-2019-7310 poppler: heap-based buffer over-read in XRef::getEntry in XRef.cc
Keywords:
Status: CLOSED ERRATA
Alias: CVE-2019-7310
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:
Depends On: 1672420 1672421 1673699 1673700 1717779
Blocks: 1672422
TreeView+ depends on / blocked
 
Reported: 2019-02-04 21:32 UTC by Laura Pardo
Modified: 2019-09-29 15:07 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2019-08-06 13:21:49 UTC
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHSA-2019:2022 0 None None None 2019-08-06 12:03:02 UTC
Red Hat Product Errata RHSA-2019:2713 0 None None None 2019-09-11 09:33:21 UTC

Description Laura Pardo 2019-02-04 21:32:38 UTC
In Poppler 0.73.0, a heap-based buffer over-read (due to an integer signedness error in the XRef::getEntry function in XRef.cc) allows remote attackers to cause a denial of service (application crash) or possibly have unspecified other impact via a crafted PDF document, as demonstrated by pdftocairo.


References:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12797
https://gitlab.freedesktop.org/poppler/poppler/issues/717

Upstream Patch:
https://gitlab.freedesktop.org/poppler/poppler/merge_requests/172

Comment 1 Laura Pardo 2019-02-04 21:32:53 UTC
Created mingw-poppler tracking bugs for this issue:

Affects: fedora-all [bug 1672421]


Created poppler tracking bugs for this issue:

Affects: fedora-all [bug 1672420]

Comment 4 Scott Gayou 2019-02-07 20:46:54 UTC
Easy to reproduce:

```
==28176== Invalid read of size 4
==28176==    at 0x4FA62B1: XRef::getEntry(int, bool) (XRef.cc:1609)
==28176==    by 0x4F89FF6: Parser::makeStream(Object*, unsigned char*, CryptAlgorithm, int, int, int, int, bool) (Parser.cc:207)
==28176==    by 0x4F8A8F7: Parser::getObj(Object*, bool, unsigned char*, CryptAlgorithm, int, int, int, int, bool) (Parser.cc:131)
==28176==    by 0x4F6FA84: Hints::readTables(BaseStream*, Linearization*, XRef*, SecurityHandler*) (Hints.cc:145)
==28176==    by 0x4F8B474: PDFDoc::getHints() (PDFDoc.cc:607)
==28176==    by 0x4F90518: PDFDoc::parsePage(int) (PDFDoc.cc:1890)
==28176==    by 0x4F90769: PDFDoc::getPage(int) (PDFDoc.cc:1931)
==28176==    by 0x4087C5: getPageMediaWidth (PDFDoc.h:126)
==28176==    by 0x4087C5: main (pdftocairo.cc:1014)
==28176==  Address 0x9ffd444 is 28 bytes before a block of size 16 in arena "client"
==28176== 
==28176== Invalid read of size 4
==28176==    at 0x4F8A003: Parser::makeStream(Object*, unsigned char*, CryptAlgorithm, int, int, int, int, bool) (Parser.cc:205)
==28176==    by 0x4F8A8F7: Parser::getObj(Object*, bool, unsigned char*, CryptAlgorithm, int, int, int, int, bool) (Parser.cc:131)
==28176==    by 0x4F6FA84: Hints::readTables(BaseStream*, Linearization*, XRef*, SecurityHandler*) (Hints.cc:145)
==28176==    by 0x4F8B474: PDFDoc::getHints() (PDFDoc.cc:607)
==28176==    by 0x4F90518: PDFDoc::parsePage(int) (PDFDoc.cc:1890)
==28176==    by 0x4F90769: PDFDoc::getPage(int) (PDFDoc.cc:1931)
==28176==    by 0x4087C5: getPageMediaWidth (PDFDoc.h:126)
==28176==    by 0x4087C5: main (pdftocairo.cc:1014)
==28176==  Address 0x9ffd448 is 24 bytes before a block of size 5 free'd
==28176==    at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==28176==    by 0x4F96037: FlateStream::~FlateStream() (Stream.cc:4521)
==28176==    by 0x4F96078: FlateStream::~FlateStream() (Stream.cc:4524)
==28176==    by 0x4F83E73: Object::free() (Object.cc:145)
==28176==    by 0x4FA5CBB: XRef::readXRef(long long*, std::vector<long long, std::allocator<long long> >*, std::vector<int, std::allocator<int> >*) (XRef.cc:562)
==28176==    by 0x4FA5DEF: XRef::XRef(BaseStream*, long long, long long, bool*, bool) (XRef.cc:342)
==28176==    by 0x4F8F327: PDFDoc::setup(GooString*, GooString*) (PDFDoc.cc:260)
==28176==    by 0x4F8F627: PDFDoc::PDFDoc(GooString*, GooString*, GooString*, void*) (PDFDoc.cc:165)
==28176==    by 0x4F829E3: LocalPDFDocBuilder::buildPDFDoc(GooString const&, GooString*, GooString*, void*) (LocalPDFDocBuilder.cc:31)
```

Looks like a negative index can get passed to XRef::getEntry by an attacker.

```c
XRefEntry *XRef::getEntry(int i, GBool complainIfMissing)
{
  if (i >= size || entries[i].type == xrefEntryNone) {

    if ((!xRefStream) && mainXRefEntriesOffset) {
      if (!parseEntry(mainXRefEntriesOffset + 20*i, &entries[i])) {
        error(errSyntaxError, -1, "Failed to parse XRef entry [{0:d}].", i);
      }
    } else {
...
return &entries[i];
```

Presumably, valgrind/ASAN is asserting when the entries[i] load occurs. Could then return a negative entry back to the caller.

Unclear if this could lead to code execution, but rated the CVSS a bit higher to account for my uncertainty.

Comment 7 errata-xmlrpc 2019-08-06 12:03:01 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 7

Via RHSA-2019:2022 https://access.redhat.com/errata/RHSA-2019:2022

Comment 8 Product Security DevOps Team 2019-08-06 13:21:49 UTC
This bug is now closed. Further updates for individual products will be reflected on the CVE page(s):

https://access.redhat.com/security/cve/cve-2019-7310

Comment 9 errata-xmlrpc 2019-09-11 09:33:20 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 8

Via RHSA-2019:2713 https://access.redhat.com/errata/RHSA-2019:2713


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