Security: Memory Corruption Vulnerability in Skia [MSAN Build]
Reported by
kushal89...@gmail.com,
Sep 15 2017
|
||||||||||
Issue descriptionVULNERABILITY DETAILS Memory Corruption Vulnerability triggered in Skia. Analysis done on LINUX System, Only the reporting was done on Windows System. PoC has been tested on latest Chrome Linux "MSAN" build (#502297) as of Sept 15 12:45PM PST. Build links have been shared in the Step 1 of the "Reproduction Case" section. VERSION Chrome Version: Latest Linux "MSAN" release build. Operating System: Ubuntu REPRODUCTION CASE 1. Download latest chrome "MSAN" build from https://www.googleapis.com/download/storage/v1/b/chromium-browser-msan/o/linux-release%2Fmsan-chained-origins-linux-release-502297.zip?generation=1505503057006046&alt=media 2. Unzip the downloaded "msan" builds. 3. Change directory to filter_fuzz_stub location. 4. Set environment variable MSAN_OPTIONS=allocator_may_return_null=1 5. Under gdb, run the filter_fuzz_stub binary against the New_Msan_PoC.fil testcase file. 6. Check the crash details in the terminal window. FOR CRASHES, PLEASE INCLUDE THE FOLLOWING ADDITIONAL INFORMATION Binary segfaults (crashes) due to trigger of an Out-Of-Bounds Write Access. See gdb output below: - root@kush:~/Desktop/fil_msan# printenv | grep "MSAN_OPTIONS" MSAN_OPTIONS=allocator_may_return_null=1 root@kush:~/Desktop/fil_msan# root@kush:~/Desktop/fil_msan# /root/Desktop/msan-chained-origins-linux-release-502297/filter_fuzz_stub /root/Desktop/New_Msan_PoC.fil [0915/144902.523473:INFO:filter_fuzz_stub.cc(60)] Test case: /root/Desktop/New_Msan_PoC.fil Segmentation fault root@kush:~/Desktop/fil_msan# gdb --args /root/Desktop/msan-chained-origins-linux-release-502297/filter_fuzz_stub /root/Desktop/New_Msan_PoC.fil GNU gdb (Debian 7.12-6) 7.12.0.20161007-git Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from /root/Desktop/msan-chained-origins-linux-release-502297/filter_fuzz_stub...done. (gdb) r Starting program: /root/Desktop/msan-chained-origins-linux-release-502297/filter_fuzz_stub /root/Desktop/New_Msan_PoC.fil [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [0915/144912.108117:INFO:filter_fuzz_stub.cc(60)] Test case: /root/Desktop/New_Msan_PoC.fil Program received signal SIGSEGV, Segmentation fault. 0x0000000000440085 in __msan::MsanAllocate(__sanitizer::StackTrace*, unsigned long, unsigned long, bool) () (gdb) bt #0 0x0000000000440085 in __msan::MsanAllocate(__sanitizer::StackTrace*, unsigned long, unsigned long, bool) () #1 0x0000000000440186 in __msan::msan_malloc(unsigned long, __sanitizer::StackTrace*) () #2 0x0000000000448f4f in malloc () #3 0x00000000005547fd in sk_malloc_throw () at ../../skia/ext/SkMemory_new_handler.cpp:64 #4 0x000000000065685f in reset () at ../../third_party/skia/include/gpu/../private/SkTemplates.h:183 #5 0x0000000000656c8b in allocInputs () at ../../third_party/skia/src/core/SkImageFilter.cpp:113 #6 unflatten () at ../../third_party/skia/src/core/SkImageFilter.cpp:126 #7 0x0000000000fe39ff in CreateProc () at ../../third_party/skia/src/effects/SkMergeImageFilter.cpp:114 #8 0x000000000083bf61 in readFlattenable () at ../../third_party/skia/src/core/SkValidatingReadBuffer.cpp:301 #9 0x000000000064d90c in SkValidatingDeserializeFlattenable () at ../../third_party/skia/src/core/SkFlattenableSerialization.cpp:26 #10 SkValidatingDeserializeImageFilter () at ../../third_party/skia/src/core/SkFlattenableSerialization.cpp:30 #11 0x000000000049341f in RunTestCase () at ../../skia/tools/filter_fuzz_stub/filter_fuzz_stub.cc:32 #12 ReadAndRunTestCase () at ../../skia/tools/filter_fuzz_stub/filter_fuzz_stub.cc:66 #13 main () at ../../skia/tools/filter_fuzz_stub/filter_fuzz_stub.cc:85 (gdb) exploitable __main__:99: UserWarning: GDB v7.12 may not support required Python API Description: Access violation on destination operand Short description: DestAv (8/22) Hash: bd99e13b64ec52861190c6ec972adbd6.79560eba448cc95d8a97949d1631d37f Exploitability Classification: EXPLOITABLE Explanation: The target crashed on an access violation at an address matching the destination operand of the instruction. This likely indicates a write access violation, which means the attacker may control the write address and/or value. Other tags: AccessViolation (21/22) (gdb)
,
Sep 15 2017
Hello @meacer, @reed, Google Product Security Team [skia], Good Afternoon. I noticed that there was a more recent version of chrome msan build available around the same time as my report. I would like to confirm that the crash consistently occurs in the most recent version also i.e. build #502326 available at https://www.googleapis.com/download/storage/v1/b/chromium-browser-msan/o/linux-release%2Fmsan-chained-origins-linux-release-502326.zip?generation=1505510729205749&alt=media Thanks, Kushal. PS: @meacer, That was one of the fastest (if not the fastest) responses I have seen from Google PSIRT Team!!! Truly commendable!!:)
,
Sep 15 2017
Glad to help :) Please keep the reports coming.
,
Sep 18 2017
reed@chromium --> @google
,
Sep 18 2017
This looks like MSAN itself is crashing, while trying to service a malloc request. That is odd. This option: MSAN_OPTIONS=allocator_may_return_null=1, is very dubious when embedding Skia, as skia in general does not check for null on allocations. Specifically in this case (for the ImageFilter), Skia has told the embedding client that it will NOT check for null.
,
Sep 20 2017
Hello @reed, Good Evening. I am not quite sure what you meant by calling "allocator_may_return_null=1" as dubious, but for reference, here are some crbug reports wherein the same option was previously used for several other bugs in Chrome. https://bugs.chromium.org/p/chromium/issues/detail?id=446032 https://bugs.chromium.org/p/chromium/issues/detail?id=468519 https://bugs.chromium.org/p/chromium/issues/detail?id=431288 https://bugs.chromium.org/p/chromium/issues/detail?id=699166 Hope that helps in some way..:) Thanks, ~ Kushal.
,
Sep 20 2017
Hello @reed, @hcm, @meacer, @bungeman, Google Product Security Team, I would like to confirm that the crash is consistently reproducible on the latest Chrome MSAN "Stable" and "Beta" builds available at https://www.googleapis.com/download/storage/v1/b/chromium-browser-msan/o/linux-release%2Fmsan-linux-stable-61.0.3163.91.zip?generation=1505829384001916&alt=media AND https://www.googleapis.com/download/storage/v1/b/chromium-browser-msan/o/linux-release%2Fmsan-linux-beta-62.0.3202.18.zip?generation=1505796962687871&alt=media respectively. Thanks, ~ Kushal.
,
Sep 20 2017
Kushal, 1) the crash is inside the *MSAN* allocator itself (not present in regular builds) 2) allocator_may_return_null=1 is an invalid Chromium configuration (regular builds perform a controlled-crash on allocation failures, and never return null) Unless you can repro the crash without allocator_may_return_null=1, I don't think this is valid issue.
,
Sep 20 2017
FWIW, I can't reproduce the bug (using that build, https://www.googleapis.com/download/storage/v1/b/chromium-browser-msan/o/linux-release%2Fmsan-chained-origins-linux-release-502297.zip?generation=1505503057006046&alt=media), with any of MSAN_OPTIONS=allocator_may_return_null=1 MSAN_OPTIONS=allocator_may_return_null=1 unset MSAN_OPTIONS They all result in: [0920/155404.646330:INFO:filter_fuzz_stub.cc(60)] Test case: /usr/local/google/home/palmer/Downloads/New_Msan_PoC.fil [0920/155458.950323:INFO:filter_fuzz_stub.cc(52)] Invalid stream detected.
,
Sep 20 2017
@palmer, #9: The bug is still consistently reproducible on the recent most msan build. Would you like a step by step video for the same? Thanks, ~ Kushal.
,
Sep 21 2017
Oops; this: MSAN_OPTIONS=allocator_may_return_null=1 MSAN_OPTIONS=allocator_may_return_null=1 unset MSAN_OPTIONS should have been: MSAN_OPTIONS=allocator_may_return_null=1 MSAN_OPTIONS=allocator_may_return_null=0 unset MSAN_OPTIONS I.e. none of the 3 possibilities results in a crash, just the rejection of the "invalid stream". A video won't help; I believe you that you saw it. :) But I can't reproduce it. I wonder if the buggy behavior depends on something different in our different Linux systems (e.g. libc), or something. What would help is if you can let us know if you can reproduce the crash on your system without `allocator_may_return_null=1`.
,
Sep 21 2017
#11: I have tested it on 3 different machines, one ubuntu and two kali machines. Without the 'allocator_may_return_null=1' flag, the binary crashes because the re-allocation fails and throws an error as seen below: - /root/Desktop/msan-chained-origins-linux-release-503147/filter_fuzz_stub /root/Desktop/New_Msan_PoC.fil [0920/174205.911748:INFO:filter_fuzz_stub.cc(60)] Test case: /root/Desktop/New_Msan_PoC.fil ==7539==MemorySanitizer's allocator is terminating the process instead of returning 0 ==7539==If you don't like this behavior set allocator_may_return_null=1 ==7539==Sanitizer CHECK failed: /b/build/slave/linux_upload_clang/build/src/third_party/llvm/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:218 ((0)) != (0) (0, 0) Therefore, when we set the allocator_may_return_null=1 as suggested by the above crash, we get the segfault crash. This is very much similar to crbug.com/446032 Therein, we see another researcher using the same run-time flag "allocator_may_return_null=1" to prove the vulnerability. Also we see the same Sanitizer Failed output when we don't use "allocator_may_return_null=1". Several questions raised in this report and in crbug.com/763213 have been answered 2 years back in crbug.com/446032 . Hope it helps in assessing this issue and crbug.com/763213 . Thanks, ~ Kushal.
,
Sep 21 2017
Kushal, the exception you see without allocator_may_return_null=1 is the expected behavior for production Chrome/Chromium builds - i.e. a controlled, unexploitable crash when allocations fail due to OOM. Note that crbug.com/446032 is different because, at the time of the report, the crashing process (pdfium) was not subject to the OOM exception - so allocations could indeed return null in production. That's not the case here. See https://crbug.com/446032#c14 https://crbug.com/446032#c50
,
Sep 21 2017
13: Fmalita, Not sure how this is an OOM since I couldn't find any mention of the same in the crashing output. At the end of this comment, you can see another reasoning for it not being an OOM. Note that the initial crashing output in crbug.com/446032#c0 for both with and without allocator_may_return_null=1 is identical in nature to this report. See, crbug.com/446032#c3 ; crbug.com/446032 #4 ; crbug.com/446032 #51 & crbug.com/446032 #52. Also I had another look at my crashing stack trace and at the skia files that it points to and I could see that this cannot be an OOM. Here's why: - void reset(int count) { T* start = fArray; T* iter = start + fCount; while (iter > start) { (--iter)->~T(); } SkASSERT(count >= 0); if (fCount != count) { if (fCount > kCount) { // 'fArray' was allocated last time so free it now SkASSERT((T*) fStorage != fArray); sk_free(fArray); } if (count > kCount) { const uint64_t size64 = sk_64_mul(count, sizeof(T)); const size_t size = static_cast<size_t>(size64); if (size != size64) { sk_out_of_memory(); } fArray = (T*) sk_malloc_throw(size); } else if (count > 0) { fArray = (T*) fStorage; } else { fArray = nullptr; } fCount = count; } iter = fArray; T* stop = fArray + count; while (iter < stop) { new (iter++) T; } } From the crashing output in the initial report, we can see that the code jumps to reset() function line 183 and that line is executed if NOT OOM, as seen in line 180&181 of https://cs.chromium.org/chromium/src/third_party/skia/include/private/SkTemplates.h?l=162&gsn=reset. In other words, if this was an OOM, then the condition in line 180 would have been met and the flow would have moved to line 181 and not line 183. Hope that helps..:) Thanks, ~ Kushal.
,
Sep 21 2017
MSAN itself is telling you this is an allocation failure: ==7539==MemorySanitizer's allocator is terminating the process instead of returning 0 ^ a return of 0 from the allocator is indicative of an OOM. The check on line 180 has nothing to do with the available memory/OOM - it is just a sanity check that we're not trying to allocate some insane amount (the allocation size should not overflow 32 bits). The actual allocation (and OOM) occurs on line 183 (sk_malloc_throw): https://cs.chromium.org/chromium/src/third_party/skia/include/private/SkTemplates.h?rcl=db91c6e7fbfc9d1d8fd203f7e08eefb602e4a0b9&l=183
,
Sep 22 2017
c#15 & c#8: I am still not convinced why this report is not valid, since crbug.com/446032 is almost identical to my report and it also showcases both the cases, with and without the allocator_may_return_null=1 flag, And it was accepted as valid and thereafter fixed. BUT, if you believe this to not be a security issue, I would like to request you to label it "Type-Bug" and make it public. Thanks, ~ Kushal.
,
Sep 22 2017
Based on https://crbug.com/446032#c14 , it sounds like at the time when the crash was reported, pdfium was running in a process without OOM protection. In that environment, the allocator could indeed return null (instead of crashing), so allocator_may_return_null=1 was a valid MSAN config for that process. That is not the case here: Skia allocations are never allowed to return null in production. It is also our recommendation to remove the security labels and make this bug public, but will leave it to the security team for review.
,
Sep 22 2017
#17: Yep, thanks. (I assume we use Skia on Fuchsia, right? Un-check if not.)
,
Jan 22 2018
,
Aug 2
,
Jan 11
Setting defect without priority to Pri-2.
,
Jan 16
,
Jan 16
It's unclear to me if there's anything to follow up with here, so I'll mark it as WontFix. Please remind me if this is still busy. |
||||||||||
►
Sign in to add a comment |
||||||||||
Comment 1 by mea...@chromium.org
, Sep 15 2017Labels: OS-Linux
Owner: reed@chromium.org
Status: Assigned (was: Unconfirmed)