User
Ophiuchi is a medium rated machine on HackTheBox created by felamos. In this walkthrough we will abuse insecure deserialization in a yaml parser to gain an initial foothold. After that we use the obtained tomcat credentials to ssh in as the admin user. For the root part we will abuse the use of relative paths in a go script we are allowed to run as root, changing a variable in a wasm file to switch the code path it takes.
Nmap
As usual we start our enumeration off with a nmap scan against all ports, followed by a script and version detection scan against the open ones.
All ports scan
1 |
|
Script and version scan
1 |
|
Yaml deserialization
There are only 2 ports open on the target machine, with tomcat being the biggest possible chance for success, so we will start there. Opening the page in our webbrowser we are greeted with a yaml parser on the homepage.
This might be vulnerable to deserialization if the base constructor is used for the yaml class. Following this blogpost we can test if we can make the server connect back to our machine with this piece of yaml.
1 |
|
We stand up a python webserver on the port we specified in our yaml payload.
1 |
|
Then enter our yaml payload in the website and click on Parse
.
We get redirected to a page stating that the feature has been temporarily disabled due to security reasons.
However looking on our webserver we can see a hit from the target trying to get the file we specified.
1 |
|
Following the blogpost further, we can use artsploit’s yaml-payload repository to generate payloads for rce on the server.
Following the documentation for the tool we modify the AwesomeScriptEngineFactory
function in the src/artsploit/AwesomeScriptEngineFactory.java
file. In a first step we will use it to upload the shell
file we prepared to the /tmp
directory of the webserver.
1 |
|
shell
1 |
|
After modifying the source we have to compile the code.
1 |
|
Now we set up a webserver hosting the resulting yaml-payload.jar
and modify our yaml code to download and load the file.
1 |
|
1 |
|
The deserilization seems to work and we get a hit on our server for our shell
file right after the hit for the yaml-payload.jar
.
1 |
|
With our reverse shell code being on the target we only have to execute it in a second step. We do this by simply calling bash
on the file we downloaded earlier. First we modify the source code again.
1 |
|
Recompile …
1 |
|
Set up a listener this time on the specified port to catch our reverse shell and also set up our webserver again to serve the payload.
1 |
|
1 |
|
Sending our yaml to parse it we get a callback on our webserver for the payload and a reverse shell on our listener.
1 |
|
For easier access we upgrade our reverse shell as the tomcat user and fix the terminal size.
1 |
|
Tomcat credentials
Tomcat often stores credentials in plaintext format in the tomcat-users.xml
file. This is also the case here and we get ssh access as the admin user on the machine.
1 |
|
1 |
|
Logged in as the admin user we are greeted with the user flag in his home directory.
1 |
|
Root
WASM
Checking for sudo right we see that admin is allowed to execute go run
as root on /opt/wasm-functions/index.go
.
1 |
|
The code imports the main.wasm
web assembly file. Then the exported info function get’s assigned to a variable and called. The result of this call is later converted to a string and compared to "1"
. If it isn’t equal the program prints "Not ready to deploy"
and exits. If it passes the check /bin/sh
is called on the file deploy.sh
which is not referenced by an absolute path. This means if we can both create our own custom main.wasm
and deploy.sh
and lead it down another code path, it executes the code we specify in the deploy.sh
file.
1 |
|
To not have to write the wasm from scratch we copy over the existing main.wasm
file with scp.
1 |
|
Looking at it with this tool on github we can convert the wasm to wat and see the return value for the info function is hardcoded to 0
.
Using the corresponding tool to generate wasm from wat, we can change the value to 1
and download the generated wasm file.
We scp this file over to a directory we have write access to.
1 |
|
In this directory we also create a deploy.sh
script, which is the code we want to run as root. In this case we simply give bash the suid bit as a simple method to obtain root.
deploy.sh
1 |
|
With all preparations met we can now do a go run
with sudo on /opt/wasm-functions/index.go
1 |
|
Checking bash, we see it has now the suid bit set.
1 |
|
This gives us easy access as the root user and we can add the rootflag to our collection.
1 |
|