New issue
Advanced search Search tips
Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Closed: Jul 2018
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Android , Windows , Chrome , Mac , Fuchsia
Pri: 1
Type: Bug-Security



Sign in to add a comment
link

Issue 864932: Security: Little-CMS (lcms) Heap Buffer Overflow

Reported by quangn...@gmail.com, Jul 18 2018

Issue description

**VULNERABILITY DETAILS**
 
 Little-CMS third-party library is used in PDFium to support ICC profile. I have audited source code of lcms library and I have founded a vulnerability in cmsReadTag function. The attached icc profile could crash lcms when ASAN was enabled on Linux.
 
 ```
 =================================================================
==37311==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x606000000058 at pc 0x00000053bc7b bp 0x7ffcd1988bd0 sp 0x7ffcd1988bc8
READ of size 8 at 0x606000000058 thread T0
    #0 0x53bc7a in Type_S15Fixed16_Write /root/fuzzer/lcms2/Little-CMS/src/cmstypes.c:558:43
    #1 0x4f9769 in cmsReadRawTag /root/fuzzer/lcms2/Little-CMS/src/cmsio0.c:1873:10
    #2 0x4eae5b in ReadAllRAWTags /root/fuzzer/lcms2/Little-CMS/fuzz/fuzz.c:23:9
    #3 0x4eaf05 in main /root/fuzzer/lcms2/Little-CMS/fuzz/fuzz.c:31:4
    #4 0x7f5d4f0c082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #5 0x41aa78 in _start (/root/fuzzer/lcms2/Little-CMS/fuzz/fuzz+0x41aa78)

0x606000000058 is located 0 bytes to the right of 56-byte region [0x606000000020,0x606000000058)
allocated by thread T0 here:
    #0 0x4bb1a3 in __interceptor_malloc /tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:88:3
    #1 0x57fac4 in FXMEM_DefaultAlloc /root/fuzzer/lcms2/Little-CMS/src/cmserr.c:33:9
    #2 0x57fe18 in _cmsMallocZero /root/fuzzer/lcms2/Little-CMS/src/cmserr.c:97:15
    #3 0x57feb9 in _cmsCalloc /root/fuzzer/lcms2/Little-CMS/src/cmserr.c:109:12
    #4 0x53bae0 in Type_S15Fixed16_Read /root/fuzzer/lcms2/Little-CMS/src/cmstypes.c:534:40
    #5 0x4f65d3 in cmsReadTag /root/fuzzer/lcms2/Little-CMS/src/cmsio0.c:1597:25
    #6 0x4eadc5 in ReadAllTags /root/fuzzer/lcms2/Little-CMS/fuzz/fuzz.c:11:13
    #7 0x4eaefc in main /root/fuzzer/lcms2/Little-CMS/fuzz/fuzz.c:30:4
    #8 0x7f5d4f0c082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: heap-buffer-overflow /root/fuzzer/lcms2/Little-CMS/src/cmstypes.c:558:43 in Type_S15Fixed16_Write
Shadow bytes around the buggy address:
  0x0c0c7fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c0c7fff8000: fa fa fa fa 00 00 00 00 00 00 00[fa]fa fa fa fa
  0x0c0c7fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8050: 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
==37311==ABORTING
```

**VERSION**

Chrome Version: All

Operating System: All

Following code will trigger crash

```
#include <stdio.h>
#include <lcms2.h>

void ReadAllTags(cmsHPROFILE h) {
    cmsInt32Number i, n;
    cmsTagSignature sig;

    n = cmsGetTagCount(h);
    for (i=0; i < n; i++) {
        sig = cmsGetTagSignature(h, i);
        if (cmsReadTag(h, sig) == NULL) return;
    }
}

// Read all tags on a profile given by its handle
void ReadAllRAWTags(cmsHPROFILE h) {
    cmsInt32Number i, n;
    cmsTagSignature sig;

    n = cmsGetTagCount(h);
    for (i=0; i < n; i++) {
        sig = cmsGetTagSignature(h, i);
        cmsReadRawTag(h, sig, NULL, 0);
    }
}

int main(int argc, char* argv[]) {
   cmsHPROFILE h = cmsOpenProfileFromFile(argv[1], "rb");
   if (h == NULL) return 1;
   ReadAllTags(h);
   ReadAllRAWTags(h);
   cmsCloseProfile(h);
   return 0;
}
```
 
 
**ANALYSIS**

There are many tag types which are supported in lcms: https://cs.chromium.org/chromium/src/third_party/pdfium/third_party/lcms/src/cmstypes.c?type=cs&l=5418


```
// This is the list of built-in tags
static _cmsTagLinkedList SupportedTags[] = {
   //  .....
    { cmsSigChromaticAdaptationTag, { 9, 1, { cmsSigS15Fixed16ArrayType }, NULL}, &SupportedTags[15]},
   //  .....
};
```

Each type has `ElemCount`: https://cs.chromium.org/chromium/src/third_party/pdfium/third_party/lcms/include/lcms2_plugin.h?type=cs&g=0&l=425

```
// This is the tag plugin, which identifies tags. For writing, a pointer to function is provided.
// This function should return the desired type for this tag, given the version of profile
// and the data being serialized.
typedef struct {

    cmsUInt32Number     ElemCount;          // If this tag needs an array, how many elements should keep

    // For reading.
    cmsUInt32Number     nSupportedTypes;    // In how many types this tag can come (MAX_TYPES_IN_LCMS_PLUGIN maximum)
    cmsTagTypeSignature SupportedTypes[MAX_TYPES_IN_LCMS_PLUGIN];

    // For writting
    cmsTagTypeSignature (* DecideType)(cmsFloat64Number ICCVersion, const void *Data);

} cmsTagDescriptor;
```

Let's see cmsReadTag: https://cs.chromium.org/chromium/src/third_party/pdfium/third_party/lcms/src/cmsio0.c?l=1519

The number of elements, which is calculated from data, may be less than `ElemCount`: https://cs.chromium.org/chromium/src/third_party/pdfium/third_party/lcms/src/cmsio0.c?l=1612
```
// This is a weird error that may be a symptom of something more serious, the number of
    // stored item is actually less than the number of required elements.
    if (ElemCount < TagDescriptor ->ElemCount) {

        char String[5];

        _cmsTagSignature2String(String, sig);
        cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "'%s' Inconsistent number of items: expected %d, got %d",
            String, TagDescriptor ->ElemCount, ElemCount);
    }
```
if ElemCount is less than TagDescriptor ->ElemCount, it is a malformed tag and it MUST be ignored.
 
crash-cmsReadTag_min
180 bytes View Download

Comment 1 by quangn...@gmail.com, Jul 18 2018

Patch for this issue: 
```
diff --git a/third_party/lcms/src/cmsio0.c b/third_party/lcms/src/cmsio0.c
index cc5f89064..63e4105d1 100644
--- a/third_party/lcms/src/cmsio0.c
+++ b/third_party/lcms/src/cmsio0.c
@@ -1616,6 +1616,7 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
         _cmsTagSignature2String(String, sig);
         cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "'%s' Inconsistent number of items: expected %d, got %d",
             String, TagDescriptor ->ElemCount, ElemCount);
+               goto Error;
     }


```

Comment 2 by cthomp@chromium.org, Jul 18 2018

Components: Internals>Plugins>PDF
Labels: M-69 Security_Severity-Medium FoundIn-67 Security_Impact-Stable OS-Android OS-Chrome OS-Fuchsia OS-Linux OS-Mac OS-Windows Pri-1
Owner: thestig@chromium.org
Thank you for the detailed writeup and for including a patch :-)

Setting some labels. If I understand correctly, this is a limited out-of-bounds write, so applying Sev-Medium.

thestig@ Could you take a look? You had the most recent patch to lcms/.

Comment 3 by thestig@chromium.org, Jul 18 2018

Cc: tsepez@chromium.org

Comment 4 by thestig@chromium.org, Jul 18 2018

Yes, it looks like cmsReadTag() is missing the goto statement to handle the error. We'll patch it up. Have you reported the issue upstream to lcms?

Comment 5 by thestig@chromium.org, Jul 18 2018

Status: Started (was: Unconfirmed)
https://pdfium-review.googlesource.com/c/pdfium/+/38270

Comment 7 by thestig@chromium.org, Jul 18 2018

Labels: M-68 Merge-Request-68
Status: Fixed (was: Started)

Comment 8 by sheriffbot@chromium.org, Jul 18 2018

Project Member
Labels: -Merge-Request-68 Hotlist-Merge-Review Merge-Review-68
This bug requires manual review: We are only 5 days from stable.
Please contact the milestone owner if you have questions.
Owners: cmasso@(Android), kariahda@(iOS), bhthompson@(ChromeOS), abdulsyed@(Desktop)

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot

Comment 9 by bugdroid1@chromium.org, Jul 19 2018

Project Member
The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/30ce134f3d94e8addd51f007a468af9ac626af9f

commit 30ce134f3d94e8addd51f007a468af9ac626af9f
Author: pdfium-chromium-autoroll <pdfium-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com>
Date: Thu Jul 19 02:04:36 2018

Roll src/third_party/pdfium f22b4e2f6682..c15c0b3a1e9a (3 commits)

https://pdfium.googlesource.com/pdfium.git/+log/f22b4e2f6682..c15c0b3a1e9a


git log f22b4e2f6682..c15c0b3a1e9a --date=short --no-merges --format='%ad %ae %s'
2018-07-18 thestig@chromium.org Roll third_party/skia/ af7700265..588f87967 (1391 commits; 41 trivial rolls)
2018-07-18 thestig@chromium.org Handle wrong tag element count in littlecms.
2018-07-18 tsepez@chromium.org Add pdfium::span::as_bytes() and as_writable_bytes().


Created with:
  gclient setdep -r src/third_party/pdfium@c15c0b3a1e9a

The AutoRoll server is located here: https://pdfium-roll.skia.org

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md

If the roll is causing failures, please contact the current sheriff, who should
be CC'd on the roll, and stop the roller if necessary.



BUG= chromium:864932 
TBR=dsinclair@chromium.org

Change-Id: If7555664cbb89a71e68d034eacbb6b6be0e87415
Reviewed-on: https://chromium-review.googlesource.com/1142172
Reviewed-by: pdfium-chromium-autoroll <pdfium-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com>
Commit-Queue: pdfium-chromium-autoroll <pdfium-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com>
Cr-Commit-Position: refs/heads/master@{#576322}
[modify] https://crrev.com/30ce134f3d94e8addd51f007a468af9ac626af9f/DEPS

Comment 10 by quangn...@gmail.com, Jul 19 2018

Thank you for reviewing the issue. Do you reward for this report?

Comment 11 by thestig@chromium.org, Jul 19 2018

Cc: awhalley@chromium.org

Comment 12 by sheriffbot@chromium.org, Jul 19 2018

Project Member
Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify

Comment 13 by awhalley@google.com, Jul 19 2018

Labels: reward-topanel
quangnh89@, this will go to a future meetings of the VRP panel, we'll see what they say.

Comment 14 by abdulsyed@google.com, Jul 19 2018

Labels: -Merge-Review-68 Merge-Rejected-68
My recommendation is to target this for M69, since M68 stable is next week. Rejecting merge for M68. Awhalley@/thestig@ - please confirm if this is absolutely critical.

Comment 15 by awhalley@google.com, Jul 23 2018

Labels: -M-68

Comment 17 by thestig@chromium.org, Aug 1

Comment 18 by quangn...@gmail.com, Aug 2

I have checked lcms v2.9. The vulnerability still exists.
If you update lcms, please patch it :)

https://github.com/mm2/Little-CMS/blob/master/src/cmsio0.c#L1601

Comment 19 by thestig@chromium.org, Aug 2

Thanks for mention that. When we upgrade a third party library, we usually re-evaluate all the patches to see which ones are still relevant.

Comment 20 by awhalley@chromium.org, Aug 6

Labels: -reward-topanel reward-unpaid reward-2500
*** Boilerplate reminders! ***
Please do NOT publicly disclose details until a fix has been released to all our users. Early public disclosure may cancel the provisional reward. Also, please be considerate about disclosure when the bug affects a core library that may be used by other products. Please do NOT share this information with third parties who are not directly involved in fixing the bug. Doing so may cancel the provisional reward. Please be honest if you have already disclosed anything publicly or to third parties. Lastly, we understand that some of you are not interested in money. We offer the option to donate your reward to an eligible charity. If you prefer this option, let us know and we will also match your donation - subject to our discretion. Any rewards that are unclaimed after 12 months will be donated to a charity of our choosing.
*********************************

Comment 21 by awhalley@chromium.org, Aug 6

Thanks for the report, quangnh89@! The VRP panel decided to award $2,000 for the report, and $500 for supplying the patch we used. They also noted that they'd be open to considering a higher amount if you could show how this might lead to memory corruption rather than just being an information leak.  Cheers!  A member of our finance team will be in touch to arrange for payment.

Comment 22 by awhalley@chromium.org, Aug 6

Labels: -reward-unpaid reward-inprocess

Comment 23 by quangn...@gmail.com, Aug 7

Thank you so much for the reward! That means so much to me! Your thoughtfulness encourage me to do my best. :) Have a nice day!

Comment 24 by awhalley@google.com, Aug 16

Labels: Release-0-M69

Comment 25 by sheriffbot@chromium.org, Oct 25

Project Member
Labels: -Restrict-View-SecurityNotify allpublic
This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot

Comment 26 by stackexp...@gmail.com, Oct 26

Hello, can you tell me how to reproduce this issue under pdfium? Thanks.

Sign in to add a comment