HTB - Seal
Basic Nmap scan
Nmap Command: nmap -Pn -n -sC -sV -oN 10.10.10.250-d-scan 10.10.10.250
Nmap scan report for 10.10.10.250
Host is up (0.15s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 4b894739673d07315e3f4c27411ff967 (RSA)
| 256 04a74f399565c5b08dd5492ed8440036 (ECDSA)
|_ 256 b45e8393c54249de7125927123b18554 (ED25519)
443/tcp open ssl/http nginx 1.18.0 (Ubuntu)
| tls-alpn:
|_ http/1.1
|_http-server-header: nginx/1.18.0 (Ubuntu)
| tls-nextprotoneg:
|_ http/1.1
|_http-title: Seal Market
| ssl-cert: Subject: commonName=seal.htb/organizationName=Seal Pvt Ltd/stateOrProvinceName=London/countryName=UK
| Not valid before: 2021-05-05T10:24:03
|_Not valid after: 2022-05-05T10:24:03
|_ssl-date: TLS randomness does not represent time
8080/tcp open http-proxy
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ Server returned status 401 but no WWW-Authenticate header.
|_http-title: Site doesn't have a title (text/html;charset=utf-8).
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.1 401 Unauthorized
| Date: Thu, 20 Oct 2022 04:12:15 GMT
| Set-Cookie: JSESSIONID=node01sqwxjtfptte1ar3carw6raxd2.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, 20 Oct 2022 04:12:13 GMT
| Set-Cookie: JSESSIONID=node0137rclvnco4znpxjpee5lk4e60.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, 20 Oct 2022 04:12:14 GMT
| Set-Cookie: JSESSIONID=node03dc6v9slx69a1dlrz9m5pweia1.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>
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8080-TCP:V=7.93%I=7%D=10/20%Time=6350CA9E%P=x86_64-unknown-linux-gn
SF:u%r(GetRequest,F4,"HTTP/1\.1\x20401\x20Unauthorized\r\nDate:\x20Thu,\x2
SF:020\x20Oct\x202022\x2004:12:13\x20GMT\r\nSet-Cookie:\x20JSESSIONID=node
SF:0137rclvnco4znpxjpee5lk4e60\.node0;\x20Path=/;\x20HttpOnly\r\nExpires:\
SF:x20Thu,\x2001\x20Jan\x201970\x2000:00:00\x20GMT\r\nContent-Type:\x20tex
SF:t/html;charset=utf-8\r\nContent-Length:\x200\r\n\r\n")%r(HTTPOptions,10
SF:8,"HTTP/1\.1\x20200\x20OK\r\nDate:\x20Thu,\x2020\x20Oct\x202022\x2004:1
SF:2:14\x20GMT\r\nSet-Cookie:\x20JSESSIONID=node03dc6v9slx69a1dlrz9m5pweia
SF:1\.node0;\x20Path=/;\x20HttpOnly\r\nExpires:\x20Thu,\x2001\x20Jan\x2019
SF:70\x2000:00:00\x20GMT\r\nContent-Type:\x20text/html;charset=utf-8\r\nAl
SF:low:\x20GET,HEAD,POST,OPTIONS\r\nContent-Length:\x200\r\n\r\n")%r(RTSPR
SF:equest,AD,"HTTP/1\.1\x20505\x20Unknown\x20Version\r\nContent-Type:\x20t
SF:ext/html;charset=iso-8859-1\r\nContent-Length:\x2058\r\nConnection:\x20
SF:close\r\n\r\n<h1>Bad\x20Message\x20505</h1><pre>reason:\x20Unknown\x20V
SF:ersion</pre>")%r(FourOhFourRequest,F4,"HTTP/1\.1\x20401\x20Unauthorized
SF:\r\nDate:\x20Thu,\x2020\x20Oct\x202022\x2004:12:15\x20GMT\r\nSet-Cookie
SF::\x20JSESSIONID=node01sqwxjtfptte1ar3carw6raxd2\.node0;\x20Path=/;\x20H
SF:ttpOnly\r\nExpires:\x20Thu,\x2001\x20Jan\x201970\x2000:00:00\x20GMT\r\n
SF:Content-Type:\x20text/html;charset=utf-8\r\nContent-Length:\x200\r\n\r\
SF:n")%r(Socks5,C3,"HTTP/1\.1\x20400\x20Illegal\x20character\x20CNTL=0x5\r
SF:\nContent-Type:\x20text/html;charset=iso-8859-1\r\nContent-Length:\x206
SF:9\r\nConnection:\x20close\r\n\r\n<h1>Bad\x20Message\x20400</h1><pre>rea
SF:son:\x20Illegal\x20character\x20CNTL=0x5</pre>")%r(Socks4,C3,"HTTP/1\.1
SF:\x20400\x20Illegal\x20character\x20CNTL=0x4\r\nContent-Type:\x20text/ht
SF:ml;charset=iso-8859-1\r\nContent-Length:\x2069\r\nConnection:\x20close\
SF:r\n\r\n<h1>Bad\x20Message\x20400</h1><pre>reason:\x20Illegal\x20charact
SF:er\x20CNTL=0x4</pre>")%r(RPCCheck,C7,"HTTP/1\.1\x20400\x20Illegal\x20ch
SF:aracter\x20OTEXT=0x80\r\nContent-Type:\x20text/html;charset=iso-8859-1\
SF:r\nContent-Length:\x2071\r\nConnection:\x20close\r\n\r\n<h1>Bad\x20Mess
SF:age\x20400</h1><pre>reason:\x20Illegal\x20character\x20OTEXT=0x80</pre>
SF:");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Open ports : 22,443,8080
PORT | SERVICE | PRODUCT | VERSION | EXTRAINFO |
---|---|---|---|---|
22 | ssh | OpenSSH | 8.2p1 Ubuntu 4ubuntu0.2 | Ubuntu Linux; protocol 2.0 |
443 | http | nginx | 1.18.0 | Ubuntu |
8080 | http-proxy |
Enum 443
Investigating the certificate we find the hostname info as seal.htb
Enum 8080
There is an option to create an account in Gitbucket.
Created an Gitbucket account sammy/Passw0rd
Discover tomcat creds
Upon exploring the gitbucket repository we found credentials for tomcat user in the tomcat-user.xml
file.
gobuster discovery
gobuster has found few folder with a 302 status. It has found admin and server is redirecting to admin/
. This redirection is happening either nginx or at tomcat.
nginx enum
The configuration file in nginx sites-enabled/default
file points to few more urls /manager/html
and /admin/dashboard
Trying to access /admin/dashboard
is blocked by nginx
but when trying to access /admin
we get an error from tomcat.
Looks like nginx is blocking the url before reaching tomcat. We need break the parser to reach the tomcat.
nginx - breaking parser logic Exploit
reference to Breaking parser logic - pdf
updating /admin/dashboard
to /admin;name=orange/dashboard
in request and we are able to successfully bypass nginx filter.
Not much information is on this url, lets check /manager/html
using the tomcat credentials found earlier we will attempt to login and we able to successfully login.
Now, we can generate a reverse shell war file and upload it.
Reverse shell
uploading the war file and catch the reverse shell.
got a 403 error. Let investigate with burpsuite. Most likely it could be the url parsing issue.
Inspecting the request in the burpsuite show that when deploy button is clicked. The request is sent to the default upload url as show below
Updating the request with /;name=orange
logic, we are able to successfully upload the file and deploy.
Deployed shell
Accessing the reverse shell.
Privilege escalation
Downloading our monitoring script and executing the script for running processes
ansible exploitation
Looks like there a cron job running every minute. It is an ansible playbook executing rum.yml file.
Analyzing run.yml file, we identify that there is back files are created from the source file /var/lib/tomcat9/webapps/ROOT/admin/dashboard
to the destination /opt/backups/files
and also links in the source folder are copied. But critical loophole is, the symbolic links are copied as items into the archived file. We shell exploit this loophole by creating a symbolic link to ssh file of the luis user in the writable folder of source.
Symbolic file create
creating the symbolic the file to ssh file in the writable folder
the backup file in the archives folder
The cron job should create a backup file
Move the backup file and extract the backup file. This extracted folder should contain the ssh file.
ssh file for luis
Luis ssh
user flag
escalating to root
Exploiting the sudo privileges. luis has sudo privileges to execute ansible playbook.
Create playbook to return a reverse shell.
Execute the playbook