Normal view

There are new articles available, click to refresh the page.
Before yesterdayPentest/Red Team

Crossing Trusts 4 Delegation

By: 0xe7
4 April 2020 at 22:34

The purpose of this post is to attempt to explain some research I did not long ago on performing S4U across a domain trust. There doesn't seem to be much research in this area and very little information about the process of requesting the necessary tickets.

I highly recommend reading Elad Shamir's Wagging the Dog post before reading this, as here I'll primarily focus on the differences between performing S4U within a single domain and performing it across a domain trust but I won't be going into a huge amount of depth on the basics of S4U and it's potential for attack, as Elad has already done that so well.

Motivation

I first thought of the ability to perform cross domain S4U when looking at the following Microsoft advisory. It states:

“To re-enable delegation across trusts and return to the original unsafe configuration until constrained or resource-based delegation can be enabled, set the EnableTGTDelegation flag to Yes.”

This makes it clear that it is possible to perform cross domain constrained delegation. The problem was I couldn't find anywhere that gave any real detail as to how it is performed, and the tools used to take advantage of constrained delegation did not support it.

Luckily Will Schroeder published how to simulate real delegation traffic:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# translated from the C# example at https://msdn.microsoft.com/en-us/library/ff649317.aspx

# load the necessary assembly
$Null = [Reflection.Assembly]::LoadWithPartialName('System.IdentityModel')

# execute S4U2Self w/ WindowsIdentity to request a forwardable TGS for the specified user
$Ident = New-Object System.Security.Principal.WindowsIdentity @('[email protected]')

# actually impersonate the next context
$Context = $Ident.Impersonate()

# implicitly invoke S4U2Proxy with the specified action
ls \\PRIMARY.TESTLAB.LOCAL\C$

# undo the impersonation context
$Context.Undo()

This allowed me to figure out how it works and implement it into Rubeus.

Recap

To perform standard constrained delegation, 3 requests and responses are required: 1. AS-REQ and AS-REP, which is just the standard Kerberos authentication. 2. S4U2Self TGS-REQ and TGS-REP, which is the first step in the S4U process. 3. S4U2Proxy TGS-REQ and TGS-REP, which is the actual impersonation to the target service.

I created a visual representation as the ones I've seen previously weren't the easiest to understand:

In this it's the ticket contained within the final TGS_REP that is used to access the target service as the impersonated user.

Some Theory

After hours of using Will's Powershell to generate S4U traffic and staring at packet dumps, this is how I understood cross domain S4U to work:

Clearly there's a lot more going on here, so let me try to explain.

  1. The first step is still the same, a standard Kerberos authentication with the local domain controller. (1 and 2)

  2. A service ticket is requested for the foreign domains krbtgt service from the local domain controller. (3 and 4)

    • The users real TGT is required for this request.
    • This is known as the inter-realm TGT or cross domain TGT. This resulting service ticket is used to request service tickets for services on the foreign domain from the foreign domain controller.

    Here's where things start to get a little complicated. And the S4U2Self starts.

  3. A service ticket for yourself as the target user you want to impersonate is requested from the foreign domain controller. (5 and 6)

    • This requires the cross domain TGT.
    • This is the first step in the cross domain S4U2Self process.
  4. A service ticket for yourself as the user you want to impersonate is now requested from the local domain controller. (7 and 8)

    • This request includes the users normal TGT as well as having the S4U2Self ticket, received from the foreign domain in step 3, attached as an additional ticket.
    • This is the final step in the cross domain S4U2Self process.

    And finally the S4U2Proxy requests. As with S4U2Self, it involves 2 requests, 1 to the local DC and 1 to the foreign DC.

  5. A service ticket for the target service (on the foreign domain) is requested from the local domain controller. (9 and 10)

    • This requires the users real TGT as well as the S4U2Self ticket, received from the local domain controller in step 4, attached as an additional ticket.
    • This is the first step in the cross domain S4U2Proxy process.
  6. A service ticket for the target service is requested from the foreign domain controller. (11 and 12)

    • This requires the cross domain TGT as well as the S4U2Proxy ticket, received from the local domain controller in step 5, as an additional ticket.
    • This is the service ticket used to access the target service and the final step in the cross domain S4U2Proxy process.

I implemented this full process into Rubeus with this PR, which means that the whole process can be carried out with a single command.

The implementation primarily involves the CrossDomainS4U(), CrossDomainKRBTGT(), CrossDomainS4U2Self() and CrossDomainS4U2Proxy() functions, along with the addition of 2 new command line switches, /targetdomain and /targetdc, and some other little modifications.

Basically when /targetdomain and /targetdc are passed on the commandline, Rubeus executes a cross domain S4U, otherwise a standard one is performed.

What's The Point?

Good question. This could be a useful attack path in some unusual situations. Let me try to explain one.

Consider the following infrastructure setup:

There are 2 domains, in a single forest. internal.zeroday.lab (the parent and root of the forest) and child1.internal.zeroday.lab (a child domain).

We've compromised a standard user, child.user, on child1.internal.zeroday.lab, this user can also authenticate against the SQL server ISQL1 in internal.zeroday.lab as a low privileged user:

As Elad mentions in the MSSQL section of his blog post, if the SQL server has the WebDAV client installed and running, xp_dirtree can be used to coerce an authentication to port 80.

What is important here is that the machine account quota for internal.zeroday.lab is 0:

This means that the standard method of creating a new machine account using the relayed credentials will not work:

The machine account quota for child1.internal.zeroday.lab is still the default 10 though:

So the user child.user can be used to create a machine account within the child1.internal.zeroday.lab domain:

As the machine account belongs to another domain, ntlmrelayx.py is not able to resolve the name to a SID:

For this reason I made a small modification which allows you to manually specify the SID, rather than a name. First we need the SID of the newly created machine account:

Now the --sid switch can be used to specify the SID of the machine account to delegate access to:

The configuration can be verified using Get-ADComputer:

Impersonation

So now everything is in place to perform the S4U and impersonate users to access ISQL1.

The NTLM hash of the newly created machine account is the ast thing that is required:

The following command can be used to perform the full attack and inject the service ticket for immediate use:

1
.\Rubeus.exe s4u /user:TestChildSPN$ /rc4:C4B0E1B10C7CE2C4723B4E2407EF81A2 /domain:child1.internal.zeroday.lab /dc:IC1DC1.child1.internal.zeroday.lab /impersonateuser:internal.admin /targetdomain:internal.zeroday.lab /targetdc:IDC1.internal.zeroday.lab /msdsspn:http/ISQL1.internal.zeroday.lab /ptt

This command does a number of things but simply put, it authenticates as TestChildSPN$ from child1.internal.zeroday.lab against IC1DC1.child1.internal.zeroday.lab and impersonates internal.admin from internal.zeroday.lab to access http/ISQL1.internal.zeroday.lab.

Now let's look at this in a bit more detail.

As described previously, the first step is to perform a standard Kerberos authentication and recieve the account's TGT that has been delegated access (TestChildSPN in this case):

This TGT is then used to request the cross domain TGT from IC1DC1.child1.internal.zeroday.lab (the local domain controller):

This is simply a service ticket to krbtgt/internal.zeroday.lab. This cross domain TGT is then used on the foreign domain in exactly the same manner the users real TGT is used on the local domain.

It is this ticket that is then used to request the S4U2Self service ticket for TestChildSPN$ for the user internal.admin from IDC1.internal.zeroday.lab (the foreign domain controller):

To complete the S4U2Self process, the S4U2Self service ticket is requested from IC1DC1.child1.internal.zeroday.lab, again for TestChildSPN$ for the user internal.admin, but this time the users real TGT is used and the S4U2Self service ticket retrieved from the foreign domain in the previous step is attached as an additional ticket within the TGS-REQ:

To begin the impersonation, a S4U2Proxy service ticket is requested for the target service (http/ISQL1.internal.zeroday.lab in this case) from IC1DC1.child1.internal.zeroday.lab. As this request is to the local domain controller the users real TGT is used and the local S4U2Self, received in the previous step, is atached as an additional ticket in the TGS-REQ:

Lastly, a S4U2Proxy service ticket is also requested for http/ISQL1.internal.zeroday.lab from IDC1.internal.zeroday.lab. As this request is to the foreign domain controller, the cross domain TGT is used, and the local S4U2Proxy service ticket received in the previous step is attached as an additional ticket in the TGS-REQ. Once the final ticket is received, Rubeus automatically imports the ticket so it can be used immediately:

Now that the final service ticket has been imported it's possible to get code execution on the target server:

Conclusion

While it was possible to perform this across trusts within a single forest, I didn't manage to get this to work across external trusts. It would probably be possible but would require a non-standard trust configuration.

With most configurations this wouldn't be required as you could either create a machine account within the target domain or delegate to the same machine account, as I've discussed in a previous post, but it's important to understand the limits of what is possible with these types of attacks.

The mitigations are exactly the same as Elad discusses in his blog post as the attack is exactly the same, the only difference is here I'm performing it across a domain trust.

Acknowledgements

A big thaks to Will Schroeder for all of his work on delegation attacks and Rubeus. Also Elad Shamir for his detailed work on resource-based constrained delegation attacks and contributions to Rubeus which helped me greatly when trying to implement this. Benjamin Delpy for all of his work on Kerberos tickets in mimikatz and kekeo.

I'm sure there are many more too, without these guys work, research in this area would be much further behind where it currently is!

A Strange Case of Trusts, Machine Accounts and DNS

By: 0xe7
1 May 2020 at 11:28

While playing about with my Active directory (AD) lab infrastructure, I discovered I was able to create machine accounts across domain trusts. This led to the following bit of research.

There's been a lot of research into the impact of users creating machine accounts, including by Kevin Robertson's here and by Elad Shamir here but not much discussed about doing this across a domain trust.

The Setup

The lab I'm using for this blog post is setup as follows:

So here there are 3 forests and 4 domains (1 child domain). For the sake of simplicity this is a completely flat network, so all machines can access all other machines.

We have access to a low privileged user in the other.zeroday.lab domain.

This domain has a bidirectional external trust with the child domain child1.internal.zeroday.lab:

The child1.internal.zeroday.lab domain has an addition trust with it's parent domain internal.zeroday.lab:

Limitations Of The Current Position

It is not possible to authenticate against the internal.zeroday.lab domain using the current user:

And therefore, it is not possible to perform any real enumeration against that domain.

Also, it is not possible to create DNS records in the child1.internal.zeroday.lab domain:

Enter Machine Accounts

So while trying some things on this lab I attempted to create a machine account in child1.internal.zeroday.lab using the other.user user from other.zeroday.lab, and it worked:

The reason I tried this initially was because I wanted to create a DNS record in the trusted domain, which is now possible using this newly created machine account:

This shows that I now have more privileges on the trusted domain than I did otherwise.

But the implications were bigger, I can now use this machine account to query other trusted domains. So I can now enumerate trusts for the trusted domain internal.zeroday.lab:

And as a result, it's also possible to perform attacks such as kerberoasting against those trusted domains:

As well as triggering the printer bug discovered by Lee Christensen.

So we now clearly have much greater privileges across the enterprise than we did with only the user account we started out with.

Limitations Of Machine Accounts

While the machine accounts can create other machine account within the same domain (as I mentioned in my delegate to thyself post, a machine account is not able to create machine accounts across a trust:

This means we cannot use this machine account to pivot across the whole enterprise and gain access to the external.zeroday.lab domain without compromising another user account.

Conclusion

For me at least, this makes clear that the machine account quota configuration is more important than previously thought. By leaving this configuration at anything but 0, you allow for attackers on any domains that you have trust relationships with, to perform attacks against all other domains you have trust relationships with. Clearly it's not a huge impact if your domain only has 1 trust, then the main impact I can see is the ability for an attacker on the other domain to create DNS records within your domain.

More research is definitely needed in this area, I can't help but feel that this opens up new attacks that I'm not currently seeing.

Revisiting 'Delegate 2 Thyself'

By: 0xe7
18 August 2020 at 18:18

So while still trying to ingest the great blog post by Elad Shamir Wagging the Dog, I discovered a section called Solving a Sensitive Problem which improves on the method I used in my Delegate 2 Thyself post. This post is about that improvement and an abuse case using it.

I highly recommend reading both of those posts before reading this if you haven't done already.

The Improvement

An S4U2Self service ticket can be retrieved by any machine account, without any prior configuration.

As shown below, this machine account for EIIS1 is not configured for any type of delegation:

Also, the external.admin user is marked as Account is sensitive and cannot be delegated:

Elad says that it is still possible to impersonate as that user on the requesting system (EIIS1), all that's required are the machine account credentials or TGT.

Automating the Process

In the Wagging the Dog post, Elad was using an ASN.1 editor to modify the S4U2Self ticket obtained using Rubeus. I decided to modify Rubeus so that this process was fully automated.

All this modification does is add's a /self flag to Rubeus's s4u command, when that's used and the /altservice flag is also used, the value to /altservice (in the format of the full SPN, eg. host/computer.domain.com) is subsituted into the sname field in the returned S4U2Self ticket.

Trying It Out

In the previous post I started with code execution to the IIS server EIIS1, which is the same position here:

We already know that this user can use the tgtdeleg trick to get a usable TGT:

Now it's important to understand the rest I perform from a separate non domain-joined system. I tend to see a lot of questions about performing attacks from systems that aren't domain-joined but due to the nature of most of my work, I almost always perform the attacks from my own, non domain-joined system, so I do in my blog posts too.

So next I perform the S4U2Self using the TGT we just recieved from a different system:

As you can see here, I've requested the S4U2Self ticket then rewrote the sname to http/eiis1.external.zeroday.lab as the user that cannot de delegated external.admin, the resulting ticket can be seen in the following klist output:

This ticket can then be used to execute commands over PowerShell remoting:

Conclusion

Obviously, the only way you can take advantage of this is if you can get access to the credentials or TGT of the target system.

But it can still be used for privilege escalation and, in the case of gaining access to a system configured for unconstrained delegation, remote code exectution (because you will be able to gather usable TGT's for remote systems).

The advantages of this over the full S4U2Proxy approach is that no configuration changes are required and you are able to impersonate protected users.

The advantages of this over a traditional silver ticket is that the resulting ticket contains a valid PAC.

PowerView - A New Hope

By: 0xe7
10 November 2020 at 23:56

I'd been wanting to add some features to PowerView for a while, it's arguably the tool I use most on infrastructure assessments, and when @harmj0y officially discontinued PowerSploit I decided to fork it and start adding them.

For anyone that doesn't know, PowerView is an amazing tool written in PowerShell that can be used for playing with Active Directory and particually performing recon of Active Directory.

This post is about some new features I've added to it. My forked version can be found here.

RBCD Support

Until now dealing with RBCD (or the msds-allowedtoactonbehalfofotheridentity attribute) using PowerView was a manual process. Using Security.AccessControl.RawSecurityDescriptor with an security descriptor definition language (SDDL) string as an argument and manually converting it, as documented here and here.

I wanted to automate this so I created the Get-DomainRBCD and Set-DomainRBCD functions.

Get-DomainRBCD

Get-DomainRBCD by default finds all accounts, user and computer, that have the msds-allowedtoactonbehalfofotheridentity. It returns a custom PS object where the SID's have been resolved if possible. If identities are specified then only the RBCD configuration of those identities are returned:

It also tells you whether the account (either source account or account that's been granted delegation rights) is a user or machine account. This is useful to know because only 1 type of account can be configured on the msds-allowedtoactonbehalfofotheridentity security descriptor at once. So either all computer accounts or all user accounts, but a mixture of the 2.

Set-DomainRBCD

To compliment Get-DomainRBCD, I created Set-DomainRBCD, which can be used to configured RBCD on an account.

The Identity parameter is the account(s) where RBCD is to be configured, it can be done on multiple accounts at once and works the same way as in the other PowerView functions, like Get-DomainUser. The DelegateFrom parameter is a pipe ('|') delimited list of identities to delegate access to. The argument to DelegateFrom can be any format also supported by the Identity parameter:

Configuring RBCD the same as in the previous screenshot can be done like this:

Here, I configure RBCD on the computer account ISQL1 and delegate access to ISQL1 and ISQL2. This results in the same configured shown previously:

Finally, it is possible to easily remove this configuration using the -Clear switch to Set-DomainRBCD:

This makes dealing with RBCD using only PowerView much easier.

Ownership

A small addition to the Get-DomainUser function in PowerView was the -Owner switch. With this switch it return 2 extra object members, OwnerSID and OwnerName:

As shown here, the owner of the testsd user has the SID of S-1-5-21-2042794111-3163024120-2630140754-512 and the SamAccountName of Domain Admins. This is important for the next section.

Security Descriptors

While coding Set-DomainRBCD I realised that the msds-allowedtoactonbehalfofotheridentity attribute is just a security descriptor (SD) and it reminded me of a conversation I had in the BloodHound slack regarding the AdminCount attribute.

As discussed here members of protected groups have their AdminCount attribute set to 1 by the SD Propagator (SDProp). At the same time the security descriptor (SD) from AdminSDHolder gets applied, which is basically a hardened SD for protected objects. The problem here is that when the object is removed from having protected status, the AdminCount attribute value as well as the hardened SD remains.

It is often required to escalate accounts during assessments to perform certain attack paths, but it is always best to leave the client infrastructure in as similar state as before the assessment. So a method of viewing and restoring object SD's was required.

Enter Get-DomainObjectSD and Set-DomainObjectSD.

Get-DomainObjectSD

Get-DomainObjectSD can be used to retrieve an object's SD. By default it will output a custom PS object with 2 members (ObjectSID and ObjectSDDL).

  1. ObjectSID is the objects security idenfitier (i.e S-1-5-21-2042794111-3163024120-2630140754-1113).
  2. ObjectSDDL is the security descriptor of the object in SDDL string format.

There is also an -OutFile parameter that can be used to output the SD's and SID's to a file:

The -OutFile argument appends when the file exists so different SD's can be added dynamically:

It is also possible to retrieve several SD's at the same time, by piping the identities into Get-DomainObjectSD, like with other PowerView functions:

A -Check parameter exists which allows the current SD to be compared to a supplied one. If it's the same just a warning will be thrown but if the SD is different, a warning will be thrown and the object will be returned:

The -Check parameter also takes a file containing multiple account SD's to be checked:

Escalating A User

So after adding the testsd user to the Domain Admins group, the AdminCount attribute was set as expected:

After a while and retreiving the SD using Get-DomainObjectSD function and diffing the 2 SD's shows that they are significantly different:

Removing testsd from the Domain Admins group, leaves the AdminCount set to 1, as shown below:

The AdminCount attribute can easily be cleared using Set-DomainObject's -Clear parameter:

Set-DomainObjectSD

This is where Set-DomainObjectSD comes in. Set-DomainObjectSD can only be used from an account that has owner privileges on the object, this is partly why the -Owner switch was added to Get-DomainUser.

There are 2 ways to set object SD's with Set-DomainObjectSD, firstly using an input file with the -InputFile parameter, this takes a csv file in the same format created by Get-DomainObjectSD:

This will apply all SD's contained within the provided file. The other way is to specify the object identity and the SDDL string manually with -SDDLString:

If multiple identities are specified here, the same SD will be applied to them, unlike if an input file is provided.

Some Other Useful Features

I have added 2 other useful functions, Find-HighValueAccounts and Get-DomainDCSync.

Find-HighValueAccounts

As mentioned above, the AdminCount attribute remains even after the user has been removed from the protected group. I wanted a way to find all current members of these groups. For this I created Find-HighValueAccounts, by default it returned the full user and computer objects (I've selected just the samaccountname so it can be displayed better):

It gets group membership recursively. You can specify which type of object to return with the -Users and -Computers switches. It also supports -SPN for returning accounts with service principal names, -Enabled and -Disabled, -AllowDelegation and -DisallowDelegation; and -PassNotExpire to search for accounts that are configured to not require a regular password reset.

Get-DomainDCSync

Another useful function I created is Get-DomainDCSync which gets the ACL from the domain head, and determines which result in the ability to perform a DCSync. This is primarily 2 different types of ACE's, GenericAll or both DS-Replication-Get-Changes and DS-Replication-Get-Changes-All. This function again returns the full object and by default returns user and computer objects:

This function also gets group membership recursively and also provides the ability to filter by object type, with -Users and -Computers but this time also includes the ability to filter by groups too with -Groups.

Get-DomainUser

I've also added a few features to some standard PowerView functions, including Get-DomainUser.

Along with the already mentioned -Owner switch, I added -Enabled, -Disabled -PassNotExpire switches which are pretty self-explainatory. A -Unconstrained switch which filters user accounts that are configured for unconstrained delegation. A -RBCD switch which returns user accounts that have a non empty msds-allowedtoactonbehalfofotheridentity attribute. A -PassLastSet parameter which will only return user accounts that have not changed their password for at least a number of days:

I've also added the -Locked and -Unlocked switches. These take into account the domain lockout duration policy into account. So if a user account has been locked 31 minutes ago but the lockout duration policy is set to 30, the account will be returned as unlocked.

Get-DomainComputer

For Get-DomainComputer I've added 2 switches, -RBCD and -ExcludeDCs. The -RBCD switch which returns computer accounts that have a non empty msds-allowedtoactonbehalfofotheridentity attribute. -ExcludeDCs allows you to filter out domain controllers from the results, useful for searching for computer accounts configured for unconstrained delegation:

Conclusion

I do plan on making more additions to PowerView but hopefully these will be useful on assessments.

Until then you can grab my fork of PowerView here.

Another Delegation Edge Case

By: 0xe7
17 May 2021 at 16:43

While coding the cross domain S4U into Rubeus I only really considered the situation where the user that was to be impersonated was in the target/foreign domain, but not if the user was in the source/local domain. After looking at how the process of requesting delegation worked when impersonating a user on the local domain, I decided to write this post detailing how it works and when it might be useful.

The information in this post is reasonably complex and I won't be going over previous work on how S4U works, the best places to see this is probably the Microsoft Documentation and Elad Shamir's post. It might also be helpful to check out my original post on cross domain S4U if you haven't already.

So let's get to it.

The Standard Process

I've created a diagram for showing how these tickets are requested when the OS performs this type of delegation:

This can understandably look a little intimidating, so let's break it down:

  1. The service account gets its standard TGT from the local DC, this is nothing interesting and included for the sake of completion. (1 and 2)

  2. The account connects to the service accounts SPN using a standard service ticket, which is forwardable. (3)

  3. The service account uses its TGT to request a referral TGT from the local DC for the foreign domain where the end service resides (krbtgt/Domain2). (4 and 5)

  4. The service account uses its TGT, with the standard service ticket (provided by the connecting account) as an additional ticket, to request a service ticket for the end service SPN from the local DC. This results in what I'm calling a delegated referral TGT for the foreign domain being issued by the local DC. (6 and 7)

  5. The service account uses its referral TGT to request a service ticket for itself for the end service from the foreign DC. (8 and 9)

  6. The service account finally requests the delegated service ticket for the end service as the connecting user account from the foreign DC using the service accounts referral TGT and the delegated referral TGT (obtained in step 4 in this list or 6 and 7 in the image) as an additional ticket. (10 and 11)

From this we can determine that the main thing that is required to impersonate a local account on a service on a foreign domain is a forwardable service ticket from that account.

With this in mind, I decided to try to find a scenario this might be useful in.

The Situation

The following diagram shows the relevant part of the lab setup for this demonstration:

The position we are currently in is we have compromised the low privileged user child.user in the child domain child1.internal.zeroday.lab.

For the sake of simplicity, this user has an SPN set:

There are many ways to obtain an account with an SPN, including creating a machine account, compromising an account with an SPN, adding an SPN to an account you have Write privileges on. The other important thing here is that the user child.user has GenericWrite privileges on the machine account ISQL1 on the parent domain (internal.zeroday.lab):

The last thing to note here is the machine account quota for the parent domain (internal.zeroday.lab) is set to 0:

So there's no creating machine accounts to hop across the trust, as I demonstrated in a previous blog post.

Gaining Access to ISQL1

Due to having GenericWrite privileges on ISQL1 it is possible to configure resource-based constrained delegation (RBCD) to allow ourselves the ability to delegate to it:

At this point child1.internal.zeroday.lab\child.user can delegate to internal.zeroday.lab\ISQL1$.

The first thing we might try is to delegate to an administrative user on the foreign domain (internal.zeroday.lab), internal.admin is a member of the Domain Admins group so might be a good option. Using the Rubeus additions I did here I can try the following command to impersonate internal.admin:

1
Rubeus.exe s4u /user:child.user /rc4:C4B0E1B10C7CE2C4723B4E2407EF81A2 /domain:child1.internal.zeroday.lab /dc:ic1dc1.child1.internal.zeroday.lab /impersonateuser:internal.admin /targetdomain:internal.zeroday.lab /targetdc:idc1.internal.zeroday.lab /msdsspn:CIFS/ISQL1.internal.zeroday.lab /nowrap

This results in a KDC_ERR_BADOPTION error, as shown below:

We can see the reason for this by looking at the S4U2Self ticket returned by the local DC (IC1DC1.child1.internal.zeroday.lab) with Rubeus' describe command:

This ticket does not have the forwardable flag set, meaning it can't be used to perform the S4U2Proxy extension. Looking at the user internal.admin we can see that it is protected from delegation:

So the question becomes, what can we do if all users in the foreign domain with the desired privileges on the target system are protected from delegation? Well, there are several potential attack paths but the one we're going to focus on here is impersonating a user in the local domain that has administrative privileges on the target system. Again for simplicity sake, I've just added a user (child1.internal.zeroday.lab\sql.admin) to the local Administrators group on ISQL1:

With what we know about the process of obtaining a service ticket for child1.internal.zeroday.lab\sql.admin to internal.zeroday.lab\ISQL1, all we require is a forwardable service ticket to our account (child1.internal.zeroday.lab\child.user). Using a trick Elad mentions in the A Forwardable Result section of his Wagging the Dog post, all service tickets produced by S4U2Proxy is always forwardable.

This means that providing the user sql.admin can be delegated (shown below), we can obtain a forwardable service ticket using RBCD.

So configuring RBCD on ourselves (child.user) so we can delegate to ourselves:

The following Rubeus command was used to retrieve a forwardable service ticket as the user sql.admin for the SPN blah/foobar (just a junk one for demonstration purposes) which belongs to the account child.user:

1
Rubeus.exe s4u /user:child.user /rc4:C4B0E1B10C7CE2C4723B4E2407EF81A2 /domain:child1.internal.zeroday.lab /dc:ic1dc1.child1.internal.zeroday.lab /impersonateuser:sql.admin /msdsspn:blah/foobar /nowrap

Using Rubeus' describe command shows that this ticket is forwardable:

Now everything is in place to gain access to the remote system ISQL1. The following requests is the process in full described earlier to obtain the desired delegated service ticket for CIFS/ISQL1.internal.zeroday.lab as the user child1.internal.zeroday.lab, with any requests not required omitted. Each request, except gaining the TGT initially, are made manually using the asktgs Rubeus command.

Firstly the TGT for the service account (child.user) is required:

We already have the forwardable service ticket to child.user, so we don't need to worry about that. Next we have to obtain a referral TGT as the service account (child.user) for the foreign domain (internal.zeroday.lab), for this we only require the TGT just obtained. We can use the following command for that:

1
Rubeus.exe asktgs /service:krbtgt/internal.zeroday.lab /dc:ic1dc1.child1.internal.zeroday.lab /nowrap /ticket:doIFq...(snip)...

The last thing we require from the local DC is the delegated referral TGT, to get this I made another PR to Rubeus which allows for including additional tickets when using asktgs by providing the /tgs:X argument. Using the following command and including the primary TGT for the service account (child.user) as the /ticket:X argument and the forwardable service ticket as the /tgs:X argument, it is possible to request this delegated referral TGT:

1
Rubeus.exe asktgs /service:CIFS/ISQL1.internal.zeroday.lab /nowrap /dc:ic1dc1.child1.internal.zeroday.lab /ticket:doIFqjCCB...(snip)... /tgs:doIGPDCCB...(snip)...

We can skip requesting a service ticket for the end service using only the referral TGT for child.user as we won't be using that ticket. The last thing we need to do it request the final service ticket for CIFS/ISQL1.internal.zeroday.lab from the DC for the domain internal.zeroday.lab (IDC1.internal.zeroday.lab), this is the ticket we can use to impersonate sql.admin on the target service. To do this we use a similar command to the one we just run, except instead of the TGT and fowardable service ticket, we use the referral TGT and delegated referral TGT, and instead of the local DC we request it from the foreign DC, you also have to pass Rubeus the /usesvcdomain switch because cross-domain stuff is hard:

1
Rubeus.exe asktgs /service:CIFS/ISQL1.internal.zeroday.lab /nowrap /dc:idc1.internal.zeroday.lab /usesvcdomain /ticket:doIFpjCCB...(snip)... /tgs:doIHJjCCB...(snip)...

And finally we get the service ticket we're after:

Using this ticket gives as access to the CIFS service on the target ISQL1:

Conclusion

While this attack path is probably not normally required, due to other easier attack paths being likely possible, it does show that unsual edge cases exist that could allow for privilege escalation within a domain or even across domain trusts. Defenders should therefore ensure that they are fully aware of the configuration of their whole enterprise and the implications any of those configurations could have on the security of the infrastructure as a whole.

CVE-2021-42287/CVE-2021-42278 Weaponisation

By: 0xe7
9 December 2021 at 23:13

So on 9th November 2021, Cliff Fisher tweeted about a bunch of CVE's to do with Active Directory that caught a lot of people's eyes. These included CVE-2021-42278, CVE-2021-42291, CVE-2021-42287 and CVE-2021-42282. The one that caught my eye the most was CVE-2021-42287 as it related to PAC confusion and impersonation of domain controllers, also having just worked on PAC forging with Rubeus 2.0.

This post discusses my quest to figure out how to exploit this issue and some things I discovered along the way.

I just want to highlight that there's no new research here, this issue was discovered by Andrew Bartlett of Catalyst IT. I just found one way to weaponise it, there may well be others in the issues he found.

A Little Digging

So immediately upon seeing Cliff's tweet, Ceri Coburn and I started tryng to figure out how this could be exploited. We (perhaps incorrectly) latched onto the text on Microsofts description of CVE-2021-42287 which seemed to be based around the idea of TGT's being issued without PACs. This led me to modify Rubeus to allow for requesting TGT's without a PAC.

After Ceri debugging the Windows KDC and us digging through the leaked XP source we were convinced that to trigger the codepath we needed to go down (to insert a PAC into a ST when it was requested with a TGT lacking a PAC) required a cross domain S4U2self but was unable to get it to work. The only way we could get a DC to add a PAC when an service ticket (ST) was requested using a TGT without a PAC was by configuring altSecurityIdentities.

This process involves modifying the altSecurityIdentities attribute of an account in a foreign domain to Kerberos:[samaccountname]@[domain] to impersonate that user.

So below you can see a low privileged user (internal.user) of the local doamin (internal.zeroday.lab) has GenericAll over a high privileged user (external.admin) of a different domain (external.zeroday.lab):

As this user we can add ourselves to the altSecurityIdentities attribute as shown below:

Now we can get a TGT from our local DC and request it without a PAC using the new /nopac switch:

This results in an obviously small TGT. We then use that TGT to request a referral to the target domain (external.zeroday.lab) from our local DC:

That referral can then be used to request ST's for services on our target domain (external.zeroday.lab). Here I'm requesting a ST for LDAP/EDC1.external.zeroday.lab the DC's LDAP service:

The size of the ST is very large compared to the previous 2 tickets, this is because (as we'll see) a PAC has been added. As shown in the klist output below, this ST is for the original user internal.user which has no special privileges on either domain:

Using this ST, however, we can DCSync:

So what happened here is the DC has searched for the account in the local database, it hasn't found it so it's then searched to see if any accounts have this account listed in their AltSecurityIdentities attribute, which external.admin does because we added it earlier, and if so, the DC adds a PAC belonging to that account. This can be verified using Rubeus' describe command and the AES256 key we just DCsync'd:

We now effectly have the privileges of the external.admin user on the external.zeroday.lab domain.

This didn't help us exploiting the issue we wanted but I did find it interesting.

Some Progress

Then along came this tweet from Clément Notin which actually mentioned the Samba information regarding these issues and led me to CVE-2020-25719 and this patch. What particularly caught my attention was this paragraph:

Delegated administrators with the right to create other user or machine accounts can abuse the race between the time of ticket issue and the time of presentation (back to the AD DC) to impersonate a different account, including a highly privileged account.

Suddenly I realised that to make the local lookup fail, we didn't need to attack a foreign domain but perhaps remove the account after retrieving the TGT.

I started playing with naming a machine account the same as the local DC (minus the $), requesting a TGT (still without a PAC), removing the machine account and using that TGT. I noticed something funny.

When using this PAC-less TGT with a U2U request but without supplying an additional ticket, it was failing to decrypt the resulting ST:

The U2U ST should be encrypted with the session of within the provided TGT but as I didn't provide an additional ticket I assumed it was triyng to lookup the account based on the sname which I was setting to IDC1 the samaccountname of my now missing machine account. I had the idea to try decrypting this ST using the long term key of the domain controller that I was naming my machine account after (IDC1$):

It worked! It sucessfuly decrypted the ST, it just couldn't find the PAC because there wasn't one there. I tried the same thing using S4U2self and got the same result, the DC was looking for my IDC1 account, not finding it and then search for the same but adding a $ on the end, finding the domain controller account and encrypting the ticket using it's key instead.

At that time I still couldn't figure out why it wasn't adding the PAC, so I decided to try requesting the initial TGT with a PAC instead of without a PAC and surprisingly it worked! So apparently there was no need to request a TGT without a PAC, supplying a TGT with a PAC for an account that has the samaccountname of the DC minus the $ to a request for an S4U2self ticket, when the intial account no longer exists, results in the ST being encrypted using the key of the DC.

The sname of that resulting ST can be modified as per Alberto Solino's post here. So it can be used to authenticate against any service on the target box, even users protected from delegation, as Elad Shamir mentions in the Solving a Sensitive Problem section of Wagging the Dog.

The last thing to work out was how can we get a machine account in this state from a low privileged user, as until now I was manually modifying the machine account as an admin. Thankfully Kevin Robertson's amazing post on the Macine Account Quota helped massively. It explains that the creator of the machine account has control over various attributes including the samAccountName and ServicePrincipalName. Another problem I was running into was trying to change the samaccountname, as trying to change it to be the same as the DC minus the $, I was getting the following error:

As Kevin mentions in his post:

If you modify the samAccountName, DnsHostname, or msDS-AdditionalDnsHostName attributes, the SPN list will automatically update with the new values.

So the SPN it was trying to set was already an SPN belonging to the target DC. Ceri suggested removing the SPNs before changing the samaccountname, which worked.

Lastly, until now I was removing the machine account after requesting the TGT (which requires admin privileges), I had to test whether disabling it or renaming it worked too. Disabling it resulted in a S_PRINCIPAL_UNKNOWN error being returned by the DC when requesting the S4U2self but renaming it worked.

Finally all of the pieces were in place.

Checking If Exploitable

To exploit this requires 3 things, at least 1 DC not patched with either KB5008380 or KB5008602, any valid domain user account and a Machine Account Quota (MAQ) above 0.

To determine if a DC is patched is very easy. Using my additional /nopac switch to Rubeus' asktgt, request a TGT without a PAC, if the DC is vulnerable it'll look like the following:

Look at the size of the returned TGT. If the DC is not vulnerable the TGT will look as follows:

The size difference is immediately obvious. The next thing to check would be the MAQ:

By default it is 10 as above but can be changed, anything above 0 will do. Lastly we need to check the SeMachineAccountPrivilege which is granted to Authenticated Users by default:

If everything checks out, we can exploit this issue.

The Full Attack

The first step is to create a machine account we can use for the attack (The account I create is called TestSPN$). Kevin's Powermad works nicely for this:

After this, PowerView's Set-DomainObject can be used to clear the SPNs from the machine account:

Changing the machine account's samaccountname can be done using Powermad's Set-MachineAccountAttribute (Here I'm changing it to IDC1, because the DC's samaccountname is IDC1$):

Rubeus' asktgt can be leveraged to request a TGT for that newly created machine account (This is just a normal TGT for the machine we just created but using it's new samaccontname):

Set-MachineAccountAttribute can again be used to change the machine accounts samaccountname (either back to what it was or something else entirely, it doesn't matter):

With the machine account renamed, it is now possible to request an S4U2self ticket using the retrieved TGT and get an ST encrypted with the DC's key, at the same time we can rewrite the sname within the ticket to be the LDAP service:

Here, I've impersonated the Administrator user for the LDAP service on the DC. It's worth noting that this could be any user on any service on any system on the domain.

The ticket has been sucessfully injected into LSA as shown below:

Using that ticket it is now possible to DCSync:

The commands I run to do this are shown below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Create Machine Account
New-MachineAccount -MachineAccount TestSPN -Domain internal.zeroday.lab -DomainController idc1.internal.zeroday.lab -Verbose

# Clear SPNs
Set-DomainObject "CN=TestSPN,CN=Computers,DC=internal,DC=zeroday,DC=lab" -Clear 'serviceprincipalname' -Verbose

# Change Machine Account samaccountname
Set-MachineAccountAttribute -MachineAccount TestSPN -Value "IDC1" -Attribute samaccountname -Verbose

# Request TGT
.\Rubeus.exe asktgt /user:IDC1 /password:Password1 /domain:internal.zeroday.lab /dc:idc1.internal.zeroday.lab /nowrap

# Change Machine Account samaccountname
Set-MachineAccountAttribute -MachineAccount TestSPN -Value "TestSPN" -Attribute samaccountname -Verbose

# Request S4U2self
.\Rubeus.exe s4u /impersonateuser:Administrator /nowrap /dc:idc1.internal.zeroday.lab /self /altservice:LDAP/IDC1.internal.zeroday.lab /ptt /ticket:[TGT]

Mitigation / Detection

The best way to mitigate against this is to install the Microsoft patch (KB5008602), this patch fixes the issue with PAC confusion as well as fixes this issue with S4U2self created by the earlier KB5008380 patch.

Setting the Machine Account Quota to 0 is a quick and easy fix for stopping low privileged user from being able to create machine accounts, another related fix is to remove Authenticated Users from the SeMachineAccountPrivilege and adding Domain Admins or another group of allowed accounts.

There are several Events caused by various steps which would be useful for determining attempts to perform this attack. The credit for determining these Events should go entirely to Andrew Schwartz, I simply sent my logs to him after I performed the attack.

Machine Account Creation

Firstly, there is a 5156 event of an inbound connection to LDAP to create the machine account, For this event ID Andrew leveraged the research of “A Voyage to Uncovering Telemetry: Identifying RPC Telemetry for Detection Engineers” By: Jonathan Johnson:

Immediately followed by a 4673 event, which is the usage of the SeMachineAccountPrivilege:

As well as a 4741 event, describing the creation of the machine account:

And a 4724 event, regarding the password reset of the newly create machine account:

Clearing The SPNs

Next a 4742 event can be seen when the SPNs are removed from the machine account, this will show for the Service Principal Names field, as shown below:

Changing the SamAccountName

A 4742 event will also show when the SAM Account Name is changed, and the new name will be shown in the SAM Account Name field:

More interestingly, a 4781 event will show both the old account name and the new account name:

Get TGT

When retrieving the TGT, a 4768 event will show, interestingly the Account Name field will show the new name of the account, while the User ID field will show the old name:

Then the account name change happens again with the 2 events mentioned above.

S4U2self

Lastly, as Elad mentions in his Wagging the Dog post, event 4769 fires, this time, however, some discrepancy is shown between Account Name and Service Name, while the Service Name field has the proper machine account name, the Account Name is missing the trailing dollar ($):

Conclusion

With the November 9th updates, many changes were made to AD and I wouldn't be surprised if many other avenues existed using those issues but the one I use directly from a low privileged user to full domain takeover with a default configuration.

Ensuring all DC's are fully patched should be the main priority here as it will only take 1 unpatched DC for domain takeover to be possible.

On top of patching, proper AD hardening with decent monitoring will always minimise the impact of any compromise significantly.

More sAMAccountName Impersonation

By: 0xe7
11 December 2021 at 19:08

So in my excitement to put out the previous post I forgot something and since then I've thought of another attack path that may come in useful for some people.

For these examples I'm using the internal.user account in the internal.zeroday.lab domain, as shown below:

This is just a generic low privileged user.

Trusts

I did reply to my tweet afterwards, but I thought it'd be best to explain a little more that this works across trusts.

As mentioned in a previous post I did, creating machine accounts across trusts is not only possible but can be incredibly useful. This is another example of that.

A forest trust is configured between the internal.zeroday.lab and external.zeroday.lab forests:

A new machine account (named NewComputer) is created across this trust on the external.zeroday.lab domain:

The SPNs can be cleared from this newly created account:

It's best to get the distinguishedname of the machine account for changing the name:

Lastly, the name can be changed to the same as the domain controller minus the '$':

At this point the attack is exactly the same as the initial example I gave in the original post, ie. request a TGT for EDC1, rename machine account back, perform S4U2self.

User Account

Another example of exploitation involved user account control. 2 more prerequisites are required to perform the attack using a user account, The GenericAll privilege over the user account and access to the account credential. Any user account can be used to perform the attack.

There are several potential ways of obtaining the user account password when you have GenericAll over it, including tageted Kerberoasting from Will Schroeder, Shadow Credentials by Elad Shamir, just resetting the user password and probably more I'm forgetting right now. Point is, I'm not going to go into all of the potential ways you might do this, I'm just going to assume the password has been obtained.

So the user I'm running as (internal.user) has GenericAll over the target user (new.user):

Changing the samaccountname to that of the DC minus the '$' is also possible using PowerView:

The attack from this point is exactly the same as in the original post, I'm not going to duplicate all of that here, you can try it for yourself if you want. Interestingly on patched servers you can rename a user account this way with GenericAll over it, but the S4U2self part fails with KDC_ERR_TGT_REVOKED error due to the new Requestor PAC_INFO_BUFFER being included within the TGT's PAC.

EDIT: Charlie BROMBERG suggested GenericAll isn't actually required and this works with GenericWrite or even WriteProperty on sAMAccountName for changing the samaccountname, but it is important to remember that the ability to request a TGT for this account is required too, so the higher the privileges, the more likely you are to be able to do this.

Conclusion

It is very important that all domain controllers throughout the whole enterprise is patched against these issues due to the impact of exploitation and the ease with which it can be performed.

While more limited, it may still be possible in situations where a machine account cannot be created/controlled or renaming of machine account fails.

Defending the Three Headed Relay

By: 0xe7
9 May 2022 at 22:57

A joint blog written by Andrew Schwartz, Charlie Clark, and Jonny Johnson

Introduction

For the past couple of weeks it has become apparent that Kerberos Relaying has set off to be one of the hottest topics of discussion for the InfoSec community. Although this attack isn’t new and was discovered months ago by James Forshaw, it has recently taken off because a new tool called KrbRelayUp has come to surface that takes James’ work and automates that process for anyone wanting to exploit this activity. This tool however doesn’t only exploit James’ work, but also work from Elad Shamir around S4U2Self/S4U2Proxy, while using code from Rubeus by Will Schroeder. We as a group (Andrew, Charlie, and Jonny) found this interesting as we saw many detections coming out for “Kerberos Relay” that might not actually detect “Kerberos Relay” if the action was performed by itself, but more of post-exploitation actions — say in the S4U activity.

During this blog post we will take a look into Kerberos Relay, break out the different attack paths one could take, and talk about the different defensive opportunities tied to this activity and other activities leading up to Kerberos Relay or after.

Kerberos Relay Explained

Kerberos relaying was described in detail in James Forshaws blog post “Using Kerberos for Authentication Relay Attacks”. The primary focus of Kerberos relaying is to intercept an AP-REQ and relay it to the service specified within the service principal name (SPN) used to request the service ticket (ST). The biggest discovery within James’ research is that using certain protocols a victim client can be coerced to authenticate to an attacker using Kerberos while allowing an SPN to be specified that differs from the service that the client is connecting to. This means that the client will request a ST for an SPN of the attacker’s choosing, create an AP-REQ containing that ST and send it to the attacker. The attacker can then forward this AP-REQ to the target service, disregard the resulting AP-REP (unless the attacker needs to relay this back to the client for some reason) and at this point establish an authenticated session as the victim client.

While there are other potential ways Kerberos relaying can happen, (ie. like man-in-the-middle (MITM) attacks), the primary focus of this post will be on coercing a client to authenticate to the attacker as the method of receiving the AP-REQ. The process is essentially as follows:

Attacker coerces victim client auth with target service SPN -> client requests ST to SPN specified -> client sends AP-REQ to attacker -> attacker extracts AP-REQ sends to target service -> attacker establishes session as victim client

There are some caveat’s to this process. The first being protections enabled on the target service. As with NTLM relaying, if the target service has signing/sealing or channel binding enforced, relaying Kerberos authentication will not work. The second caveat is the protections supported by the client. With some target protocols, if the client indicates support for certain protections, the server will enable those protections, again making Kerberos relaying not possible without some other bug in the implementation.

Potential Attack Paths with Kerberos Relay

There are several potential attack paths that Kerberos relaying allows for. Many of these were documented by James in his initial blog post. As alluded to previously, there are 2 main considerations when discussing Kerberos relaying attack paths:

  1. The protocol used to trigger the authentication from the victim client
  2. The protocol used by the service the authentication is being relayed to

Trigger Protocol

As discussed, the main requirement for the trigger protocol is the ability for the attacker to specify an arbitrary SPN, or at least a partially attacker controlled SPN, when triggering the authentication. Protocols known to potentially have this requirement are:

  • IPSec and AuthIP
  • MSRPC
  • DCOM
  • HTTP
  • LLMNR
  • MDNS

Service Protocol

Depending on the protections enabled on the server, the following protocols are known to be target service protocols for Kerberos relaying:

  • LDAP/LDAPS
  • HTTP
  • SMB

Potentially many combinations of these protocols could be used as attack paths for Kerberos relaying. This presents many attack paths, for instance, relaying to an LDAP server could allow for modification of LDAP objects or relaying to an AD CS HTTP web enrolment endpoint could allow for requesting an authentication certificate.

Detecting Kerberos Relay

Before diving straight into detections, queries, and indicators of activity for these behaviors we think it is important to touch on what we are looking at for detection and why. It is fairly easy to take a tool that performs some behavior then immediately go look at the logs to see what telemetry exists. This isn’t a terrible approach, it just isn’t the only one and not the one we take.

We (Charlie, Andrew, and Jonny) like to approach this detection piece a little differently by breaking up a tool’s capability, understanding what it is trying to accomplish, understanding the technologies tied to an attack and their capabilities, and identifying what actions (if any) apply to other techniques. We then like to find the core behavior the attack is built on and identify what pieces of that action is or can be controlled by an attacker. This process helps us identify which behaviors are explicitly tied to the attack and which might relate to an action that was performed prior to the attack or after. One thing we don’t want to do is create detection explicitly tied to the tool, but to the attack. We are using the tool as a starting point of understanding the attack and the various variants an attacker may take to accomplish these actions.

That being said, every attack will have a pre, intra, and post action. These actions are extracted during the research process and help us scope what capabilities we are trying to detect. Let us explain.

In order for an attack to be run, an attacker must do something that gives them the ability to perform that action. This could be a number of things, let’s use the following as an example of pre-action activity:

  • Gain access to a domain user
  • Compromise/obtain a foothold on a box
  • Run a LDAP query for reconnaissance
  • Escalate to a local administrator/High IL

You then have the actual attack (intra-action):

  • Kerberoast
  • Dump LSASS
  • Access Token Impersonation

Finally, the attacker is going to do something with whatever output the attack gives them — being the post-action:

  • Logs on as user
  • Impersonates user

Here is a visual representation of this:

This allows us to apply a detection layering approach when creating detections for these behaviors because there is going to be something within the pre-action that we can relate to the intra-action, and similarly the intra-action to the post-action. Due to this we can change the diagram up a little bit:

As you can probably tell by now, every post-action leads into a pre-action. It restarts the attack flow. We see this below with Kerberos Relay. One potential post-action is to perform S4U2Self/S4U2Proxy. Kerberos Relay has now become a pre-action to this activity and a post-action could be that an attacker is using that ability to login, talk to the SCM to create a service and run a process as SYSTEM.

If we just run the attack and look directly at the logs it is easy to start making assumptions. So before we run the attack we can break out what we are looking for, then go look for it. This allows us to truly understand what layer we are applying a detection, which inherently will help us understand what level of coverage we have.

We can now apply this to Kerberos Relay in the next section.

Detection Queries

Some of the attacks within the pre/intra/post actions were applied due to how KrbRelayUp was exploiting this activity. The attacker doesn’t always have to take these exact paths and some of the specifics may change, for example — below we show a detection for the COM server initialization/TCP connection. An attacker could use a different protocol like HTTP/LDAP. Although we didn’t create queries for each one of these scenarios we wanted to share the different pre/intra/post-action detections someone could create.

Pre-Kerberos Relay Detections:

  • Initial domain user foothold (No detection added as there are so many options)
  • LDAP queries to identify potential SPNs available
  • Computer account added via LDAP (Using Microsoft Defender for Endpoint DeviceEvents)
1
2
3
4
5
DeviceEvents
| where ActionType containsLdapSearchand (InitiatingProcessParentFileName !has (“services.exe”) or InitiatingProcessAccountName !in (“local service”, “system”))
| extend SearchFilter= extractjson(“$.SearchFilter”, AdditionalFields)
| where SearchFilter containssAMAccountNameand SearchFilter contains “$”
| summarize count() by Timestamp, InitiatingProcessAccountName,InitiatingProcessParentFileName, InitiatingProcessFileName, SearchFilter, InitiatingProcessCommandLine, AdditionalFields, InitiatingProcessLogonId

Note: This query was created via MDE and will look for when a computer account is created via LDAP, for this attack this is totally optional. To perform this specific attack path, the attacker only requires the credentials of any computer object or a user object with an SPN. There are many other ways to potentially obtain one.

  • Computer Account added via Splunk and Window Security Event ID 4741:
1
index=windows sourcetype=Security EventCode=4741 AND SAM_Account_Name = “*$”

Going a step further would be to correlate the 4741 with Windows Security Event ID 4673. As Andrew wrote in his post the event details in 4673 contain the four (4) SPN’s that are also created when a computer account is created with certain attack tools (in their present state as of writing this post). Kevin Robertson first blogged about the 4 SPN’s being generated in his post, “MachineAccountQuota is USEFUL Sometimes: Exploiting One of Active Directory’s Oddest Settings.” Many publicly available Open Source Tools (OSTs) incorporate the same 4 SPNs into their tooling.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
index=windows (EventCode=4741 MSADChangedAttributes=*(*HOST/*) AND *(*RestrictedKrbHost/*) New_UAC_Value=0x80) OR (EventCode=4673 Privileges=SeMachineAccountPrivilege) 
| eventstats values(Process_Name),values(Privileges),values(EventCode) as EventCode by Logon_ID 
| search EventCode=4741
| rex field=_raw “(Message=(?<Message>[a-zA-z ].*))” 
| eval datetime=strftime(_time, “%m-%d-%Y %H:%M:%S.%Q”) 
| stats count values(datetime),values(Process_Name),values(Privileges),values(EventCode),values(MSADChangedAttributes),values(Message),values(Account_Domain),values(Security_ID),values(SAM_Account_Name),values(DNS_Host_Name) by Logon_ID 
| search count >=2 
| rename values(*) as * 
| eval Effecting_Account=mvindex(Security_ID,1) 
| eval New_Computer_Account_Name=mvindex(Security_ID,0) 
| table datetime,Account_Domain,Effecting_Account,Logon_ID,New_Computer_Account_Name,DNS_Host_Name,Message,MSADChangedAttributes,Process_Name,Privileges,EventCode

Intra-Kerberos Relay Detections:

  • DCOM Server connection with TCP connection to localhost (Using Splunk and Window Security Event ID 5156):
1
index=windows sourcetype=Security EventCode=5156 Direction=Inbound AND Source_Address=::1 AND Destination_Address=::1 AND Process_ID !=4 AND Protocol=6

Post-Kerberos Relay Detections:

  • RBCD Exploitation (Using Splunk and Window Security Event ID 5136/4768/4769)
1
2
3
4
5
6
7
8
index=windows sourcetype=”Security” ((EventCode=5136 AND “msDS-AllowedToActOnBehalfOfOtherIdentity”) AND (Type=”Value Added” OR Type=”Value Deleted”)) OR EventCode=4768 OR EventCode=4769 
| eval alt_type=mvindex(Type,2) 
| eval datetime=strftime(_time, “%m-%d-%Y %H:%M:%S.%Q”) 
| bucket _time span=11m
| stats dc(EventCode) as eventcodes,values(EventCode),values(datetime),values(LDAP_Display_Name),values(host),values(Account_Domain),values(Client_Address),values(Service_Name),values(Service_ID),values(Ticket_Options),values(Class),values(Ticket_Encryption_Type),values(alt_type) by _time 
| rename values(*) as *
| where eventcodes >=3
| table _time,datetime,host,Account_Domain,Client_Address,Service_Name,Service_ID,Ticket_Options,Ticket_Encryption_Type,Class,LDAP_Display_Name,alt_type,EventCode,eventcodes

It should be noted that this detection query has limitations given its use of bucket _time span. We employed the use of this time feature as there was not an easy way (i.e. by Logon ID) to correlate the three events. The only common variable we discovered between these three different events observed was time, specifically all within a 15 second window. While this query worked in our lab with our specific dataset, we would like to point out that by grouping the events by time in a bucket, events can possibly occur outside the span of the bucket as we don’t know WHEN the event will take place. As such the event could occur in the middle of the bucket or it could be on the “edge.” A thank you to Greg Rivas for helping create the above SPL query.

During the writing of this post the author of KrbRelayUp added support for Shadow Credentials, which performs slightly different post-actions than we have specified above. However; it is good to note that Shadow Credentials is still a post-action potential attack that can be leveraged.

Mitigations

  1. Limit MAQ attribute and/or restrict the SeMachineAccountPrivilege to a specific group rather than Authenticated Users
  2. Extended Protection for Authentication (EPA)/Protocol Signing/Sealing and Channel Binding
  3. Disabling mDNS/LLMNR
  4. Require authenticated IPsec/IKEv2
  5. Disabling Disable NTLM

A thank you to James Forshaw for vocalizing some of these mitigations when introducing this attack.

Conclusion

During this write-up we wanted to give a brief explanation of Kerberos Relay, how this can be exploited, and the various levels of detection/prevention that could be applied. Although we didn’t go over every pre/post-exploitation scenario an attacker could take, we wanted to highlight the importance of thinking about attacks from a pre/intra/post-action perspective. This helps us identify the scope of our detections, which will then allow us to identify at what depth we are applying the detection.

We hope this was helpful and a huge thank you to James Forshaw again for his previous work on this.

References

  • https://googleprojectzero.blogspot.com/2021/10/using-kerberos-for-authentication-relay.html
  • https://googleprojectzero.blogspot.com/2021/10/windows-exploitation-tricks-relaying.html
  • https://dirkjanm.io/relaying-kerberos-over-dns-with-krbrelayx-and-mitm6/
  • https://github.com/Dec0ne/KrbRelayUp
  • https://github.com/cube0x0/KrbRelay

dnscat(how)2

13 May 2022 at 22:00
Quick primer on how to setup and use dnscat2 - dnscat2 uses a client server architecture to tunnel traffic via UDP and/or DNS queries. It can be used to bypass firewalls and execute commands on the machine running the client. It can also be used to to tunnel traffic from the server to the internal network of the client through...

What does a cybersecurity beginner do? | Cybersecurity Career Series

By: Infosec
16 May 2022 at 07:00

Just getting started?  This role is for you!

The Cybersecurity Beginner role focuses on the foundational skills and knowledge that will allow anyone to take the first step towards transitioning into a cybersecurity career.  No prior knowledge of cybersecurity or work experience is required. The only prerequisite is a passion for technology and cybersecurity.

– Free cybersecurity training resources: https://www.infosecinstitute.com/free
– Learn more about the role here: https://www.infosecinstitute.com/role-cybersecurity-beginner/

0:00 - Working as a cybersecurity beginner
0:41 - Tasks a cybersecurity beginner may take on
4:15 - Cybersecurity work imposter syndrome
5:49 - Common tools cybersecurity beginners use
9:08 - Jobs for cybersecurity beginners
13:50 - Get started in cybersecurity 

About Infosec
Infosec believes knowledge is power when fighting cybercrime. We help IT and security professionals advance their careers with skills development and certifications while empowering all employees with security awareness and privacy training to stay cyber-safe at work and home. It’s our mission to equip all organizations and individuals with the know-how and confidence to outsmart cybercrime. Learn more at infosecinstitute.com.

💾

Working as a privacy manager | Cybersecurity Career Series

By: Infosec
23 May 2022 at 07:00

A Privacy Manager is responsible for the development, creation, maintenance and enforcement of the privacy policies and procedures of an organization. They ensure compliance with all privacy-related laws and regulations. The Privacy Manager takes an active lead role when a privacy incident or data breach occurs and will start the investigation. They will then monitor, track and resolve any privacy issues. The Privacy Manager builds a strategic and comprehensive privacy program for their organization that minimizes risk and ensures the confidentiality of protected information.

Advanced knowledge of privacy law and data protection is critical to success in this role.

– Free cybersecurity training resources: https://www.infosecinstitute.com/free
- Learn more about privacy managers: https://www.infosecinstitute.com/role-privacy-manager/

0:00 - Working as a privacy manager
0:40 - What does a privacy manager do? 
3:02 - Experience a privacy manager needs
5:15 - Is college necessary for a privacy manager?
8:05 - Skills needed to be a privacy manager
10:30 - What tools does a privacy manager use?
11:15 - Where do privacy managers work? 
12:15 - Roles privacy managers can move to
13:30 - How do I get started becoming a privacy manager?

About Infosec
Infosec believes knowledge is power when fighting cybercrime. We help IT and security professionals advance their careers with skills development and certifications while empowering all employees with security awareness and privacy training to stay cyber-safe at work and home. It’s our mission to equip all organizations and individuals with the know-how and confidence to outsmart cybercrime. Learn more at infosecinstitute.com.

💾

EDR Bypass : How and Why to Unhook the Import Address Table

By: Author
27 May 2022 at 09:33
One day, I was trying to bypass an EDR and I noticed something interesting. The EDR I was trying to bypass wasn’t hooking the DLL in their code with jmp instruction like other EDRs in user-land. In this case, it was hooking directly the Import Address Table. This technique makes the usual move like live-patching, or erasing the loaded DLL with one freshly loaded from disk useless. I had to unhook the Import Address Table of my process.

Ethical user data collection and machine learning | Guest Ché Wijesinghe

By: Infosec
6 June 2022 at 07:00

Today on Cyber Work Ché Wijesinghe of Cape Privacy talks about the safe and ethical collection of user data when creating machine learning or predictive models. When your bank is weighing whether to give you a loan, they can make a better choice the more info they know about you. But how secure is that contextual data? Hint: not as secure as Wijesinghe would like!

– Start learning cybersecurity for free: https://www.infosecinstitute.com/free
– View Cyber Work Podcast transcripts and additional episodes: https://www.infosecinstitute.com/podcast

0:00 - Machine learning and data collection
2:37 - Getting started in cybersecurity
3:15 - Being drawn to big data
4:35 - What data is driving decision-making?
9:04 - How is data collection regulated?
15:02 - Closing the encryption gap
16:50 - Careers in data privacy
19:07 - Where can you move from data privacy?
21:20 - Ethics of data collection 
23:25 - Learn more about Wijesinghe 
23:55 - Outro

About Infosec
Infosec believes knowledge is power when fighting cybercrime. We help IT and security professionals advance their careers with skills development and certifications while empowering all employees with security awareness and privacy training to stay cyber-safe at work and home. It’s our mission to equip all organizations and individuals with the know-how and confidence to outsmart cybercrime. Learn more at infosecinstitute.com.

💾

Avoiding B.A.D. behaviour

11 June 2022 at 22:00
The difficult relationship between nihilism, cybersecurity professionals and Being-A-Dick behaviour - Disclaimer: if you are looking for a strictly technical article, the ones I usually write, you will be disappointed. This blogpost is mainly my two cents on the way we, cybersecurity professionals, usually deal with situations, organizations and people, both techies and non-techies. Introduction A few days ago, I was...

Cybersecurity jobs: How to better apply, get hired and fill open roles | Guest Diana Kelley

By: Infosec
13 June 2022 at 07:00

Diana Kelley returns to the show to discuss her work as a board member of the Cyber Future Foundation and the goings-on at this year’s Cyber Talent Week. Whether you’re a cybersecurity hiring manager who doesn’t know why you’re not getting the applicants you want, a candidate who hears the profession has 0% unemployment but still can’t seem to get a callback or anyone in between, DO. NOT. MISS. THIS. EPISODE. This is one for the books, folks.

– Start learning cybersecurity for free: https://www.infosecinstitute.com/free
– View Cyber Work Podcast transcripts and additional episodes: https://www.infosecinstitute.com/podcast

0:00 - Cybersecurity hiring and job searching
4:30 - Diana Kelley of Cyber Future Foundation
9:00 - Cyber Future Foundation talent week
13:58 - Reexamining cybersecurity job descriptions 
21:52 - Cybersecurity hiring manager and applicant training
27:10 - Strategies to bring in diverse talent from other industries
33:06 - Narrowing your cybersecurity job pursuit
39:37 - Using different educations in cybersecurity roles
41:32 - Implementing an educational pipeline
44:40 - Hiring based on strong skills from other trades
48:22 - Cybersecurity apprenticeships 
53:22 - Fostering cybersecurity community value 
59:09 - Diana Kelley's future projects
1:00:30 - Outro

💾

Intigriti XSS Challenge – December 2021

27 December 2021 at 14:33
The approach to this challenge was completely different from the past two months, as the vulnerable component was on the backend, forcing us to approach it as a black box scenario. The page presents a simple submittable get form providing the open and payload parameters. To reach that from the UI, a user has to […]

KRWX: Kernel Read Write Execute

12 March 2022 at 15:41
Introduction Github project: https://github.com/kiks7/KRWX During the last few months/year I was studying and approaching the Kernel Exploitation subject and during this journey I developed few tools that assissted me (and currently assist) on better understanding specific topics. Today I want to release my favourine one: KRWX (Kernel Read Write Execute). It is a simple LKM […]

Linux Kernel Exploit Development: 1day case study

13 June 2022 at 10:01
Introduction I was searching for a vulnerability that permitted me to practise what I’ve learned in the last period on Linux Kernel Exploitation with a “real-life” scenario. Since I had a week to dedicate my time in Hacktive Security to deepen a specific argument, I decided to search for a public vulnerability without a public […]

What does a secure coder do? | Cybersecurity Career Series

By: Infosec
20 June 2022 at 07:00

Secure coders are responsible for developing and writing secure code in a way that protects against security vulnerabilities like bugs, defects and logic flaws. They take proactive steps to introduce secure coding methodologies before the application or software is introduced into a production environment, often following recommendations from the Open Web Application Security Project (OWASP) Foundation.

– Free cybersecurity training resources: https://www.infosecinstitute.com/free
– Learn more here: https://www.infosecinstitute.com/skills/train-for-your-role/secure-coder/

0:00 - Intro
0:25 - What does a secure coder do?
5:48 - How do you become a secure coder?
9:46 - What skills do secure coders need?
12:28 - What tools do secure coders use?
17:08 - What roles can secure coders transition into?
19:50 - What to do right now to become a secure coder

About Infosec
Infosec believes knowledge is power when fighting cybercrime. We help IT and security professionals advance their careers with skills development and certifications while empowering all employees with security awareness and privacy training to stay cyber-safe at work and home. It’s our mission to equip all organizations and individuals with the know-how and confidence to outsmart cybercrime. Learn more at infosecinstitute.com.

💾

Cybersecurity has a marketing problem — and we're going to fix it | Guest Alyssa Miller

By: Infosec
27 June 2022 at 07:00

On today's episode, we're breaking down phrases you've heard a million times: “security is everyone’s job,” “humans are the weakest link in the security chain,” “it’s not if you get breached, but when.” Returning guest Alyssa Miller drills into these comforting nostrums and explains why, even when they’re used for well-intended purposes, they often act to limit the conversation and the options, rather than address the hard work needed to overcome these evergreen problems. You’re not going to want to miss this one, folks! It’s all that, plus a little bit of book talk, today on Cyber Work!

– Start learning cybersecurity for free: https://www.infosecinstitute.com/free
– View Cyber Work Podcast transcripts and additional episodes: https://www.infosecinstitute.com/podcast
– Get the Cybersecurity Career Guide by Alyssa Miller: https://alyssa.link/book

0:00 - Intro
1:38 - Alyssa's tweet that inspired this episode
4:00 - Why you need to read the Cybersecurity Career Guide
9:10 - Cybersecurity platitudes and clichés
11:30 - Cliché 1: "It's not if you get breached, but when"
18:44 - Cliché 2:"Just patch your shit"
24:58 - Cliché 3: "Users are the weakest link"
32:34 - Cliché 4: "Security is everyone's job"
35:52 - Cliché 5: What is a "quality gate"?
44:14 - Cliché 6: "You just need passion to get hired"
48:14 - How to write a better cybersecurity job description 
50:15 - Business value of diversity and inclusion
52:52 - Building a security champions program
55:12 - Where can you connect with Alyssa Miller?
56:44 - Outro

About Infosec
Infosec believes knowledge is power when fighting cybercrime. We help IT and security professionals advance their careers with skills development and certifications while empowering all employees with security awareness and privacy training to stay cyber-safe at work and home. It’s our mission to equip all organizations and individuals with the know-how and confidence to outsmart cybercrime. Learn more at infosecinstitute.com.

💾

Malware Analysis: Ragnarok Ransomware

By: Ylabs
29 April 2021 at 15:30
Reading Time: 11 minutes The analysed sample is a malware employed by the Threat Actor known as Ragnarok. The ransomware is responsible for files’ encryption and it is typically executed, by the actors themselves, on the compromised machines. The name of the analysed executable is xs_high.exe, but others have been found used by the same ransomware family (such as […]

Chaining Bugs: NVIDIA GeForce Experience (GFE) Command Execution

By: Ylabs
13 May 2021 at 15:30
Reading Time: 5 minutes NVIDIA GeForce Experience (GFE) v.<= 3.21 is affected by an Arbitrary File Write vulnerability in the GameStream/ShadowPlay plugins, where log files are created using NT AUTHORITY\SYSTEM level permissions, which lead to Command Execution and Elevation of Privileges (EoP). NVIDIA Security Bulletin – April 2021 NVIDIA Acknowledgements Page Introduction Some time ago I was looking for […]

Reverse Engineering & Exploiting Dell CVE-2021-21551

By: Ylabs
20 May 2021 at 15:30
Reading Time: 11 minutes At the beginning of the month, Sentinel One disclosed five high severity vulnerabilities in Dell’s firmware update driver.As the described vulnerability appeared not too complicated to exploit, a lot of fellow security researchers started weaponizing it. I was one of, if not the first tweeting about weaponizing it into a _SEP_TOKEN_PRIVILEGES overwrite exploit, and with […]

Root Cause Analysis of a Printer’s Driver Vulnerability

By: Ylabs
29 July 2021 at 15:30
Reading Time: 8 minutes Last week SentinelOne disclosed a "high severity" flaw in HP, Samsung, and Xerox printer's drivers (CVE-2021-3438); the blog post highlighted a vulnerable strncpy operation with a user-controllable size parameter but it did not explain the reverse engineering nor the exploitation phase of the issue. With this blog post, I would like to analyse the vulnerability […]

Homemade Fuzzing Platform Recipe

By: Ylabs
26 August 2021 at 15:30
Reading Time: 5 minutes It’s no secret that, since the beginning of the year, I’ve spent a good amount of time learning how to fuzz different Windows software, triaging crashes, filling CVE forms, writing harnesses and custom tools to aid in the process.Today I would like to sneak peek into my high-level process of designing a Homemade Fuzzing Platform, […]

Crucial’s MOD Utility LPE – CVE-2021-41285

By: Ylabs
30 September 2021 at 15:30
Reading Time: 7 minutes Crucial Ballistix MOD Utility is a software product that can be used to customize and control gaming systems, specifically LED colours and patterns, memory, temperature, and overclock.During my vulnerability research, I’ve discovered that this software utilizes a driver, MODAPI.sys, containing multiple vulnerabilities and allowing an attacker to achieve local privilege escalation from a low privileged […]

Driver Buddy Reloaded

By: Ylabs
28 October 2021 at 15:30
Reading Time: 5 minutes As part of Yarix's continuous security research journey, during this year I’ve spent a good amount of time reverse-engineering Windows drivers and exploiting kernel-mode related vulnerabilities. While in the past there were (as far as I know), at least two good IDA plugins aiding in the reverse engineering process: DriverBuddy of NCC Group. win_driver_plugin of […]

Merry Hackmas: multiple vulnerabilities in MSI’s products

By: Ylabs
16 December 2021 at 16:30
Reading Time: 2 minutes This blog post serves as an advisory for a couple MSI’s products that are affected by multiple high-severity vulnerabilities in the driver components they are shipped with. All the vulnerabilities are triggered by sending specific IOCTL requests and will allow to: Directly interact with physical memory via the MmMapIoSpace function call, mapping physical memory into […]
❌
❌