This Week in Safe: Hide Yo SSH, Polyfill and Wrap It Up

The big news this week was that OpenSSH has an unauthorized Remote Code Execution exploit. More specifically, it had one that was fixed in 2006 that was inadvertently reintroduced in 2021’s 8.5p1. The bug is a signal handler race condition where dangerous code is called asynchronously from the SIGALARM handler. What does it mean?

To understand this, we need to dive into the world of Linux signal processing. Signals are sent by the operating system to individual processes to notify the process of a state change. For example SIGHUPor SIGNnal HangUP, originally indicated the disconnection of the serial line of the terminal where the program was running. SIGALRM is a SIGNAL ALARM indicating that the timer has expired.

The interesting thing about signal handling in Unix is ​​how it interrupts program execution. The OS has full control over execution scheduling, so in response to a signal, the scheduler suspends execution and processes the signal immediately. If no signal processing function is defined, it means the default driver provided by the OS. But if the driver is set, this function will start immediately. And here’s the dangerous part. Program execution can be anywhere in the program when it pauses, starts a signal handler, and then resumes execution. From Andries Brouwer at The Linux Kernel:

It is difficult to do interesting things in a signal handler because the process can be interrupted at any point, data structures can be in any state, etc. The three most common things to do in a signal handler are (i) set a flag variable and immediately roll back and (ii) (mess up) discard whatever the program was doing and restart at some convenient point, maybe the main command loop or something, and (iii) clean up and exit.

The term async-signal-safe describes functions that have predictable behavior even when called from a signal handler, with execution suspended in an arbitrary state. How can such a feature be dangerous? Consider the asynchronous signal-dangerous free(). Here, sections of memory are marked as free and then pointers to that memory are added to the free memory table. If program execution is interrupted between these points, we have an undefined state where memory is both free and still allocated. Calling free() a second time while execution is paused will corrupt the free memory data structure because the code is not intended to be called this way.

So back to the OpenSSH error. The SSH daemon sets a timer when a new connection arrives, and if authentication has not completed, a SIGALRM signal is generated when the timer expires. The problem is that this signal handler uses the syslog() system call, which is not an asynchronously safe function because it contains malloc() and free() system calls. The trick is to start an SSH connection, wait for the timeout to expire, and send the last bytes of the public key packet just before the timeout signal is triggered. If the public key processing function happens to be at the right point va malloc() call when the SIGALRM handler re-enters malloc(), the heap is damaged. This damage overrides the feature counter. Replace the pointer with the address where the incoming key material was stored and suddenly we have shellcode execution.

There are a few problems with turning this into a working exploit. The first is that this is a race that requires very tight timing to split the execution of the program into the correct location. The randomness of network timing makes this a big hurdle. Furthermore, all major distributions use address space layout randomization (ASLR), which should make it very difficult to override this pointer. It turns out that ASLR is somewhat broken on all major distributions as well. OK, it’s completely broken on 32-bit installations. On the Debian system tested, there is literally only one piece of ASLR in play for the glibc library. It can be located in one of two possible memory locations.

Assuming default settings for maximum SSH connections and LoginGraceTime, it takes an average of 3-4 hours to win a race condition to trigger an error, and then there is a 50% chance of guessing the correct address on the first try. The average time to jailbreak a 32-bit Debian machine seems to be five and a quarter hours. The 64-bit machine has ASLR which works a bit better. A working exploit was not proven at the time of the vulnerability note, but the authors suggest that it could be achieved within a week of attacks.

So what systems should we really care about? The regression was introduced in 8.5p1 and fixed in 9.8p1. This means that Debian 11, RHEL 8 and their derivatives are in the clear because they ship older versions of OpenSSH. Debian 12 and RHEL 9 have problems, although both distributions now have updates available that fix the problem. If you’re using one of these distributions, especially the 32-bit version, it’s time to update OpenSSH and restart the service. You can check the version of OpenSSH by running nc -w1 localhost 22 -i 1to see if you might be vulnerable.

Polyfill

Polyfill was once a useful tool for downloading JavaScript functions to emulate newer browser functions in browsers that did not perform this task. It worked by including the polyfill JS script from polyfill.io. The problem is that Funnull acquired the polyfill domain and Github account and started providing malicious scripts instead of the legitimate polyfill functionality.

The list of domains and companies caught in this supply chain attack is quite extensive, with nearly 400,000 still trying to connect to the domain as of July 3rd. We say “trying” because the providers took note of the Sansec report, breaking the story. Google blocked the associated domains from advertising, Cloudflare rewrites polyfill calls to a clean cache, and Namecheap blocked the domain, ending the attack. It’s a reminder that just because a domain is trusted now, it doesn’t mean it won’t be trusted in the future. Be careful where you link.

Wrap it up

We are no strangers to disagreement over the drama of CVE severity. There can be a desire to make a found vulnerability appear serious, and at times this leads to wildly exaggerating the impact of the problem. An example is that the node-ip project has an issue, CVE-2023-42282, that originally reached CVSS 9.8. The author of node-IP took the position that this is not a security flaw at all, as it requires untrusted input to be passed to node-ip and then used for authorization checks. This seems like a reasonable objection — if an attacker can manipulate the source IP address like this, the source IP is untrusted, regardless of this issue in node-ip.

administrator, [Fedor] called to simply archive the node-ip project in response to the seemingly bogus CVE and the endless stream of inadvertent harassment over the issue. Monitoring tools started alerting developers to the problem and they started pinging the project. Since there seemed to be no way to fight back against the message, archiving the project seemed like the best solution. However, the bug has been fixed and Github has downgraded the severity to “low” in its advisory. As a result, [Fedora] announced that the project is coming back, and indeed it is once again an active project on Github.

Bits and bytes

[sam4k] found a remote Use After Free (UAF) in the Linux Transparent Inter Process Communication (TIPC) service that can be exploited to achieve RCE. This is a kind of toy vulnerability that was found while preparing a talk about finding bugs in the Linux kernel. It’s also not a protocol that’s even built into the kernel by default, so the potential impact here is fairly low. The problem is in the fragmentation handling because the error handling skips checking the last fragment buffer and tries to free it twice. It was fixed this May in kernel version 6.8.

CocaoPods is a dependency manager for Swift/Objective-C projects and had a trio of serious problems. Most interesting was the result of the migration, where many packages lost their association with the correct administrator account. Using the CocaoPods API and an admin email address, it was possible for any user to claim these packages and make changes. This and several other issues were resolved late last year.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top