Data center: Ashburn, VA

Telegram Chat : MBHH_x86

Email Us:

Mobile Hacker For Hire, hire a hacker, hiring a hacker, hacker with proof

OpenSSH fixes double-free memory bug that’s pokable over the network – Mobile Hacker For Hire

Table of Contents

The open source operating system distribution OpenBSD is well-known amongst sysadmins, especially those who focus on managing servers, for its focus on security over speed, features and fancy front-ends.

Fittingly, perhaps, its logo is a puffer fish – inflated, with its spikes ready to repel any wily hackers who might come along.

But the OpenBSD team is probably best known not for its entire distro, but for the remote access toolkit OpenSSH that was originally created in the late 1990s for inculsion in the operating system itself.

SSH, short for secure shell, was originally created by Finnish computer scientist Tatu Ylönen in the mid-1990s in the hope of weaning sysadmins off the risky habit of using the Telnet protocol.

The trouble with Telnet

Telnet was remarkably simple and effective: instead of connecting physical wires (or using a modem over a telephone line) to make a teletype connection to remote servers, you used a TELetype NETwork connection instead.

Basically, the data that would usually flow back and forth over a dedicated serial connection or dial-up phone connection was sent and received over the internet, using a packet-switched TCP network connection instead of a circuit-switched point-to-point link.

Same login system, cheaper connections, no need for dedicated data lines!

The giant flaw in Telnet, of course, is that it wasn’t encrypted at all, so that sniffing out your exact terminal session was trivial, allowing crackers to see every command you typed (even the mistakes you made and the times you hit [Backspace], every byte of output produced…

…and, of course, your username and password at the start of the session.

Anyone on your network path could not only easily reconstruct your sysadmin sessions in real time on their own screen, but probably also tamper with your session by modifying the commands you sent to the remote server, and even faking the replies coming back so you didn’t notice the subterfuge.

They could even set up an imposter server, lure you to it, and make it surprisingly difficult for you to spot the deception.

Strong encryption FTW

Ylönen’s SSH aimed to add a layer of strong encryption and authentication to each end of a telnet-like session, creating a secure shell (that’s what the name stands for, if you’ve ever wondered, although almost eveyone just calls it ess-ess-aitch these days).

It was an instant hit, and the protocol was quickly adopted by sysadmins everywhere.

OpenSSH soon followed, with its first version coming out in 1999, aiming to create a free, reliable, open-source implementation of the protocol that anyone could use, without any of the licensing or commercial complications that had gradually encumbered the original implementation in the years immediately after its release.

Indeed, if you run the Windows SSH server and connect to it from a Linux computer, you’ll almost certainly be using the OpenSSH implementation at both ends.

The SSH protocol is also used in other popular client-server services including SCP and SFTP, short for secure copy and secure FTP respectively. SSH loosely means, “connect securely and run a command SHell at the other end”, typically for interactive logins, because the Unix program for a command shell is usually /bin/sh. SCP is similar, but for CoPying files, because the Unix COPY command is generally called /bin/cp, and SFTP is named in much the same way.

OpenSSH isn’t the only SSH client-server toolkit in town.

Other well-known implementations include: libssh2, for developers who want to build SSH support right into their own applications; Dropbear, a stripped-down SSH server from Australian coder Matt Johnston that’s widely found on so-called IoT (Internet of Things) devices such as home routers and printers; and PuTTY, a popular, free collection of SSH-related tools for Windows from indie open-source developer Simon Tatham in England.

But if you’re a regular SSH user, you’ve almost certainly connected to at least one OpenSSH server today, not least because most contemtporary Linux distributions include it as their standard remote access tool, and Microsoft offers it as a click-to-install optional feature.

Double-free bug fix

OpenSSH version 9.2 just came out, and the release notes report as follows:

This release contains fixes for […] a memory safety problem. [This bug] is not believed to be exploitable, but we report most network-reachable memory faults as security bugs.

The bug affects sshd, the OpenSSH server (the -d suffix stands for daemon, the Unix name for the sort of background process that Windows calls a service):

sshd: fix a pre-authentication double-free memory fault introduced in OpenSSH 9.1. This is not believed to be exploitable, and it occurs in the unprivileged pre-auth process that is subject to chroot(2) and is further sandboxed on most major platforms.

A double-free bug means that a memory block you already returned to the operating system to be re-used in other parts of your program…

…will later get handed back again by a part of the program that no longer actually “owns” that memory, but doesn’t know it doesn’t.

This can lead to subtle and hard-to-unravel bugs, especially if the system marks the freed-up block as available when the first free() happens, later allocates it to another part of your code when it asks for memory via malloc(), and then marks the block free once again when the superfluous call to free() appears.

That leaves you in the sort of situation you experience when you check into a hotel that says, “Oh, good news! We thought we were full up, but another guest just decided to check out early, so you can have their room.”

Even if the room is neatly cleaned and prepared for new occupants when you go in, and thus looks as though it was properly allocated for your exclusive use, youstill have to trust that the previous guest’s keycard did indeed get correctly cancelled, and that their “early checkout” wasn’t a cunning ruse to sneak back later the same day and steal your laptop.

Bug fix for bug fix

Ironically, if you look at the recent OpenSSH code history, you’ll see that OpenSSH had a modest bug in a function called compat_kex_proposal(), used to check what sort of key-exchange algorithm to use when setting up a connection.

By the way, that’s what makes this a so-called network-reachable pre-authentication vulnerability (or pre-auth for short).

The double-free bug happens in code that needs to run after a client has initiated a remote connection, but before any key-agreement or authentication has taken place, therefore it can be triggered before any passwords or cryptographic keys have been presented for validation.

In OpenSSH 9.0, compat_kex_proposal looked something like this (simplified here):

char *compat_kex_proposal(char *suggestion)
   if (condition1) { return suggestion; }
   if (condition2) { suggestion = allocatenewstring1(); }
   if (condition3) { suggestion = allocatenewstring2(); }
   if (suggestion is blank) { error(); }
   return suggestion;                                                   

The idea is that the caller passes in their own block of memory containing a text string suggesting a key-exchange setting, and gets back either an approval to use the very suggestion they send in, or a newly-allocated text string with an updated suggestion.

The bug is that if condition 1 is false but conditions 2 and 3 are both true, the code allocates two new text strings, but only returns one.

The memory block allocated by allocatenewstring1() is never freed up – indeed, it’s just abandoned forever, allocated but never used, thus leaking memory.

Over time, this could cause trouble, up to and including the process needing to shut down to recover from memory overload.

In OpenSSH 9.1, the code was updated in an attempt to avoid allocating two strings but abandoning one of them:

/* Always returns pointer to allocated memory, caller must free. */
char *compat_kex_proposal(char *sugestion)
   char *previousone = NULL;

   if (condition1) { return newcopyof(suggestion); }
   if (condition2) { suggestion = allocatenewstring1(); }
   if (condition3) {
      previousone = suggestion;                          
      suggestion  = allocatenewstring2(); }
   if (suggestion is blank) { error(); }
   return suggestion;    

This has the double-free bug, because if condition 1 and condition 2 are both false, but condition 3 is true, then the code allocates a new string to send back as its answer…

…but incorrectly frees up the string that the caller originally passed in, because the function allocatenewstring1() was never called.

The passed-in suggestion string is memory that belongs to the caller, and that the caller will later free() up themselves, leading to the double-free danger.

Now, the code has become yet more cautious, keeping track of all three possible memory blocks used, namely the original suggestion (memory owned by someone else!), and two possible new strings that might be created on the way:

/* Always returns pointer to allocated memory, caller must free. */
char *compat_kex_proposal(char *sugestion)
   char *newone = NULL, *newtwo = NULL;

   if (condition1) { return newcopyof(suggestion); }
   if (condition2) { newone = allocatenewstring1(); }
   if (condition3) {
      newtwo  = allocatenewstring2(); }
      newone = newtwo;
   if (newone is blank) { error(); }
   return newone; 

If condition 1 is true, a direct copy of the passed-in string is used, so the caller can free that passed-in string’s memory whenever they like.

If we get past condition 1, and condition 2 is true but condition 3 is false, then alternative suggestion string1 gets returned, and the passed-in suggestion string is left alone.

If condition 2 is false and condition 3 is true, then a new suggestion string gets generated and returned, and the passed-in suggestion string is left alone.

(The manual confirms that if you call free(newone) when newone is NULL, then “no operation is performed.”)

If both 2 and 3 are true, then two new strings get allocated along the way, the first one gets freed up because it’s not needed, the second one is returned, and the passed-in suggestion string is left alone.

What to do?

As the OpenSSH team suggests, exploiting this bug will be hard because of the limited privileges that the sshd program has while it’s still setting up the connection for use.

Nevertheless, they also reported it as a security hole because it is, so make sure you’ve updated to OpenSSH 9.2.

And if you’re writing code in C, remember that no matter how experienced you get, memory management is easy to get wrong…

…so take care out there.

(Yes, Rust and its modern friends will help you to write correct code, but sometimes you will still need to use C, and even Rust can’t guarantee to stop you writing incorrect code if you program injudiciously!)

Leave a Reply

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

error: Content is protected !!