oxagast / Marshall Whittaker
I take no, and by that I mean zero fucking responsiblity for what you might do with this code. Also, this should never
be used in a production environment under any circumstances, it will make your server insecure, and quite possibly break
other things system-wide, because /etc/ld.so.preload acts on all binaries run on the system, not only sudo. Run this
code in a VM or throwaway install, for research purposes only. This is a proof of concept, and not meant to be used
for illegal things.
The code is intended to be placed in /etc/ld.so.preload where it can isolate itself in memory on the sudo process specifically
then modify the code execution of sudo as it reads a password, so that it also records the password to a world readable file in
/tmp. We do this by using a couple checks to make sure we are in the corret process, and by checking data from surrounding code
to make sure we are at the specific point in the code path by checking values of things like the file descriptor and other read()
attributes, as wel as it's returned data, to be able to lift the password. This is all accomplished as a shared library.
Compliation:
The actual compiling looks like:
gcc -fPIC -shared -ldl -Wall -o /tmp/cap_pass.so sudo_lib_hook.c
But to make things a little more simple, I created a Makefile. So:
make clean
make
sudo make install
Then when you are ready to remove the library from the system do:
sudo make deinstall
- This library, by the nature of
ld.so.preload, effects every other binary running on the system, although we do try to isolate it to sudo as much as possible. - You need to already be root for any of this to work. This code assumes that you have aquired root by means of LPE, or sitting at an unlocked terminal, but don't have the passphrase.
- If a user enters a passphrase incorrectly, that will also be logged.
The Makefile adds the resulting shared library /tmp/cap_pass.so to the file /etc/ld.so.preload.
You can now open a new terminal, and run sudo su and enter your passphrase. Do some work.. whatever.
You may now log back out, and finally, check /tmp/stolen.txt. It should now contain your
passphrase!
The abused function from sudo comes from the file tgetpass.c and the relevant call to
read() on line ~393 in commit 2a33699f8a0520161a8b507a9cb256802d6f45cb from sudo-project/sudo
is:
while (cp < ep) {
nr = read(fd, &c, 1);
if (nr != 1 || c == '\n' || c == '\r')
break;
Where nr = read(fd, &c, 1); can be isolated and swapped out for our jacking library to read
and log entry from the terminal's file descriptor to a file.
Our code assures we are in the sudo process using /proc/self/comm to grab our process name, then
use strcmp to verify it matches sudo. We then check to make sure that the "count" varaible is
equal to 1, because sudo's code does, so this helps us make sure we are modifying the read() call
in the correct part of sudo. Finally we use the %.1s format for fprintf() to assure that only a
single charater is written to our /tmp/stolen.txt file, because only a single character is read
at any given step in sudo's code from the console as the user enters their passphrase.