Tuesday, April 28, 2020

Fuzzing ImageIO

Posted by Samuel Groß, Project Zero

This blog post discusses an old type of issue, vulnerabilities in image format parsers, in a new(er) context: on interactionless code paths in popular messenger apps. This research was focused on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Apple ecosystem and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 image parsing API provided by it: cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ImageIO framework. Multiple vulnerabilities in image parsing code were found, reported to Apple or cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 respective open source image library maintainers, and subsequently fixed. During this research, a lightweight and low-overhead guided fuzzing approach for closed source binaries was implemented and is released alongside this blogpost.

To reiterate an important point, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerabilities described throughout this blog are reachable through popular messengers but are not part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir codebase. It is thus not cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 responsibility of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 messenger vendors to fix cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. 

Introduction


While reverse engineering popular messenger apps, I came across cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following code (manually decompiled into ObjC and slightly simplified) on a code path reachable without user interaction:

NSData* payload = [handler decryptData:encryptedDataFromSender, ...];
if (isImagePayload) {
    UIImage* img = [UIImage imageWithData:payload];
    ...;
}

This code decrypts binary data received as part of an incoming message from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sender and instantiates a UIImage instance from it. The UIImage constructor will cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n try to determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 image format automatically. Afterwards, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 received image is passed to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following code:

CGImageRef cgImage = [image CGImage];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef cgContext = CGBitmapContextCreate(0, thumbnailWidth, thumbnailHeight, ...);
CGContextDrawImage(cgContext, cgImage, ...);
CGImageRef outImage = CGBitmapContextCreateImage(cgContext);
UIImage* thumbnail = [UIImage imageWithCGImage:outImage];


The purpose of this code is to render a smaller sized version of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 input image for use as a thumbnail in a notification for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user. Unsurprisingly, similar code can be found in ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r messenger apps as well. In essence, code like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one shown above turns Apple’s UIImage image parsing and CoreGraphics image rendering code into 0click attack surface.

One of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 insights gained from developing an exploit for an iMessage vulnerability was that a memory corruption vulnerability could likely be exploited using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 described techniques if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following preconditions are met:

  1. A form of automatic delivery receipt sent from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same process handling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 messages
  2. Per-boot ASLR of at least some memory mappings
  3. Automatically restarting services

In that case, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability could for example be used to corrupt a pointer to an ObjC object (or something similar), cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n construct a crash oracle to bypass ASLR, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n gain code execution afterwards.

All preconditions are satisfied in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current attack scenario, thus prompting some research into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 robustness of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exposed image parsing code. Looking into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 documentation of UImage, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following sentence can be found: “You use image objects to represent image data of all kinds, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 UIImage class is capable of managing data for all image formats supported by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying platform”. As such, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next step was determining exactly what image formats were supported by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying platform.

An Introduction to ImageIO.framework


Parsing of image data passed to UIImage is implemented in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ImageIO framework. As such, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 supported image formats can be enumerated by reverse engineering cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ImageIO library (/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO on macOS or part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 dyld_shared_cache on iOS).

In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ImageIO framework, every supported image format has a dedicated IIO_Reader subclass for it. Each IIO_Reader subclass is expected to implement a testHeader function which, when given a chunk of bytes, should decide whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se bytes represent an image in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 format supported by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 reader. An example implementation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 testHeader implementation for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 LibJPEG reader is shown below. It simply tests a few bytes of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 input to detect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JPEG header magic.

bool IIO_Reader_LibJPEG::testHeader(IIO_Reader_LibJPEG *this, const unsigned __int8 *a2, unsigned __int64 a3, const __CFString *a4)
{
  return *a2 == 0xFF && a2[1] == 0xD8 && a2[2] == 0xFF;
}

By listing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 different testHeader implementations, it thus becomes possible to compile a list of file formats supported by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ImageIO library. The list is as follows:

IIORawCamera_Reader::testHeader
IIO_Reader_AI::testHeader
IIO_Reader_ASTC::testHeader
IIO_Reader_ATX::testHeader
IIO_Reader_AppleJPEG::testHeader
IIO_Reader_BC::testHeader
IIO_Reader_BMP::testHeader
IIO_Reader_CUR::testHeader
IIO_Reader_GIF::testHeader
IIO_Reader_HEIF::testHeader
IIO_Reader_ICNS::testHeader
IIO_Reader_ICO::testHeader
IIO_Reader_JP2::testHeader
IIO_Reader_KTX::testHeader
IIO_Reader_LibJPEG::testHeader
IIO_Reader_MPO::testHeader
IIO_Reader_OpenEXR::testHeader
IIO_Reader_PBM::testHeader
IIO_Reader_PDF::testHeader
IIO_Reader_PICT::testHeader  (macOS only)
IIO_Reader_PNG::testHeader
IIO_Reader_PSD::testHeader
IIO_Reader_PVR::testHeader
IIO_Reader_RAD::testHeader
IIO_Reader_SGI::testHeader  (macOS only)
IIO_Reader_TGA::testHeader
IIO_Reader_TIFF::testHeader

While this list contains many familiar formats (JPEG, PNG, GIF, …) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are numerous racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r exotic ones as well (KTX and ASTC, apparently used for textures or AI: Adobe Illustrator Artwork) and some that appear to be specific to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Apple ecosystem (ICNS for icons, ATX likely for Animojis)

Support for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 different formats also varies. Some formats appear fully supported and are often implemented using what appear to be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 open source parsing library which can be found in /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources on macOS: libGIF.dylib, libJP2.dylib, libJPEG.dylib, libOpenEXR.dylib, libPng.dylib, libRadiance.dylib, and libTIFF.dylib. Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r formats seem to have only rudimentary support for handling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most common cases.

Finally, some formats (e.g. PSD), also appear to support out-of-process decoding (on macOS this is handled by /System/Library/Frameworks/ImageIO.framework/Versions/A/XPCServices/ImageIOXPCService.xpc) which can help sandbox vulnerabilities in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parsers. It does not, however, seem to be possible to specify whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r parsing should be performed in-process or out-of-process in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 public APIs, and no attempt was made to change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default behaviour.

Fuzzing Closed Source Image Parsers


Given cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 wide range of available image formats and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fact that no source code is available for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 majority of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code, fuzzing seemed like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 obvious choice. 

The choice of which fuzzer and fuzzing approach to use was not so obvious. Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 majority of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target code was not open source, many standard tools were not directly applicable. Furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r, I had decided to limit fuzzing to a single Mac Mini for simplicity. Thus, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fuzzer should:
  1. Run with as little overhead as possible to fully utilize cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 available compute resources, and
  2. Make use some kind of code coverage guidance
In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end I decided to implement something myself on top of Honggfuzz. The idea for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fuzzing approach is loosely based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 paper: Full-speed Fuzzing: Reducing Fuzzing Overhead through Coverage-guided Tracing 
and achieves lightweight, low-overhead coverage guided fuzzing for closed source code by: 

  1. Enumerating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 start offset of every basic block in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 program/library. This is done with a simple IDAPython script
  2. At runtime, in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fuzzed process, replacing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first byte of every undiscovered basic block with a breakpoint instruction (int3 on Intel). The original byte and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 corresponding offset in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 coverage bitmap are stored in a dedicated shadow memory mapping whose address can be computed from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 modified library, and
  3. Installing a SIGTRAP handler that will:
    1. Retrieve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 faulting address and compute cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 offset in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 library as well as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 corresponding entry in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shadow memory
    2. Mark cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 basic block as found in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global coverage bitmap
    3. Replace cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 breakpoint with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original byte
    4. Resume execution

As only undiscovered basic blocks are instrumented and since every breakpoint is only triggered once, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 runtime overhead quickly approaches zero. It should, however, be noted that this approach only achieves basic block coverage and not edge coverage as used for example by AFL and which, for closed source targets, can be achieved through dynamic binary instrumentation albeit with some performance overhead. It will thus be more “coarse grained” and for example treat different transitions to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same basic block as equal whereas AFL would not. As such, this approach will likely find fewer vulnerabilities given cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same number of iterations. I deemed this acceptable as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 goal of this research was not to perform thorough discovery of all vulnerabilities but racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r to quickly test cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 robustness of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 image parsing code and highlight cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack vector. Thorough fuzzing, in any case, is always best performed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 maintainers with source code access.

The described approach was fairly easy to implement by patching honggfuzz’s client instrumentation code and writing an IDAPython script to enumerate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 basic block offsets. Both patch and IDAPython script can be found here

The fuzzer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n started from a small corpus of around 700 seed images covering cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 supported image formats and ran for multiple weeks. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following vulnerabilities were identified:

A bug in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 usage of libTiff by ImageIO which caused controlled data to be written past cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of a memory buffer. No CVE was assigned for this issue likely because it had already been discovered internally by Apple before we reported it.

An out-of-bounds read on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap when processing DDS images with invalid size parameters.

An out-of-bounds write on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap when processing JPEG images with an optimized parser. 

Possibly an off-by-one error in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PVR decoding logic leading to an additional row of pixel data being written out-of-bounds past cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 output buffer.

A related bug in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PVR decoder leading to an out-of-bounds read which likely had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same root cause as P0 Issue 1974 and thus was assigned cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same CVE number.

An out-of-bounds read during handling of OpenEXR images.

The last issue was somewhat special as it occurred in 3rd party code bundled with ImageIO, namely that of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OpenEXR library. As that library is open source, I decided to fuzz it separately as well. 

OpenEXR


OpenEXR is “a high dynamic-range (HDR) image file format [...] for use in computer imaging applications”. The parser is implemented in C and C++ and can be found on github.
As described above, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OpenEXR library is exposed through Apple’s ImageIO framework and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365refore is exposed as a 0click attack surface through various popular messenger apps on Apple devices. It is likely that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface is not limited to messaging apps, though I haven't conducted additional research to support that claim.

As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 library is open source, “conventional” guided fuzzing is much easier to perform. I used a Google internal, coverage-guided fuzzer running on roughly 500 cores for around two weeks. The fuzzer was guided by edge coverage using llvm’s SanitizerCoverage and generated new inputs by mutating existing ones using common binary mutation strategies and starting from a set of roughly 80 existing OpenEXR images as seeds.  

Eight likely unique vulnerabilities were identified and reported as P0 issue 1987 to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OpenEXR maintainers, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n fixed in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 2.4.1 release. They are briefly summarized next:

CVE-2020-11764
An out-of-bounds write (of presumably image pixels) on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 copyIntoFrameBuffer function.

CVE-2020-11763
A bug that caused a std::vector to be read out-ouf-bounds. Afterwards, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 calling code would write into an element slot of this vector, thus likely corrupting memory.

CVE-2020-11762
An out-of-bounds memcpy that was reading data out-of-bounds and afterwards potentially writing it out-of-bounds as well.

CVE-2020-11760, CVE-2020-11761, CVE-2020-11758
Various out-of-bounds reads of pixel data and ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r data structures.

CVE-2020-11765
An out-of-bounds read on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack, likely due to an off-by-one error previously overwriting a string null terminator on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack.

CVE-2020-11759
Likely an integer overflow issue leading to a write to a wild pointer.

Interestingly, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 crash initially found by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ImageIO fuzzer (issue 1988) did not appear to be reproducible in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 upstream OpenEXR library and was thus reported directly to Apple. A possible explanation is that Apple was shipping an outdated version of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OpenEXR library and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug had been fixed upstream in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 meantime.

Recommendations


Media format parsing remains an important issue. This was also demonstrated by ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r researchers and vendor advisories, with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two following coming immediately to mind:

This of course suggests that continuous fuzz-testing of input parsers should occur on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendor/code maintainer side. Furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r, allowing clients of a library like ImageIO to restrict cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allowed input formats and potentially to opt-in to out-of-process decoding can help prevent exploitation.

On cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 messenger side, one recommendation is to reduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface by restricting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiver to a small number of supported image formats (at least for message previews that don’t require interaction). In that case, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sender would cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n re-encode any unsupported image format prior to sending it to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiver. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case of ImageIO, that would reduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface from around 25 image formats down to just a handful or less.

Conclusion

This blog post described how image parsing code, as part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 operating system or third party libraries, end up being exposed to 0click attack surface through popular messengers. Fuzzing of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exposed code turned up numerous new vulnerabilities which have since been fixed. It is likely that, given enough effort (and exploit attempts granted due to automatically restarting services), some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 found vulnerabilities can be exploited for RCE in a 0click attack scenario. Unfortunately it is also likely that ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r bugs remain or will be introduced in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 future. As such, continuous fuzz-testing of this and similar media format parsing code as well as aggressive attack-surface reduction, both in operating system libraries (in this case ImageIO) as well as messenger apps (by restricting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 number of accepted image formats on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiver) are recommended.

Tuesday, April 21, 2020

You Won't Believe what this One Line Change Did to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chrome Sandbox

Posted by James Forshaw, Project Zero


The Chromium sandbox on Windows has stood cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 test of time. It’s considered one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 better sandboxing mechanisms deployed at scale without requiring elevated privileges to function. For all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 good, it does have its weaknesses. The main one being cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox’s implementation is reliant on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows OS. Changing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 behavior of Windows is out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 control of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chromium development team. If a bug is found in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security enforcement mechanisms of Windows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox can break.

This blog is about a vulnerability introduced in Windows 10 1903 which broke some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security assumptions that Chromium relied on to make cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox secure. I’ll present how I used cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug to develop a chain of execution to escape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox as used for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU Process on Chrome/Edge or cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default content sandbox in Firefox. The exploitation process is also an interesting insight into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 little weaknesses in Windows which in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365mselves do not cross a security boundary but led to a successful sandbox escape. This vulnerability was fixed in April 2020 as CVE-2020-0981.

Background to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Issue

Let’s have a quick look at how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chromium sandbox works on Windows before describing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug itself. The sandbox works on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 concept of least privilege by using Restricted Tokens. A Restricted Token is a feature added in Windows 2000 to reduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access granted to a process through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 modification of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Process’s Access Token through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following operations:
  • Permanently disabling Groups.
  • Removing Privileges.
  • Adding Restricted SIDs.

Disabling groups removes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Access Token’s membership, resulting in disabling access to resources secured by those groups. Removing privileges prevents cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process from performing any unnecessary privileged operations. Finally, adding restricted SIDs changes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security access check process. To be granted access to a resource we need to match a security descriptor entry for both a group in our main list as well as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list of Restricted SIDs. If one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lists of SIDs does not grant access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resource cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n access will be denied.

Chromium also uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Integrity Level (IL) feature added in Vista to furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r restrict resource access. By setting a low IL we can block write access to higher integrity resources regardless of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access check.

Using Restricted Tokens with IL in this way allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox to limit what resources a compromised process can access and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365refore cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impact an RCE can have. It’s especially important to block write access as that would typically grant an attacker leverage to compromise ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r parts of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system by writing files or registry keys.

Any process on Windows can create a new process with a different Token, for example by calling CreateProcessAsUser. What stops a sandboxed process creating a new process using an unrestricted token? Windows and Chromium implement a few security mitigations to make creating a new process outside of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox difficult:
  1. The Kernel restricts what Tokens can be assigned by an unprivileged user to a new process.
  2. The sandbox restrictions limit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 availability of suitable access tokens to use for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process.
  3. Chromium runs a sandboxed process inside a Job object which is inherited by any child processes which has a hard process quota limit of 1.
  4. From Windows 10, Chromium uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Child Process Mitigation Policy to block child process creation. This is applied in addition to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job object from 3.

All of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se mitigations are ultimately relying on Windows to be secure. However by far cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most critical is 1. Even if 2 through 4 fail, in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ory we shouldn’t be able to assign a more privileged access token to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process. What is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel checking when it comes to assigning a new token?

Assuming cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 calling process doesn’t have SeAssignPrimaryTokenPrivilege (which we don’t) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new token must meet one of two criteria which are checked in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel function SeIsTokenAssignableToProcess. The criteria are based on specified values in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel’s TOKEN object structure as shown in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following diagram

Parent/Child and Sibling Process Token Assignment Relationships


In summary cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token must eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r be:
  1. A child of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current process token. Based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new token’s Parent Token ID being equal to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Process Token’s ID.
  2. A sibling of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current process token. Based on both cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Parent Token ID and Aucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ntication ID fields being equal.

There’s also additional checks to ensure that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new Token is not an identification level impersonation token (due to this bug I reported) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IL of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new token must be less than or equal to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current process token. These are equally important, but as we’ll see, less useful in practice.

One thing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token assignment does not obviously check is whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Parent or Child tokens are restricted. If you were in a restricted token sandbox could you get an Unrestricted Token which passes all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 checks and assign it to a child effectively escaping cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox? No you can’t, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system ensures cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Sibling Token check fails when assigning Restricted Tokens and instead ensures cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Parent/Child check is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one which will be enforced. If you inspect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel function SepFilterToken, you’ll understand how this is implemented. The following code is executed when copying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 existing properties from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parent token to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new restricted token.

NewToken->ParentTokenId = OldToken->TokenId;

By setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new Restricted Token’s Parent Token ID it ensures that only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process which created cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Restricted Token can use it for a child as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Token ID is unique for every instance of a TOKEN object. At cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same time by changing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Parent Token ID cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sibling check is broken. 

However, when I was doing some testing to verify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token assignment behavior on Windows 10 1909 I noticed something odd. No matter what Restricted Token I created I couldn’t get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 assignment to fail. Looking at SepFilterToken again I found cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code had changed.

NewToken->ParentTokenId = OldToken->ParentTokenId;

The kernel code was now just copying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Parent Token ID directly across from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 old token. This completely breaks cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 check, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new sandboxed process has a token which is considered a sibling of any ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r token on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 desktop.

This one line change could just be sufficient to break out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Restricted Token sandbox, assuming I could bypass cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r 3 child process mitigations already in place. Let’s go through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trials and tribulations undertaken to do just that.

Escaping cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Sandbox

The final sandbox escape I came up with is quite complicated, it’s also not necessarily cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 optimal approach. However, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 complexity of Windows means it can be difficult to find alternative primitives to exploit in our chain.

Let’s start with trying to get a suitable access token to assign to a new process. The token needs to meet some criteria:
  1. The Token is a Primary token or convertible to a Primary Token.
  2. The Token has an IL equal to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox IL, or is writable so that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IL level can be reduced.
  3. The Token meets cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sibling token criteria so that it can be assigned.
  4. The Token is for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current Console Session.
  5. The Token is not sandboxed or is less sandboxed than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current token.

Access Tokens are securable objects cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365refore if you have sufficient access you can open a handle to a Token. However, Access Tokens are not referred to by a name, instead to open a Token you need to have access to eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r a Process or an Impersonating Thread. We can use my NtObjectManager PowerShell module to find accessible tokens using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Get-AccessibleToken command.

PS> $ps = Get-NtProcess -Name "chrome.exe" `
                  -FilterScript { $_.IsSandboxToken } `
                  -IgnoreDeadProcess
PS> $ts = Get-AccessibleToken -Processes $ps -CurrentSession `
                              -AccessRights Duplicate
PS> $ts.Count
101

This script gets a handle to every sandboxed Chrome process running on my machine (obviously start Chrome first), cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access token from each process to determine what ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r tokens we can open for TOKEN_DUPLICATE access. The reason for checking for TOKEN_DUPLICATE to use as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token in a new process is that we need to make a copy of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token as two processes can’t use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same access token object. The access check takes into account whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 calling process would have PROCESS_QUERY_LIMITED_INFORMATION access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target process which is a prerequisite for opening cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Token. We’ve got a fair number of results, over 100 entries.

However this number is deceiving, for a start, some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Tokens we can access will almost certainly be sandboxed more than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current token is sandboxed. Really we want only accessible tokens which are unsandboxed. Secondly, while cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a lot of accessible tokens, that's likely an artifact of a small number of processes being able to access a large number of tokens. We’ll filter it down to just cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command lines of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chrome processes which can access non-sandboxed tokens.

PS> $ts | ? Sandbox -ne $true | `
    Sort {$_.TokenInfo.ProcessCommandLine} -Unique | `
    Select {$_.TokenInfo.ProcessId},{$_.TokenInfo.ProcessCommandLine}

ProcessId ProcessCommandLine
--------- ----------------------------------
     6840 chrome.exe --type=gpu-process ...
    13920 chrome.exe --type=utility --service-sandbox-type=audio ...

Out of all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 potential Chrome processes only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU process and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Audio utility process have access to non-sandbox tokens. This shouldn’t come as a massive surprise. The renderer processes are significantly more locked down than eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU or Audio sandboxes due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 limitations of calling into system services for those processes to function. This does mean that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 likelihood of an RCE to sandbox escape is much reduced, as most RCE occur in rendering HTML/JS content. That said GPU bugs do exist, for example this bug is one used by Lokihardt at Pwn2Own 2016.

Let’s focus on escaping cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU process sandbox. As I don’t have a GPU RCE to hand I’ll just inject a DLL into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process to run cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 escape. That’s not as simple as it sounds, once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU process has started cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process is locked down to only loading Microsoft signed DLLs. I use a trick with KnownDlls to load cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL into memory (see this blog post for full details).

In order to escape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox we need to do is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:
  1. Open an unrestricted token.
  2. Duplicate token to create a new Primary Token and make cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token writable.
  3. Drop cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IL of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token to match cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current token (for GPU this is Low IL)
  4. Call CreateProcessAsUser with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new token.
  5. Escape Low IL sandbox.

Even for step 1 we’ve got a problem. The simplest way of getting an unrestricted token would be to open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parent process which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main Chrome browser process. However, if you look through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list of tokens cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU process can access you’ll find that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main Chrome browser process is not included. Why is that? This is intentional, as I realized after reporting this bug in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel that a GPU process sandbox could open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 browser process’ token. With this token it’s possible to create a new restricted token which would pass cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sibling check to create a new process with much more access and escape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox. To mitigate this I modified cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process token to block lower IL processes from opening cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token for TOKEN_DUPLICATE access. See HardenTokenIntegerityLevelPolicy. Prior to this fix you didn’t need a bug in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel to escape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chrome GPU sandbox, at least to a normal Low IL token.

Therefore cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 easy route is not available to us, however we should be able to trivially enumerate processes and find one which meets our criteria. We can do this by using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NtGetNextProcess system call as I described in a previous blog post (on a topic we’ll come back to later). We open all processes for PROCESS_QUERY_LIMITED_INFORMATION access, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token for TOKEN_DUPLICATE and TOKEN_QUERY access. We can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n inspect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token to ensure it’s unrestricted before proceeding to step 2.

To duplicate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token we call DuplicateTokenEx and request a primary token passing TOKEN_ALL_ACCESS as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 desired access. But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a new problem, when we try and lower cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IL we get ERROR_ACCESS_DENIED from SetTokenInformation. This is due to a sandbox mitigation Microsoft added to Windows 10 and back ported to all supported OS’s (including Windows 7). The following code is a snippet from NtDuplicateToken where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mitigation has been introduced.

ObReferenceObjectByHandle(TokenHandle, TOKEN_DUPLICATE, 
    SeTokenObjectType, &Token, &Info);
DWORD RealDesiredAccess = 0;
if (DesiredAccess) {
    SeCaptureSubjectContext(&Subject);
    if (RtlIsSandboxedToken(Subject.PrimaryToken) 
     && RtlIsSandboxedToken(Subject.ClientToken)) {
        BOOLEAN IsRestricted;
        SepNewTokenAsRestrictedAsProcessToken(Token,
            Subject.PrimaryToken, &IsRestricted);
        if (Token == Subject.PrimaryToken || IsRestricted)
            RealDesiredAccess = DesiredAccess;
        else
            RealDesiredAccess = DesiredAccess 
                & (Info.GrantedAccess | TOKEN_READ | TOKEN_EXECUTE);
    }
} else {
    RealDesiredAccess = Info.GrantedAccess;
}

SepDuplicateToken(Token, &DuplicatedToken, ...)
ObInsertObject(DuplicatedToken, RealDesiredAccess, &Handle);

When you duplicate a token cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel checks if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller is sandboxed. If sandboxed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n checks if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token to be duplicated is less restricted than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller. If it’s less restricted cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code limits cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 desired access to TOKEN_READ and TOKEN_EXECUTE. This means that if we request a write access such as TOKEN_ADJUST_DEFAULT it’ll be removed on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 handle returned to us from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 duplication call. In turn this will prevent us reducing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IL so that it can be assigned to a new process.

This would seem to end our exploit chain. If we can’t write to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token, we can’t reduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token’s IL, which prevents us from assigning it. But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation has a tiny flaw, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 duplicate operation continues to complete and returns a handle just with limited access rights. When you create a new token object cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default security grants cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller full access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Token object. This means once you get back a handle to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new Token you can call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 normal DuplicateHandle API to convert it to a fully writable handle. It’s unclear if this was intentional or not, although it should be noted that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 similar check in CreateRestrictedToken returns an error if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new token isn’t as restricted. Whatever cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case we can abuse this misfeature to get an writable unrestricted token to assign to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct IL.

Now that we can get an unrestricted token we can call CreateProcessAsUser to create our new process. But not so fast, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU process is still running in a restrictive Job object which prevents creating new processes. I detailed how Job objects prevent new process creation in my “In-Console-Able” blog post almost 5 years ago. Can we not use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same bug in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Console Driver to escape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job object? On Windows 8.1 you probably can (although I’ll admit I’ve not tested), however on Windows 10 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s two things which prevent us from using it:
  1. Microsoft changed Job objects to support an auxiliary process counter. If you have SeTcbPrivilege you can pass a flag to NtCreateUserProcess to create a new process still inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job which doesn’t count towards cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process count. This is used by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Console Driver to remove cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 requirement to escape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job. As we don’t have SeTcbPrivilege in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox we can’t use this feature.
  2. Microsoft added a new flag to Tokens which prevent cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m being used for a new process. This flag is set by Chrome on all sandboxed processes to restrict new child processes. Even without ‘1’ cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 flag would block abusing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Console Driver to spawn a new process.

The combination of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se two features blocks spawning a new process outside of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current Job by abusing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Console Driver. We need to come up with anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r way of escaping both cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job object restriction and to also circumvent cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 child process restriction flag. 

The Job object is inherited from parent to child, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365refore if we could find a process outside of a Job object which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU process can control we can use that process as a new parent and escape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job. Unfortunately, at least by default, if you check what processes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU process can access it can only open itself.

PS> Get-AccessibleProcess -ProcessIds 6804 -AccessRights GenericAll `
             | Select-Object ProcessId, Name
ProcessId Name
--------- ----
     6804 chrome.exe

Opening itself isn’t going to be very useful, and we can’t rely on getting lucky with a process which just happens to be running at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time which is both accessible and not running a Job. We need to make our own luck. 

One thing I noticed is that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a small race condition setting up a new Chrome sandbox process. The process is first created, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job object is applied. If we could get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chrome browser to spawn a new GPU process we could use it as a parent before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job object is applied. The handling of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU process even supports respawning cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process if it crashes. However I couldn’t find a way of getting a new GPU process to spawn without also causing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current one to terminate so it wasn’t possible to have code running long enough to exploit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 race.

Instead I decided to concentrate on finding a RPC service which would create a new process outside of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job. There’s quite a few RPC services where process creation is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main goal, and ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs where process creation is a side effect. For example I already documented cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Secondary Logon service in a previous blog post where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire purpose of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RPC service is to spawn new processes. 

There is a slight flaw in this idea though, specifically cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 child process mitigation flag in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token is inherited across impersonation boundaries. As it’s common to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impersonated token as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 basis for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process any new process will be blocked. However, we have an unrestricted token that does not have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 flag set. We can use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unrestricted token to create a restricted token we can impersonate during a RPC call and we can bypass cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 child process mitigation flag.

I tried to list what known services could be used in this way, which I’ve put togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following table:

Service
Is Accessible
Can Escape Job
Secondary Logon Service
No
No
WMI Win32_Process
No
Yes
User Account Control (UAC)
Yes
No
Background Intelligent Transfer Service (BITS)
No
Yes
DCOM Activator
Yes
Yes

The table is not exhaustive and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s likely to be ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r RPC services which would allow processes to be created. As we can see in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 table, well known RPC services which spawn processes such as Secondary Logon, WMI and BITS are not accessible from our sandbox level. The UAC service is accessible and as I described in a previous blog post cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re exists a way of abusing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service to run arbitrary privileged code by abusing debug objects. Unfortunately when a new UAC process is created cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service sets cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parent process to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller process. As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job object is inherited cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process will be blocked. 

The last service in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DCOM Activator. This is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system service which is responsible for starting out-of-process COM servers and is accessible from our sandbox level. It also starts all COM servers as children of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service process which means cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job object is not inherited. Seems ideal, however cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a slight issue, in order for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DCOM Activator to be useful we need an out-of-process COM server that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox can create. This object must meet a set of criteria:

  1. The Launch Security for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server grants local activation to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox.
  2. The server must not run as Interactive User (which would spawn out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox) or inside a service process.
  3. The server executable must be accessible to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 restricted token.

We don’t have to worry about criteria 3, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU process can access system executables so we’ll stick to pre-installed COM servers. It also doesn’t matter if we can’t access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM server after creation, all we need is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rights to start cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM server process outside of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n we can hijack it. We can find accessible COM servers using OleViewDotNet and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Select-ComAccess command.

PS> Get-ComDatabase -SetCurrent
PS> Get-ComClass -ServerType LocalServer32 | `
      Where-Object RunAs -eq "" | `
      Where-Object {$_.AppIdEntry.ServiceName -eq ""} | `
      Select-ComAccess -ProcessId 6804 `
           -LaunchAccess ActivateLocal -Access 0 | `
      Select-Object Clsid, DefaultServerName

Clsid                                DefaultServerName
-----                                -----------------
3d5fea35-6973-4d5b-9937-dd8e53482a56 coredpussvr.exe
417976b7-917d-4f1e-8f14-c18fccb0b3a8 coredpussvr.exe
46cb32fa-b5ca-8a3a-62ca-a7023c0496c5 ieframe.dll
4b360c3c-d284-4384-abcc-ef133e1445da ieframe.dll
5bbd58bb-993e-4c17-8af6-3af8e908fca8 ieproxy.dll
d63c23c5-53e6-48d5-adda-a385b6bb9c7b ieframe.dll

On a default installation of Windows 10 we have 6 candidates. Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last 4 are all in DLLs, however cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se classes are registered to run inside a DLL Surrogate so can still be used out-of-process. I decided to go for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 servers in COREDPUSSVR because it’s a unique executable racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 generic DLLHOST so makes it easier to find. The Launch Security for this COM server grants Everyone and all AppContainer packages local activation permission as shown below:

Security Descriptor view for COM Class showing Everyone has Access and Low Integrity Level


As an aside, even though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are two classes registered for COREDPUSSVR, only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one starting with 417976b7 is actually registered by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 executable. Creating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r class will start cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server executable, however cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class creation will hang waiting for a class which will never come.

To start cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server you call CoCreateInstance while impersonating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 child process mitigation flag-free restricted token. You need to pass cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CLSCTX_ENABLE_CLOAKING as well to activate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impersonation token, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default would use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process token which has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 child process mitigation flag set and so would block process creation. Doing this, you’ll find an instance of COREDPUSSVR running at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same sandbox level however outside of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job object and without cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 child process mitigation. Success?

Not so fast. Normally cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default security of a new process is based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default DACL inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access token used to create it. Unfortunately for some unclear reason cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DCOM activator sets an explicit DACL on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process which only grants access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user, SYSTEM and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current logon SID. This doesn’t allow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU process to open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new COM server process, even though it’s running at effectively cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same security level. So close and yet so far. I tried a few approaches to get code executed inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM server such as Windows Hooks however nothing obvious worked.

Fortunately, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default DACL is still used for any threads created after process startup. We can open one of those threads for full access and change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread context to redirect execution using SetThreadContext. We’ll need to brute force cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread IDs of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se new threads as furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r sandbox mitigations block us from using CreateToolhelp32Snapshot to enumerate processes we can’t open directly, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NtGetNextThread API requires cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parent process handle which we also don’t have. 

Abusing threads is painful especially as we can’t write anything into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process directly, but it at least works. Where to redirect execution to? I decided for simplicity to call WinExec, which will spawn a new process and only requires a command line to execute. The new process will have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default DACL and so we can open it. I could have chosen something else like LoadLibrary to load a DLL in-process. However when messing with thread contexts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a chance of crashing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process. I felt it was best just avoid that by escaping cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process as quickly as possible.

What to use as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command line for WinExec? We can’t directly write or allocate memory in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM server process but we can easily repurpose existing strings in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 binary to execute. To avoid having to find string addresses or deal with ASLR I just chose to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PE signature at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 start of DLL which gives us cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string “PE”. When passed to WinExec cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current PATH environment variable will be used to find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 executable to start. We can set PATH to anything we like in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM server as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DCOM activator will use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller’s environment when starting a process at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same security level. The only thing we need to do is find a directory we can write to, and this time we can use Get-AccessibleFile to find a candidate as shown.

PS> Get-AccessibleFile -Win32Path "C:\" -Recurse -ProcessIds 6804 `
     -DirectoryAccessRights AddFile -CheckMode DirectoriesOnly `
     -FormatWin32Path | Select-Object Name
Name
----
C:\ProgramData\Microsoft\DeviceSync

By setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PATH Environment variable to contain cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DeviceSync path and copying an executable named PE.exe to that directory we can set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread context and spawn a new process which is out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job object and can be opened by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GPU process.

We can now exploit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel bug and call CreateProcessAsUser from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unrestricted token running at Low IL. This removes all sandboxing except for Low IL. The final step is breaking out of Low IL.Again cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s probably plenty of ways of doing this but I decided to abuse cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 UAC service. I could have abused cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Debug Object bug documented in my previous blog, however I decided to abuse a different “feature” of UAC. By abusing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same Token access we’re abusing in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chain to open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unrestricted token we can get UI Access permissions. This allows us to automate privileged UI (such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Explorer Run Dialog) to execute arbitrary code outside of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Low IL sandbox. It’s not necessarily efficient but it’s more photogenic. Full documentation for this attack is available in anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r blog post.

The final chain is as follows:
  1. Open an unrestricted token.
    1. Brute force finding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process until a suitable process token is found.
  2. Duplicate token to create a new Primary Token and make cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token writable.
    1. Duplicate Token as Read Only
    2. Duplicate Handle to get back Write Access
  3. Drop cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IL of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token to match cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current token.
  4. Call CreateProcessAsUser with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new token.
    1. Create a new restricted token to remove cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 child process mitigation flag.
    2. Set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 environment block’s PATH to contain cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DeviceSync folder and drop cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PE.exe file.
    3. Impersonate restricted token and create OOP COM server.
    4. Brute force thread IDs of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM server process.
    5. Modify thread context to call WinExec passing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of a known PE signature in memory.
    6. Wait for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PE process to be created.
  5. Escape Low IL sandbox.
    1. Spawn a copy of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 On-Screen Keyboard and open its token.
    2. Create a new process with UI Access permission based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 opened token.
    3. Automate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Run dialog to escape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Low IL sandbox.

Or in diagrammatic form:

Full chain overview of sandbox escape

Wrapping Up

I hope this gives an insight into how such a small change in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows kernel can have a disproportionate impact on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security of a sandbox environment. It also demonstrates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of exploit mitigations around sandbox behaviors. At numerous points cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 easy path to exploitation was shut down due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mitigations.

It’d be interesting to read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 post-mortem on how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability was introduced. I find it likely that someone was updating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code and thought that this was a mistake and so “fixed” it. Perhaps cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re was no comment indicating its purpose, or just cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security critical nature of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 single line was lost in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mists of time. Whatever cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case it should now be fixed, which indicates it wasn’t an intentional change.

Due to “features” in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OS, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s usually some way around cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se mitigations to achieve your goal even if it takes a lot of effort to discover. These features are not in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365mselves security issues but are useful for building chains.