This project is based on the recent security incident, named “xz utils backdoor”, that was caused by the lack of memory isolation. On some Linux distributions, developers linked OpenSSH, an implementation of SSH protocol for secure networking, with systemd, a program used to load services during the system startup. Systemd, in turn, linked the liblzma library used for data compression, which was tampered with to allow for replacing the original OpenSSH function RSA_public_decrypt()
, giving the bad actor full access to the victim’s machine. Here, we separate OpenSSH and systemd into two different processes by establishing a Remote Procedure Call mechanism to call sd_notify()
function provided by systemd library and used to notify the service manager that an OpenSSH server process had finished starting up.
In the current implementation, we make use of the rpcgen compiler. From the official documentation:
It accepts a remote program interface definition written in a language, called RPC Language, which is similar to C. It produces a C language output which includes stub versions of the client routines, a server skeleton, XDR filter routines for both parameters and results, and a header file that contains common definitions.
At the time of writing this documentation, Network Sockets are used with the loopback address to connect a server and a client as they both run on the same machine. The future implementation should rely on Unix Domain Sockets as they provide faster inter-process communication because they do not require the overhead of network protocols and communication. The rpcgen compiler does not support Unix Domain Sockets, thus writing a custom compiler might be required in the future.
- Uncomment every line that starts with a
deb-src
in /etc/apt/sources.list and run
$ sudo apt update
- Get the library's build dependencies
$ sudo apt build-dep openssh-server
- Install essential utilities
$ sudo apt install build-essential devscripts
- Install systemd library
$ sudo apt install libsystemd-dev
- Install rpcgen library
$ sudo apt-get install libtirpc-dev
- Install openssh package. Note that the version of the package used in this project is 8.9p1.
$ apt source openssh-server
- Download the sshdRPC.patch, sshdSetup.sh, libtirpcFix.sh, Makefile.sshrpc, sshrpc_clnt.c, sshrpc_server.c, sshrpc_svc.c, sshrpc.x, sshrpc.c files from this repository.
- Add the sshdRPC.patch patch file to debian/patches folder and make sure that the patch name is listed inside debian/patches/series.
- Add the rest of the files to the source code root folder.
rpcgen was part of glibc up until some point in time, after which all rpc headers were cleaned from /usr/include/rpc. However, the paths to the headers were not fixed in the library's source code, so now, after you install the rpcgen library with a new path /usr/include/tirpc/rpc, you will have to perform the fix manually. To do that, just run the libtirpcFix.sh
script, which creates all the required symbolic links:
$ sudo bash ./libtirpcFix.sh
You can inspect all the changes to the library's oriignal source code including new files generated by the rpcgen compiler in sshdRPC.patch. rpcgen uses .x files written in the Remote Procedure Call language and generates the following output:
- Stub versions of the client and server routines
- Server skeleton
- eXternal Data Representation (XDR) filter routines for parameters and results
- A header file that contains common definitions of constants and macros
In our case, since the ssh daemon acts as a client, the automatically generated client program was removed. Inside sshd.c, we create a client and make a remote procedure call to run the notification function sd_notify()
. configure.c file was changed to include to new required libraries, namely libsystemd and libtirpc. Natively, ssh server process functions as a deamon invoked at a system start-up, but since for debugging purposes we open the server manually, the HAVE_DAEMON macro has to be defined so that the server application could daemonize itself manually. Moreover, the HAVE_SYSTEMD macro has to be defined to activate the portion of the code responsible for sending a notification to the system daemon.
Navigate to the *source code root folder.
First, run Makefile.sshrpc to build the server side.
$ make -f Makefile.sshrpc
Then, run the sshdSetup.sh script to remove the files that will be created during the installation. This step needs to be performed every time before running the make install command.
$ ./sshdSetup.sh
Finally, to configure the application according to your specific machine, create the make file, and install the application, run the following:
$ ./configure
$ make
$ sudo make install
To start the newly built server application, run:
$ sudo /usr/local/sbin/sshd