When we first saw tweets about a security issue in Grand Theft Auto V, it sounded a bit like a troll. “Press ‘alt and f4’ to unlock a cheat mode”, or the hacker that claims to be able to delete your character. [Tez2]’s warning tweet that you shouldn’t play GTA Online without a firewall sounds like another of these online urban legends. But this one actually seems legit. NIST is even in on the fun, assigning CVE-2023-24059 for the exploit.
When playing an online game, other users send a “join request” to join the active session. This packets can contain malformed data which has been observed to crash the game client remotely. It’s believed, though not publicly confirmed, that it’s also a Remote Code Execution (RCE) vulnerability. It seems likely that this aspect will be added to some of the various cheat panels that are already widely used for this 10-year-old game. So now, rather than just giving your own character infinite ammo and health, you can inflict some havoc on other players, possibly up to corrupting their character files and getting them banned.
But why stop there? If we have code execution inside the game, what stops another player from launching a real attack? A video game isn’t sandboxed like a browser, and there’s nothing preventing a disk wiper attack or even a worm from compromising a bunch of players. The worst part is that it’s an old game, and even though there’s a large playerbase, it’s not guaranteed to get a fix. There’s at least one project aiming to be a firewall to prevent the issue.
XNU’s 19 and 20 year old Bugs
[Adam Doupé] seems to have a knack for finding old bugs in Apple’s code, and this time it’s a pair of really old flaws in Apple’s kernel, XNU. The first is an issue in
dlil.c, the network interface handler. This issue is a type casting error, where an int is cast to a uint_16. If that cast overflows, the value becomes a large negative number, and the subsequent data write underflows the buffer and writes out-of-bounds. The method to trigger this one is a bit tricky, as it requires creating 65536 network interfaces.
There are two approaches to triggering that condition. The first is the simplest, a tiny script running as root, that calls
ifconfig repeatedly to create the interfaces. While that could be interesting as part of an exploit chain, the more interesting idea is to make a malicious USB dongle that presents itself as multiple network interfaces. The rest of the post is [Adam]’s attempt to turn the underflow into an exploit. He didn’t quite pull it off, but it looks like it’s possible.
The second bug is even older, a 20 year old flaw in XNU’s
ndrv.c, the raw socket handler. It’s an edge case where a linked list with two members get improperly walked, one of the list members is freed, but the parent item still contains a pointer to the now-freed memory. Both bugs have now been fixed in the latest iOS and macOS releases.
Android (ARM) Too
Android isn’t one to be left out, with a great writeup from [Man Yue Mo] of Github Security Lab, about a problem in the Arm Mali GPU shipped as part of Pixel 6 devices. With great irony, we are told of how the one non-Google element in the all-Google phone led to kernel-space exploitation from within an app. Specifically, it’s the driver for that GPU, and how it handles JIT memory, which is memory segments that are managed by the kernel, and accessed by userspace and directly by the GPU. And as you might expect, having three different components accessing memory at once can cause problems.
In this case, the problem is how eviction is handled. Those chunks of memory get processed, and then can be returned to the free store. A performance optimization by the driver is to keep memory buffers “warm”, not actually asking the kernel to free them, and skipping the allocation process when the next request is needed. The problem is that memory in this limbo state is considered “evictable”, and the kernel can free those regions without doing so through the GPU driver. This leave the system in an odd state where the GPU driver and userspace still have valid pointers to a memory location, but the kernel has marked it free. The real fun begins when the freed memory location is claimed by an attacking process, and a fake JIT object put in its place. By some clever memory manipulation, this can be leveraged to produce a userspace mapping of kernel code, which can then be read and written. And the simplest step from there is to just modify the userspace application, making it run as root.
It’s a clever find, but what really stands out is the problem with getting it fixed. This was reported to Android engineers in July of 2022, and a few weeks later the report was closed as a “Won’t fix” issue. There is a legitimate point here, that it’s not Android code that contains the problem, and this needed to be fixed in the ARM driver. ARM issued an update that fixed the issue less than three months later, in August of 2022. A coordinated disclosure was scheduled with ARM for November, but it seems the Android engineers completely dropped the bug, and waited til the January update to finally ship the patch to Android users. And when it finally came, it was tracked as a different bug altogether, meaning the original report was closed and forgotten about. It’s a bit disheartening to see Google show such a flippant attitude toward a vulnerability of this severity, on their own product.
It’s beginning to look like a bad idea to put the Server Message Block Daemon driver in the Linux kernel, as we have another pre-auth integer underflow leading to denial of service. Researchers at Sysdig found the flaw this time, researching based on the previous ZDI-22-1690, which was a more serious RCE in the same kernel module. This one is a bit different from other integer underflows we’ve looked at. The wrap-around nature of integers instead saves this vulnerability from being a more serious one.
The real problem is that during SMB authentication, the data structure from the remote user contains a pair of length values, which are used to parse the incoming authentication data. It’s obvious that these values aren’t implicitly trusted, and some good error checking is done to prevent a trivial buffer overflow. The case that trips us up is when
nt_len is less than
CIFS_ENCPWD_SIZE, and the resulting value is negative. When this negative integer is cast to the unsigned
size_t in a
memcpy() call, the negative integer is “unwrapped” to a nearly max-value
size_t. The memory copy function will attempt the instruction, but this is a rather uncontrolled operation, and eventually reaches inaccessible memory, and panics the kernel. So far there doesn’t seem to be a way to turn this particular flaw into a true RCE. And besides, after this many years, surely everyone knows not to expose an SMB service to untrusted users, right?
While Secure Boot hasn’t quite proven to be the dystopian PC lock-in that some of us feared, it’s still occasionally a pain to deal with while trying to fix something on a broken machine. Need a custom boot disk to run a tool? Yep, time to disable secure boot. But there’s a few cases where it’s helpful, like preventing boot malware from getting a toe-hold in an encrypted system. There’s maybe something to be said for a known quantity like secure boot.
Which is why it’s a bit odd to find that MSI decided to compromise it en masse on their desktop motherboards in a firmware update pushed out last January. And do note, MSI didn’t turn off secure boot. Check the firmware settings, or run
mokutil --sb-state, and these machines would happily inform you that Secure Boot was still enabled. But an obscure firmware setting, “Image Execution Policy” is set to “Always Execute” — so Secure Boot would still check the signature on the boot stack, and then boot it regardless of what was found. I’ll just quote the discoverer, [Dawid Potocki]’s conclusion: “Don’t trust that whatever security features you enabled are working, TEST THEM!”