Writeup — Anthem (TryHackMe)
OS: Windows Server 2019 (build 17763, Umbraco 7.15.4 + Articulate)
Difficoltà: Easy
Data: 9 settembre 2026
---
## Sommario
Macchina Windows Server 2019 non in dominio con due sole porte esposte, un webserver sulla 80 e RDP sulla 3389. Nessun exploit, nessun servizio vulnerabile: la room è interamente di osservazione. Il sito è un blog Umbraco con il plugin Articulate, e nasconde quattro flag in punti che non si vedono aprendo la pagina nel browser, tutti dentro il sorgente HTML o in campi anagrafici secondari. Il robots.txt contiene una password lasciata in cima al file fuori da qualsiasi sintassi valida. lo username corrispondente non è quello firmato in fondo ai post, che è l'autore reale della poesia citata, ma il soggetto della poesia stessa, ridotto alle iniziali secondo lo schema dell'email trovata nell'altro post. Da RDP come utente standard il filesystem è quasi vuoto, tranne un file di backup illeggibile: cambiandone le ACL dall'interfaccia di Windows si legge la password dell'Administrator, e da lì la root flag
Catena: nmap → 80 e 3389 → sorgente HTML → Umbraco/Articulate + prima flag nel placeholder di ricerca → robots.txt → password → RSS per i link reali dei post → meta og:description → due flag → pagina autore → quarta flag → poesia Solomon Grundy → username SG → RDP → user.txt → C:\backup\restore.txt illeggibile → ACL modificate → password Administrator → RDP come Administrator → root.txt.
---
## strumenti e metodologie aggiuntive
durante la sessione è stato utilizzato un llm: per recupero dettagli su CVE, interpretazione di output grezzi, suggerimenti su vettori inesplorati in caso di blocco e spiegazione dettagliata di concetti tecnici. l'esecuzione e le scelte operative erano mie. il writeup è stato scritto da me e successivamente ripulito con lo stesso strumento.
il collegamento tra la poesia e lo username è stato suggerito dal chatbot dopo che avevo esaurito una decina di formati basati sull'autore sbagliato. una flag, l'ultima, l'ho recuperata da un writeup pubblico dopo la scadenza della macchina: lo scrivo qui perché è l'unico passaggio di questa room che non ho eseguito personalmente.
---
## Premessa
room fatta dalla mia Kali virtualizzata, con la VPN già attiva dalla sessione precedente su Blueprint. tecnicamente non c'è niente di difficile, ma è la room in cui ho perso più tempo su un dettaglio solo: lo username RDP. la password si trova nei primi due minuti, il nome utente ha richiesto una quindicina di tentativi su tre persone diverse prima di capire di stare guardando il nome sbagliato
la seconda cosa che mi ha rallentato è che le flag saltano fuori da posti scollegati tra loro, meta tag, placeholder di un campo di ricerca, campi profilo, e quando le trovi non hai nessun modo di sapere a quale domanda della room corrispondono. le ho raccolte tutte prima e associate dopo,per tentativi.
la macchina è scaduta subito dopo la lettura della root flag e senza abbonamento non è ridispiegabile, quindi la parte finale di verifica dei privilegi da Administrator è rimasta non eseguita.
---
## Fase 1 — Ricognizione
stesso schema di scansione della room precedente:
IP=10.112.170.81; sudo nmap -sS -Pn -p- --min-rate 5000 -oN anthem_full.txt IP && sudo nmap -sV -sC -p (grep -oP '^\d+(?=/tcp\s+open)' anthem_full.txt | paste -sd,) -oN anthem_svc.txt $IP
Not shown: 65533 filtered tcp ports (no-response)
80/tcp open http
3389/tcp open ms-wbt-server
il secondo scan è saltato subito con "Host seems down": nella concatenazione avevo lasciato il -Pn solo nel primo comando, e su un host che filtra tutto il resto il ping preliminare fallisce. rilanciato a mano:
sudo nmap -sV -sC -Pn -p80,3389 -oN anthem_svc.txt 10.112.170.81
80/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
3389/tcp open ms-wbt-server Microsoft Terminal Services
| rdp-ntlm-info:
| Target_Name: WIN-LU09299160F
| NetBIOS_Domain_Name: WIN-LU09299160F
| DNS_Computer_Name: WIN-LU09299160F
| Product_Version: 10.0.17763
Windows Server 2019, hostname WIN-LU09299160F, e il fatto che dominio NetBIOS e nome macchina coincidano conferma che non è in dominio: gli account sono locali. tutte le altre 65533 porte sono filtered, non closed, quindi c'è un firewall che scarta invece di rifiutare .
con due sole porte e nessuna versione vulnerabile in vista, il webserver è l'unica superficie da lavorare.
---
## Fase 2 — Sorgente della homepage
invece di aprire il sito nel browser leggo direttamente l'HTML grezzo, che è più veloce e mostra anche quello che il browser non renderizza:
curl -s http://10.112.170.81/ | head -60
dalla testa della pagina esce tutto quello che serve per inquadrare l'applicazione:
invisibile guardando la pagina, perché il testo è preceduto da una cinquantina di spazi e viene troncato dal campo. si vede solo nel sorgente.
---
## Fase 3 — robots.txt
curl -s http://10.112.170.81/robots.txt
UmbracoIsTheBest!
Use for all search robots
User-agent: *
Define the directories not to crawl
Disallow: /bin/
Disallow: /config/
Disallow: /umbraco/
Disallow: /umbraco_client/
robots.txt è un file di testo che sta nella root di qualunque sito e serve a dire ai crawler dei motori di ricerca quali cartelle non indicizzare. non è un endpoint applicativo e non è una protezione: chiunque lo può leggere, e proprio perché elenca le cartelle che il proprietario vorrebbe nascondere spesso rivela i path amministrativi. va letto sempre, subito dopo la homepage, insieme a sitemap.xml
qui conferma /umbraco/ come pannello di amministrazione, ma soprattutto ha in cima una riga che con la sintassi del file non c'entra niente: UmbracoIsTheBest!. è una password, lasciata lì da qualcuno e mai tolta.
---
## Fase 4 — I post e la ricerca dell'autore
la password ce l'ho, manca lo username. i post del blog sono due, "We are hiring" e "A cheers to our IT department".
primo errore: ho provato a indovinare le URL dei post con lo schema a data tipico di WordPress (/2021/04/we-are-hiring/), e Articulate mi ha risposto sempre con la pagina archivio invece del singolo post, facendomi credere per un paio di tentativi di stare leggendo il contenuto giusto. i link veri stanno nel feed RSS, che il blog espone e che nessuno mi impediva di leggere:
curl -s http://10.112.170.81/rss | grep -oP '(?<=)[^<]+'
http://10.112.170.81/
http://10.112.170.81/archive/we-are-hiring/
http://10.112.170.81/archive/a-cheers-to-our-it-department/
il secondo post contiene la poesia:
curl -s http://10.112.170.81/archive/a-cheers-to-our-it-department/ | sed -e 's/<[^>]>//g' | grep -v '^\s$' | head -40
During our hard times our beloved admin managed to save our business by redesigning the entire website.
As we all around here knows how much I love writing poems I decided to write one about him:
Born on a Monday,Christened on Tuesday,Married on Wednesday,Took ill on Thursday,
Grew worse on Friday,Died on Saturday,Buried on Sunday.That was the end...
Author
James Orchard Halliwell
il primo post dà l'altro pezzo:
If you have an interest in being a part of the movement send me your CV at JD@anthem.com
Author
Jane Doe
quindi due nomi e un formato email. da qui parte una lunga serie di tentativi falliti,prima con xfreerdp:
xfreerdp3 /v:10.112.170.81 /u:jhalliwell /p:'UmbracoIsTheBest!' /cert:ignore +clipboard /dynamic-resolution
[ERROR][com.freerdp.core.rdp] - CONNECTION_STATE_NLA - nla_recv_pdu() fail
xfreerdp3 è il client RDP per Linux da riga di comando, l'equivalente di Connessione Desktop Remoto di Windows. /u: è l'utente locale, /p: la password trovata nel robots.txt, /cert:ignore accetta il certificato self-signed della macchina. ogni tentativo però richiede di aspettare l'handshake completo, ed è lento.
per accorciare passo a NetExec, che testa le credenziali contro il protocollo senza aprire la sessione grafica:
nxc rdp 10.112.170.81 -u jane.doe -p 'UmbracoIsTheBest!'
RDP 10.112.170.81 3389 WIN-LU09299160F [*] Windows 10 or Windows Server 2016 Build 17763 (name:WIN-LU09299160F) (domain:WIN-LU09299160F) (nla:False)
RDP 10.112.170.81 3389 WIN-LU09299160F [-] WIN-LU09299160F\jane.doe:UmbracoIsTheBest! (STATUS_LOGON_FAILURE)
nla:False è un'informazione utile in sé: l'autenticazione a livello di rete è disattivata, quindi l'autenticazione avviene dopo aver stabilito la sessione e non prima. STATUS_LOGON_FAILURE però non distingue tra utente inesistente e password errata, quindi non conferma né esclude il nome.
con un ciclo si testano nove formati in pochi secondi:
for u in JD jd jane janedoe j.doe doe UmbracoAdmin admin administrator; do nxc rdp 10.112.170.81 -u $u -p 'UmbracoIsTheBest!'; done
tutti STATUS_LOGON_FAILURE. compreso administrator, che con quella password non entra.
il ragionamento che sblocca la situazione: il post dice che la poesia è dedicata all'admin, e la firma in fondo alla pagina è di chi ha scritto il testo, non di chi ne è il soggetto. la poesia è Solomon Grundy, filastrocca inglese raccolta e pubblicata proprio da James Orchard Halliwell. l'admin quindi si chiama Solomon Grundy, e il formato dell'email dell'altro post (JD@anthem.com per Jane Doe) dice che su questa macchina gli account sono le sole iniziali.
for u in SG sg solomon grundy s.grundy sgrundy solomon.grundy; do nxc rdp 10.112.170.81 -u $u -p 'UmbracoIsTheBest!'; done
RDP 10.112.170.81 3389 WIN-LU09299160F [+] WIN-LU09299160F\SG:UmbracoIsTheBest! (Pwn3d!)
RDP 10.112.170.81 3389 WIN-LU09299160F [+] WIN-LU09299160F\sg:UmbracoIsTheBest! (Pwn3d!)
funziona sia maiuscolo che minuscolo perché Windows non distingue il case negli username. le varianti estese falliscono tutte, quindi l'account è esattamente SG.
---
## Fase 5 — Le flag nascoste nei meta
la prima flag stava in un attributo HTML, quindi vale la pena grepparne il sorgente di ogni pagina invece di leggerle a occhio:
curl -s 'http://10.112.170.81/archive/we-are-hiring/' | grep -iE 'user|admin|THM|