HackTheBox – Seal
This box was really awesome.
It was the type of box that i like the most. I learnt a lot of new things, especially bypassing reverse proxies authentication and ansible exploitation.
Firstly we have to discover services running on server. We just need to discover gitbucket service running on port 8080, then we just need to create an account and enumerate carefully what we found there.
When we find you some credentials and the fact that there is reverse proxy behind the scene we just need to look for how we can exploit that fact. When we manage to find LFI vulnerability due to inconsistent configuration of proxy and the application, we can upload malicious war file on tomcat application and get foothold.
After enumeration of crons jobs we will find out there is a cron job running as user that runs specific playbook. If we carefully investigate how this playbook works we will manage how to exploit it (there is a hint inside).
After getting control over user account, we just need to check if we can run something as root, then we just need to create malicious file that enables us to elevate privileges to root.
nmap scan:
PORT STATE SERVICE VERSION
22/tcp open ssh 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)
| 256 04:a7:4f:39:95:65:c5:b0:8d:d5:49:2e:d8:44:00:36 (ECDSA)
|_ 256 b4:5e:83:93:c5:42:49:de:71:25:92:71:23:b1:85:54 (ED25519)
443/tcp open ssl/http nginx 1.18.0 (Ubuntu)
|_http-title: Seal Market
| tls-nextprotoneg:
|_ http/1.1
| 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
|_http-server-header: nginx/1.18.0 (Ubuntu)
| tls-alpn:
|_ http/1.1
8080/tcp open http-proxy
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.1 401 Unauthorized
| Date: Fri, 23 Sep 2022 08:30:13 GMT
| Set-Cookie: JSESSIONID=node0r987at4vjgvwvfphte1c46r02.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: Fri, 23 Sep 2022 08:30:12 GMT
| Set-Cookie: JSESSIONID=node0i5g0595txavx1nxhk3s6u6q830.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: Fri, 23 Sep 2022 08:30:12 GMT
| Set-Cookie: JSESSIONID=node0e2alsdqkt5pg1t2g5my9bpuze1.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>
gobuster scan:
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: https://seal.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2022/09/23 10:35:10 Starting gobuster in directory enumeration mode
===============================================================
/admin (Status: 302) [Size: 0] [--> http://seal.htb/admin/]
/css (Status: 302) [Size: 0] [--> http://seal.htb/css/]
/host-manager (Status: 302) [Size: 0] [--> http://seal.htb/host-manager/]
/icon (Status: 302) [Size: 0] [--> http://seal.htb/icon/]
/images (Status: 302) [Size: 0] [--> http://seal.htb/images/]
/index.html (Status: 200) [Size: 19737]
/js (Status: 302) [Size: 0] [--> http://seal.htb/js/]
/manager (Status: 302) [Size: 0] [--> http://seal.htb/manager/]
===============================================================
2022/09/23 10:35:29 Finished
===============================================================
Overview of webapp on port 443:
Overview of webapp on port 8080:
Enumeration of web app on port 443 shows that main page does not have any relevant information.
Since i saw that there is possibility on account creation on the applications running on port 8080 i went straight there.
I created an account.
As we can see there are two projects. The seal_market projects is an webapp we saw before on port 443.
My first idea was „Maybe i should look for credentials at first”, since i did not remember when tomcat store it’s credentials i asked google for help.
I found credentials but at this time i have no clue how i can use it. I decided to download whole project for investigation on my local system.
My findings indicated there is a static web application, nginx server working as reverse proxy and tomcat server. I put important code below (nginx.conf):
location /manager/html {
if ($ssl_client_verify != SUCCESS) {
return 403;
}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:8000;
proxy_read_timeout 90;
proxy_redirect http://localhost:8000 https://0.0.0.0;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
}
location /admin/dashboard {
if ($ssl_client_verify != SUCCESS) {
return 403;
}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:8000;
proxy_read_timeout 90;
proxy_redirect http://localhost:8000 https://0.0.0.0;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
}
location /host-manager/html {
if ($ssl_client_verify != SUCCESS) {
return 403;
}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:8000;
proxy_read_timeout 90;
proxy_redirect http://localhost:8000 https://0.0.0.0;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:8000;
proxy_read_timeout 90;
proxy_redirect http://localhost:8000 https://0.0.0.0;
}
We can see that to access paths /host-manager/html , /manager/html , /admin/dashboard we have to use valid ssl certificate. I obviously don’t have this cert nor i have access to it.
We also can notice that this indicates that nginx works as a reverse proxy for tomcat. This was a first time when i had to deal with reverse proxy things in my htb training.
I have to admit that i was stuck, but i belive that this files was presented to me by author of this machine has meaning. I thought maybe there’s a way to bypass this proxy filtering.
I decided to google for phrase nginx tomcat reverse proxy exploit i found:
This was a presentation from blackhat conference in 2018.
I strongly recommend watching the whole speech if Orange Tsai since it’s valuable:
What he said about subject related to this box is that: if there is a reverse proxy working with web application server there is possibilty of misconfiguration since reverse proxy and server may parse requests differently (that’s our case).
Nginx processes request for /foo;name=orange/bar/, when tomcat will proces the same as /foo/bar .
I was able to bypass proxy authentication.
For pages manager and host-manager i used credentials in tomcat-user.xml commit.
After enumeration i found out that for the purpose of getting foothold endpoints: /admin and /host-manager is useless. I focused on /manager endpoint.
I remembered from doing HTB Jerry machine that we can estabilish reverse shell if we upload and execute malicious war file to tomcat server.
Then i tried to upload war file:
I didn’t work so i decided to use other LFI technique presented on previously mentioned blackhat conference.
Uploading file resulted in 403 response:
I intercepted request in burp and corrected path:
Now we can see that the war file was successfully uploaded:
After execution of shelly.war file i got foothold:
While looking for interesting files i found:
After examination of it’s content i found out that password hashed stored there are hased with sha256 so that i left it behind and keep enumerating.
Pspy tool discovered interesting cron job that is running with user privileges:
Now we just need to know that ansible is a tool for automation administration and infrastructure processes and a playbook is a form of instructions for ansible.
Code of run.yml indicates it uses function synchronize with parameter copy_links.
I checked in ansible documentation how it works:
rsync basically is *more potent* version of cp in linux.
Parameter copy_link=yes means that it copies not the symlinks but the item that the point to.
Now i had to create symlink to directory /var/lib/tomcat9/webapps/ROOT/admin/dashboard (we have control over this directory).
After some time backup appear in /opt/backups/archives:
I had to do this one more time since it did not work for the first time.
After downloading and extracting backup we can log in as luis user using his id_rsa.
First thing i always check after getting control over user account is running sudo command.
That informations means we can run ansible-playbook as root.
After reading ansible documentation I created malicious yml script: