Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2019-13283: read___heap-buffer-overflow in FoFiType1::parse calls strncpy

In Xpdf 4.01.01, a heap-based buffer over-read could be triggered in strncpy from FoFiType1::parse in fofi/FoFiType1.cc because it does not ensure the source string has a valid length before making a fixed-length copy. It can, for example, be triggered by sending a crafted PDF document to the pdftotext tool. It allows an attacker to use a crafted pdf file to cause Denial of Service or an information leak, or possibly have unspecified other impact.

CVE
#android#ubuntu#linux#dos#git#pdf#buffer_overflow

Hi,
I’m Mike Zhang of Pangu Lab, I found a heap buffer overflow bug in xpdf code.

4.01.01 xpdf under Ubuntu 16.04.3 LTS

strncpy in FoFiType1::parse fofi/FoFiType1.cc:207 has not ensure the source string valid length before use a fixed copy length, causes an read___heap-buffer-overflow problem.

log from Ubuntu:

Code: Select all

==12947==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x621000009d00 at pc 0x7f29e1f08806 bp 0x7ffed0886130 sp 0x7ffed08858d8
READ of size 82 at 0x621000009d00 thread T0
    #0 0x7f29e1f08805 in strncpy (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x94805)
    #1 0xa03d0b in strncpy /usr/include/x86_64-linux-gnu/bits/string3.h:126
    #2 0xa03d0b in FoFiType1::parse() /home/panguandroid/Documents/git/xpdf/xpdf-src/fofi/FoFiType1.cc:207
    #3 0xa062da in FoFiType1::getName() /home/panguandroid/Documents/git/xpdf/xpdf-src/fofi/FoFiType1.cc:71
    #4 0x64b990 in Gfx8BitFont::Gfx8BitFont(XRef*, char*, Ref, GString*, GfxFontType, Ref, Dict*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/GfxFont.cc:1051
    #5 0x658eb2 in GfxFont::makeFont(XRef*, char*, Ref, Dict*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/GfxFont.cc:191
    #6 0x65ed1c in GfxFontDict::GfxFontDict(XRef*, Ref*, Dict*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/GfxFont.cc:2087
    #7 0x5c950c in GfxResources::GfxResources(XRef*, Dict*, GfxResources*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/Gfx.cc:292
    #8 0x5cb765 in Gfx::Gfx(PDFDoc*, OutputDev*, int, Dict*, double, double, PDFRectangle*, PDFRectangle*, int, int (*)(void*), void*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/Gfx.cc:509
    #9 0x83ca1c in Page::displaySlice(OutputDev*, double, double, int, int, int, int, int, int, int, int, int (*)(void*), void*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/Page.cc:369
    #10 0x83ca1c in Page::display(OutputDev*, double, double, int, int, int, int, int (*)(void*), void*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/Page.cc:321
    #11 0x85ce9d in PDFDoc::displayPage(OutputDev*, int, double, double, int, int, int, int, int (*)(void*), void*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/PDFDoc.cc:423
    #12 0x85ce9d in PDFDoc::displayPages(OutputDev*, int, int, double, double, int, int, int, int, int (*)(void*), void*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/PDFDoc.cc:436
    #13 0x43e2d2 in main /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/pdftotext.cc:253
    #14 0x7f29e121d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #15 0x440068 in _start (/home/panguandroid/Documents/git/xpdf/afl-install/bin/pdftotext+0x440068)

0x621000009d00 is located 0 bytes to the right of 4096-byte region [0x621000008d00,0x621000009d00)
allocated by thread T0 here:
    #0 0x7f29e1f52b50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x9a4c9f in grealloc /home/panguandroid/Documents/git/xpdf/xpdf-src/goo/gmem.cc:193
    #2 0x642386 in GfxFont::readEmbFontFile(XRef*, int*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/GfxFont.cc:849
    #3 0x648b12 in Gfx8BitFont::Gfx8BitFont(XRef*, char*, Ref, GString*, GfxFontType, Ref, Dict*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/GfxFont.cc:1049
    #4 0x658eb2 in GfxFont::makeFont(XRef*, char*, Ref, Dict*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/GfxFont.cc:191
    #5 0x65ed1c in GfxFontDict::GfxFontDict(XRef*, Ref*, Dict*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/GfxFont.cc:2087
    #6 0x5c950c in GfxResources::GfxResources(XRef*, Dict*, GfxResources*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/Gfx.cc:292
    #7 0x5cb765 in Gfx::Gfx(PDFDoc*, OutputDev*, int, Dict*, double, double, PDFRectangle*, PDFRectangle*, int, int (*)(void*), void*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/Gfx.cc:509
    #8 0x83ca1c in Page::displaySlice(OutputDev*, double, double, int, int, int, int, int, int, int, int, int (*)(void*), void*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/Page.cc:369
    #9 0x83ca1c in Page::display(OutputDev*, double, double, int, int, int, int, int (*)(void*), void*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/Page.cc:321
    #10 0x85ce9d in PDFDoc::displayPage(OutputDev*, int, double, double, int, int, int, int, int (*)(void*), void*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/PDFDoc.cc:423
    #11 0x85ce9d in PDFDoc::displayPages(OutputDev*, int, int, double, double, int, int, int, int, int (*)(void*), void*) /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/PDFDoc.cc:436
    #12 0x43e2d2 in main /home/panguandroid/Documents/git/xpdf/xpdf-src/xpdf/pdftotext.cc:253
    #13 0x7f29e121d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x94805) in strncpy
Shadow bytes around the buggy address:
  0x0c427fff9350: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fff9360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fff9370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fff9380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fff9390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c427fff93a0:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fff93b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fff93c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fff93d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fff93e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fff93f0: 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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
==12947==ABORTING

Code: Select all

void FoFiType1::parse() {
  char *line, *line1, *p, *p2;
  char buf[256];
  char c;
  int n, code, base, i, j;
  GBool gotMatrix, startsWithDup, endsWithDup;

  gotMatrix = gFalse;
  for (i = 1, line = (char *)file;
       i <= 100 && line && (!name || !encoding || !gotMatrix);
       ++i) {

    // get font name
    if (!name && !strncmp(line, "/FontName", 9)) {
      strncpy(buf, line, 255);  // L207: read___heap-buffer-overflow
    //...
      line = getNextLine(line);

“line” variable is reference member “file” memory,

When set breakpoints on all the “file” member assignment code, the following line used:

Code: Select all

FoFiBase::FoFiBase(char *fileA, int lenA, GBool freeFileDataA) {
  fileData = file = (Guchar *)fileA;  // L26
  len = lenA;
  freeFileData = freeFileDataA;
}

The constructor called from

Code: Select all

Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
             GfxFontType typeA, Ref embFontIDA, Dict *fontDict):
  GfxFont(tagA, idA, nameA, typeA, embFontIDA)
{
  //...
  char *buf;
  int len;
  //...
  buf = NULL;
  if (type == fontType1 && embFontID.num >= 0) {
    if ((buf = readEmbFontFile(xref, &len))) {  // set buf and len
      if ((ffT1 = FoFiType1::make(buf, len))) {  // L1050

This code call into “FoFiBase::FoFiBase” method, “buf” is “fileA” and “len” is "lenA".

Code: Select all

char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
  char *buf;
  Object obj1, obj2;
  Stream *str;
  int size, n;
  //...
  do {
    //...
    buf = (char *)grealloc(buf, size + 4096); // L849: expand buf memory 4096 bytes everytime
    n = str->getBlock(buf + size, 4096);
    size += n;
  } while (n == 4096);  // read into buf until a non 4096 continue block with EOF byte in it
  *len = size;
  //...
  return buf;
}

So, according to the above analysis, “len” is the “buf” memory length.

And with the dynamic debug analysis help, we found “line+255” is out of “file” memory block.

Related news

CVE-2022-24107: Xpdf Security Fixes

Xpdf prior to 4.04 lacked an integer overflow check in JPXStream.cc.

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907