150 - Fuchsia OS, Printer Bugs, and Hacking Radare2
The two null-dereferences are pretty straight forward instances, the first being that when an error happens early on, a buffer is never assigned a value after the initial NULL
assignment. In generic error handling code, it gets dereferenced assuming the error happened after it had been setup. The second being attacker controlled data can be malformed, and have a NULL
where a pointer should be.
The overflow is a little more fun:
size_t maxsize = R_MAX (ss_const, ss_selrefs); // 1
maxsize = R_MIN (maxsize, objc->file_size);
It starts off with the above code to calculate the maximum size for the buffer it will allocate. Basically its going to choose between the largest of the two size values, or cap it at the objc->file_size
.
The problem here is that despite (potentially) capping it to the objc->file_size
the actual copies later in the code use the original ss_selrefs
and ss_const
values to signify how much data to copy. So even though it capped the size of the buffer, it’ll still try to copy more data into the buffer.
Plenty of background regarding even getting to a place to start hunting for bugs on this printer, leading up two heap based overflows in pjcc_act_checkUserPassword2
, and some discussion about exploiting the DryOS heap allocator.
The overflows were simple unchecked copies in fixed size buffers with the lengths (and buffer content) for salt
and hash
in the packet being attacker controlled and trusted without consideration for whether or not the target buffer could hold the supplied lengths. This provided a straight forward overflow and ability to corrupt heap-metadata.
They targeted a next
pointer belonging a freed-block in memory. With an echo
command, they could get this fake free block reallocated, and overwrite the data, giving them an semi-arbitrary write primitive. The main constraint appears to have been that the first few bytes would be interpreted as part of the chunk header for stuff like size
. So if it was pointed somewhere with a small value it might not be reclaimed easily or with precision.
This primitive was used to corrupt some of the state information, and specifically the echo
command handler function pointer, pointing it towards their shellcode.
The majority of this post is going into background on Fuchsia and exploiting a fake vulnerability, there was one novel vulnerability that the author came across though. To obtain a KASLR bypass, the author thought to try and gain access to the kernel log for any pointers that might be leaked. This couldn’t be done normally, but they came across sys_debuglog_create
. The documentation indicated that this would require a resource of ZX_RSRC_KIND_ROOT
type, basically this is a capability check requiring “root” privileges. Yet when he actually tried to use the function, passing in some dummy resource value, it worked.
This is because the function first checks if the provided resource is valid, and then checks its type. If the resource is an invalid handle, the code just carries on like normal, bypassing the security check.