Show Notes

84 - A Curl UAF, iPhone FORCEDENTRY, and a Crazy HP OMEN Driver

This is eBPF verifier code, but its more of a logical issue. Its calculating maximum and minimum values for the destination register after the shift instructions. To ensure they don’t go out of range.

Starting with the Left Shift case:

  • Line 9 - Dst min value is a left shift by min_val
  • Line 14 - Dst max value is a left shift by max value
    • These are both correct.
    • The minimum possible value will be a Left Shift by the minimum value
    • The Maximum possible value will be a Left Shift by the max Look at the Right Shift case though
  • The minimum value is a RIGHT shift by min_val
  • The maximum value is a RIGHT shift by max_val
    • This is a wrong calculation.
      • A Right Shift is like dividing by two multiple times
      • So dividing by two the MINIMUM number of times gives the MAX value not the MIN

Its hard to even call this one a vulnerability, the driver developers simply expose some kernel primitives directly to userland, nothing crazy needed. The driver supporting HP OMEN Gaming Hub software directly exposes several privileged instructions through IOCTLs. Including exposing the CPU in and out instructions which are used for communicating with the I/O ports on the CPU (such as RAM or storage devices) and rdmsr and wrmsr which are used to read and write Model Specific Registers.

The majority of the post focuses on high-level exploit strategies using these primitives. Using the I/O port access to overwrite a privileged binary on the storage device with malicious code, and abusing write access toMSR_LSTAR to replace the syscall handler and point it to attacker controlled code.

This Talos report covers a non-trivial issue where a stack pointer is used after it went out of scope when invoking JS bindings, which are provided to document creators by Nitro Pro PDF for automating aspects of the document. When one of these bindings needs to be executed by the SpiderMonkey library, the js32u.dll!js_Invoke function is used to create stack space and push a JSStackFrame object to be used by the invoked binding. It will then link the newly created stack frame to the parent JSContext in a linked list. The main thing to note here is these stack frames are backed by stack memory allocated by js_Invoke, meaning if that function returns, these stack frames go out of scope.

The problem comes into play when the Document.flattenPages() functionality for flattening the PDF is invoked in a way that can fail (such as having annotations for pages being referenced incorrectly). The application’s registered JSFunctionSpec callback will first register a structured exception handler before allocating the necessary space for it’s stack frame. If an exception is thrown, all exception handlers that were registered during compilation will be called, the first of which will convert the exception to a different exception and throw that. This results in the next exception handler in the function being skipped, which means the exception can be caught by other C++ exception handlers.

This results in code that’s responsible for cleaning up the stack (popping the stack frames that were used to execute the binding and restoring the context) being skipped, which leads to stale JSStackFrame pointers remaining attached to the parent context. Later on after the invoke function has finished, the SpiderMonkey library will end up writing to the stale pointer in the linked list of stack frames, which can be leveraged for code execution.

This post covers an infoleak in Microsoft’s Azure Sphere Security Monitor, which is a linux-based operating system for IOT devices. They focus on the SMSyscallPeripheralAcquire system call, which is used for switching the mux mode on a given pin, and change the layout of how the pins are configured. It takes an input and output buffer.

The output consists of how many input entries were processed, how many entries have an output object, then an array of the output objects themselves, which contain metadata information for the pin. One of the fields in this object (a uint16_t) is left uninitialized, and leaks 2 bytes of kernel heap memory to userspace. It’s worth noting this system call is locked behind the AZURE_SPHERE_CAP_PERIPHERAL_PIN_MAPPING capability, and thus this bug can’t be exploited from a completely unprivileged context.

Straightforward use-after-free in libcurl when processing MQTTs. The mqtt_doing() routine will attempt to send any remainder of outgoing packet data using the mq->sendleftovers pointer, freeing that pointer, but then never clearing the reference. If that function can get triggered again, it will lead to a double free.

Where glibc is used, that can be used for a tcache poisoning attack to leak heap metadata as well as craft an arbitrary write, though you would need to target it to how the application is handling and storing message data. The curl staff and the researcher have some back and forth on the exploitability of the issue, ultimately the curl staff agree on it being a security issue and resolve it.

The CoreGraphics framework for decoding JBIG2-encoded data in a PDF has an out of bounds write. This vulnerabilities originates in its attempt to calculate the number of symbols.

In calculating the number of symbols CoreGraphics will iterate over the available segments for symbol dictionary segments, then add the size of the segment to the number of symbols. It then allocates space for these symbols and fills them in. The bug comes from a lack of overflow detection when calculating the number of symbols. It is possible to increment the number of symbols beyond the range of the unsigned int, resulting in a smaller than expected allocation.

When CodeGraphics starts to fill in the symbol values it will end up outside of its allocated rage.