Show Notes

190 - Fuzzing cURL, Netatalk, and an Emulator Escape

A hard to reach bug condition leading to a buffer overflow in Western Digital’s MyCloudHome, a consumer-grade NAS.

The core of the bug is rather straight-forward. When the handler receives an unknown command identifier it will end up calling dsi_writeinit Which takes in a buffer pointer and size. It writes any already buffered data from the look-ahead buffer into the given buffer and clears the look-ahead buffer. The problem is that despite taking in the buflen parameter, it doesn’t actually check the size before copying. So its possible to overflow the target buffer.

The challenge in exploiting this is that the look-ahead buffer will only read 8KB of data at a time, and the buffer to be overflowed is 64KB. This is an edge case though where more data will be read in. During a period of congestion when a write to the socket fails, it’ll try and peek the incoming buffer, reading in any pending data in hopes that it will clear the write-block. At this point it’ll read in more data, allowing for the look-ahead buffer to have enough content to overflow the target. The challenge is that to exploit the issue they need to fake congestion at the TCP level to block further writes, this where the custom TCP stack comes in (using Scapy, and an iptables rule).

Exploitation

Once they had the overflow they were in a pretty nice exploit situation. The overflow was controlled in terms of data being written and in terms of how far it would overflow. The target buffer also existed in the middle of a struct with other sensitive information following the buffer in memory.

To create an information disclosure there was a datalen value that could be overflowed, making it much larger. Then abusing the command replay cache when they cause the request to be replayed by making the same request back to back it would send back the data buffer, but with a corrupted length it would send back far more data.Aproximately 80% of the time they could leak a data structure containing pointers useful to break ASLR. In the failure case however it would mean the needed data couldn’t be leaked without the entire service being restarted.

With an information leak, the same structure had the input buffer pointers that could be corrupted granting the ability to write attacker controlled data to any location in member, they could also corrupt another size value to control how much data they wrote to the buffer.

With this arbitrary write ability and the information leak from earlier they replaced a function pointer for a command handler to execute the afprun function which is basically a built-in win() function like a CTF. It can run commands and even takes in a flag as to whether it should execute them as root.

Definitely a nice primitive chain for this exploit, pretty fortunate area for the overflow to happen (atleast fortunate for the attacker). It provided some great primitives and what should be a fairly stable exploit (granted the limits information disclosure). It was great to see Scapy used as part of the exploitation too, its a cool tool.

A PS2 emulator escape that can be exploited on PS4/PS5. In the previous binary episode we covered part 2 which was a stack overflow in Okage: Shadow King, by chaining that with this out-of-bounds (OOB) write in the emulator, full userland code execution is possible. As part of its duties, the PS2 emulator has to simulate Memory Mapped I/O (MMIO) for various devices such as the DVD device. The registers that are particularly relevant are the SCMD_SEND and SCMD_STATUS registers. When writing to SCMD_STATUS, the fake DVD device will update a global status buffer with the written value, and track the current position via gSStatusIndex. There’s only room for 16 entries though, and no bounds checking is performed to ensure only up to 16 entries are written, giving linear out-of-bounds write.

They then use this weaker primitive to escalate by smashing the gNStatusIndex global, which when the NCMD_STATUS register is written to can give the attacker a relative 1-byte write to escape the emulator.