Thursday, May 3, 2018

Silently turn off Active Directory Auditing using DCShadow

My fascination with DCShadow continues, thanks to Vincent and Benjamin. I blogged about it previously as well.

One very interesting thing which I recently discovered is the ability to DCShadow to modify System Access Control List or SACL. When we enable auditing on success or failure on an AD object, an entry (called ACE - Access Control Entry) is added to the SACL of that object. The permissions to an object are controlled by a DACL. For example, we modified DACL of AdminSDHolder in the previous post for persistence.

The Problem

So, SACL controls auditing (logging) for an AD object. This means if we would like to avoid logs for our activities during an assessment , we should turn it off at the very first chance. Right? But is it that easy?

Let's assume that full auditing is turned on the AdminSDHolder container and even a read operation is logged. This is what the SACL looks like:
The SACL governs logging of stuff. For example, with the above auditing settings, if we add Full Control rights for a user to the AdminSDHolder for persistence, an Event ID 4662 is logged:
Now, we would like to turn auditing off for the AdminSDHolder object so that the above logs are avoided. Right? Right? ;)

This can be done by removing the ACEs. But it is not as silent as we would like it to be. Removing ACEs results in more 4662s:
In case we were targeting a user object and remove auditing for it, a 4738 (User Account Management) in addition to multiple 4662s is logged.

The Solution

Now, how does DCShadow help? Try the below commands to set ACL of the AdminSDHolder to turn off the enhanced auditing:
Bingo! No logs for turning off logging. Of course, I cannot show you no logs :P But we can see the new SACL:
Please note that we will still have logs related to DCShadow (4742 for the Computer registered as DC and 4662 for the domain object) but nothing else.

Note that the auditing entry in the above is S:PAI(AU;CIFA;DT;;;WD)

What does that mean?
PAI -  Inheritance from higher up objects is blocked
AU - System Audit
CI - Container Inherit - The child objects inherit this.
FA - Audit Failure
DT - Delete Tree - No specific reason for using this other than chances of this being logged are low.
WD - Everyone
If you are not familiar with SDDL, go through these Technet posts to begin: The Security Descriptor Definition Language of Love (Part 1) and Part 2.

So why the above entry? No special reason. I thought, it would be better to leave an entry than removing all of it. If you want an ineffective SACL use just S:PAI. This is how it looks in the GUI:
You can use the below code for reading existing ACLs for an object. To easily get the desired ACE, set it up using GUI and then read the entries using the below code:

Further Research

This is sweet but there are so many chances of further research on this. Like, there is still a single 4662 logged when mimkatz does "Attributes Checking" before we push the attributes. I read the source code of mimikatz and tried to avoid that read, but no success.

Also, I cannot find a way to turn off default SACL for the domain object. In theory, this should be easily doable with similar commands we used above!

Also, there are detections based on absence of logs as well. Unless we go for minimal modification to auditing we will still be detected.

Hope you liked the post :)

Friday, April 6, 2018

DCShadow - Minimal permissions, Active Directory Deception, Shadowception and more

DCShadow is an awesome persistence technique introduced by Vincent and Benjamin at BluteHat IL and it can be executed with the help of mimikatz. 

In very simplified terms, DCShadow alters active directory schema (Configuration partition and SPN of the attacker machine) to mimic a domain controller. This "new" domain controller can then be used to push attributes (like SID History, Password History, SPNs etc.) and other data on domain objects for users, computers etc. Please visit and above linked preso for more details. There are couple more interesting posts at ALSID blog and NOPSEC blog which are very useful in understanding DCShadow.

In this blog post, I make notes of some of the use cases of DCShadow and couple of experiments I did while using it. Please keep in mind that I am still playing with this technique :)

Executing DCShadow

Grab the latest build of mimikatz from its GitHub repo or Invoke-Mimikatz from Nishang. The attack must be executed from a domain joined machine and needs SYSTEM privileges on the machine and by-default, domain administrator (DA) privileges on the domain.

Please keep in mind that the SYSTEM requirement is for process context and not thread. I learnt this the hard way but thankfully, a very patient Vincent and the source code helped me out :)

So, here is how to use it:
1. Start mimikatz and use !processtoken (and not token::elevate - as it elevates a thread) to escalate to SYSTEM. Make sure to use !processtoken before opening another instance of mimikatz, This is the mimikatz instance where we will specify the target object and attributes to be modified.
2. Start another mimikatz with DA privileges. This is the instance which registers a DC and is used to "push" the attributes. 
We are now ready to use dcshadow. For example, use the below command from mimikatz running as SYSTEM to change userAccountControl value of a computer object. Mimikatz makes checks for validity of object and attributes which is awesome!
To push the above attributes, run the below command from mimikatz running as DA.
On the other mimikatz session, we can see the values are updated and RPC server is stopped.
Let's check the userAccountControl attribute of the computer object we modified.
Works like a charm with Invoke-Mimikatz as well.
Please keep in mind that even on a local machine with interactive access, Invoke-Mimikatz does not show the message of "RPC server started" until the push command is executed, probably because of output redirection issues.

DCShadow for Red Teams

Minimal permissions
DCShadow provides amazing persistence opportunities. Many well known ones as well as some new stuff, can be executed with it without leaving logs on the DC. While learning about it, I started wondering if there is a way to use DCShadow without DA privileges? Like most domain persistence methods, we do not need DA privileges all the time for DCShadow but only for setting it up. For using it later on, only a subset of permissions are required.

After spending much time reading MS documentations on MS-DRSR and MS-RPCE to understand the errors shown by mimikatz when not using DA and experimenting with permissions, I was able to segregate the permissions required for running DCShadow without having DA privileges!

What does that mean? That means, you need DA privileges just once to set up the required minimal permissions for user of your choice. That user can successfully run DCShadow against a specific object later on. What are the rights required?

Following (extended rights) for the domain object:
- DS-Install-Replica (Add/Remove Replica in Domain)
- DS-Replication-Manage-Topology (Manage Replication Topology)
- DS-Replication-Synchronize (Replication Synchornization)
We also need WriteProperty right on the computer object of machine which is used for attack (gets registered as a DC) to modify SPNs and the target object to modify attributes.
Lastly, CreateChild and DeleteChild permissions are required on the Sites object (and child objects) in the Configuration container to register and un-register a DC.
To automate modification of the objects, I give you Set-DCShadowPermissions.ps1 in Nishang, a PowerShell script which sets minimal permissions for executing DCShadow attack! Use the below command with DA privileges to set permissions for user "labuser" to modify permissions on computer object ops-user19 from the computer ops-user12. 
Now, the mimikatz command can be executed without DA privileges. Please note that the command output is same as when using DA (see the screenshots in the beginning of the post).
Neat isn't it! Append the -Remove parameter at the end of the above command for cleanup.

Note that logs (4662 for changes made to ACL of the domain object, 4742 for changes made to ACL of attacker's computer object and 4738 if the target is a user object)  are generated when you modify ACLs using Set-DCShadowPermissions but so is true for other methods required to persist with high privileges.

Once we have the permissions (or DA), we can use DCShadow for tons of interesting things. Let's have a look at some of them. Please note that I am going to use all of them without DA by modifying permissions using Set-DCShadowPermissions:

Very useful, also mentioned in the DCShadow presentation. Set the SIDHistory of an account to a high privilege one like DA or EA group and we are all set for highest privileges without having to modify any Group Membership or ACL.
This too is from the preso. Change the primaryGroupID of an object to a high privileged one for higher privileges.
There is a catch though, if this is used to change primaryGroupID of a user to a privileged group, that user may show up in listing of that group which is not really stealthy. Note that this listing in the group depends on the tool used for enumeration. For example, in the below screenshot, the user "helpdeskuser" shows up as a member of "Enterprise Admins" group when using net.exe (or Get-ADGroupMember from the activedirectory module) but not when using PowerView ;)
Like the simpler attributes we modified above, it is possible to modify ACLs on objects using DCShadow by modifying the ntSecurityDescriptor attribute. This ability allows even more interesting stuff. For example, modifying AdminSDHolder ACL for persistence.

To use this, we need to read the existing SDDL on the AdminSDHolder container and add permissions for our user's SID. Quite similar to what I used in Set-RemoteWMI
To add Full Control permission we can use permissions of the BA, DA or EA (highlighted in the above screenshot) and append our user's SID. The resulting below string needs to be added to the SDDL of AdminSDHolder.
Use the below mimkatz command for DCShadow. Make sure you use the colon ":" for specifying values to parameters:

DCShadow using DCShadow - Shadowception

Similar to above, we can also push DCShadow permissions using DCShadow.I call it Shadowception Why? Because it is fun :P We just need to push permissions listed above while introducing Set-DCShadowPermissions. The permissions required are:
Use the below mimikatz commands to set DCShadow permissions which can be used only from a particular computer as a specific user against a specific object - all of them specified in the commands. Please do not get intimidated with long commands, I have used exactly the same method as for AdminSDHolder - Copy the existing SDDL and append your own.
This is sweet! Now, if we maintain access to the computer and the user specified above, it is possible to modify the attributes of the specified object without leaving logs.

Setting SPNs on Admin Accounts for Kerberoasting
As explained by Sean here, in this technique we force set SPNs for admin accounts for later Kerberoasting. Kerberoasting, those of you who are unaware, is an attack technique where TGS (Ticket Granting Service) is requested for a SPN, saved to the disk and then brute-forced offline for password of the target SPNs service account. Thus if we can set SPN for a privileged account, it is possible to brute-force its password in clear-text using kerberoasting. To set SPNs for privileged account, we need high privileges, hence this is a persistence technique. Below command can be used to set SPN of a DA account using DCShadow:
In addition to the above discussed, you can find your own attack. For example, I have not discussed setting TrustedForDelegation and TrustedToAuthForDelegation :) Go through the list of All AD attributes and find more interesting ones -

For defense, see and UnCoverDCShadow. And limit the number of DAs and usage of DA credentials across your enterprise ;) A very good reference is Securing Privileged Access Reference Material.


DCShadow for Blue Team Deception

For past couple of months, I have been working a lot on using Deception for defense. I am liking Active Directory Deception because of its efficacy in providing alerts and increasing (at least) time costs to an adversary. While I will leave the details for another post and/or talk, one thing difficult for me when forging objects which are interesting for an attacker is editing some of the attributes of an object. For example, it is not easy to forge a computer object to make it look like a DC object. Multiple attributes and services must be set before a computer object "appears" to be a DC. There are some workarounds but that calls for another post or as I said a talk. So, DCShadow helps with forging a domain controller which looks more real. Of course, there is a lot of scope for improvement but I really like how it open up opportunities for blue teams.

A quick example is this. Suppose we want to make a member computer object "ops-user12" a DC. We can use the following (make sure you either have DA privs or set permission using Set-DCShadow permissions):
Push the above
Push the above
Use the above from mimikatz instance running as DA or modified permissions. Now, if an adversary enumerates your domain, this is what it looks like:
And this holds true for most of the red team tools (like PowerView which uses the .NET class in above screenshot) and even most of the WMI classes for domain enumeration like Win32_NTDomain and ds_computer of the directory\ldap namespace.
But this is still very experimental. We can easily note missing attributes from the fake DC, although that can be set. The thing which concerns me right now is if this breaks any authentication requests or other legit functioality. Because when using the "push" option of DCShadow, the registration and unregistration takes place quickly but when we are doing it manually what if some legit authentication requests are directed to the fake DC? I am hoping to find an answer of that soon.

I wish this use of DCShadow for deception triggers a community effort on using AD objects for deception :)

Some of the problems you may face while using DCShadow:

Insufficient Privileges
ERROR kuhl_m_lsadump_dcshadow_force_sync_partition ; IDL_DRSReplicaAdd
DC=whatever,DC=com 0x80090322 (2148074274)

If you get an error like above, make sure that mimkatz is running as SYSTEM (use !processtoken). Please refer to Executing DCShadow section above. 

Permission Errors
If you see an error during registration like  "Unable to add object via ldap". Then make sure that  you are "pushing" with DA privileges from mimikatz or you have set proper permissions. 

In some cases, when unregistration fails (see the video!), you may have to cleanup the object created in the CN=Servers in the Configuration Container and/or SPNs of the computer object which is registered as Fake DC. To clear SPNs I am using this simple command from the activedirectorymodule.
Here is a video showing the above attacks and deception.

Hope you enjoyed the post!

Sunday, January 14, 2018

A Critique of Logging Capabilities in PowerShell v6

PowerShell 6 was released couple of days back. PowerShell v6 is the core version, that is, it is open source, cross platform and it is NOT Windows PowerShell which continues to be the default one on Windows. As per this blog by PowerShell Team, going forward, PowerShell core is the future (Windows PowerShell will still get critical bug-fixes.)
PowerShell Team, over past 2-3 years, has constantly improved the security controls in PowerShell. The defining moment was, of course, PowerShell ♥ the Blue Team where the PowerShell Team detailed many interesting features like System-wide Transcription, Deep Script Block Logging, AntiMalware Scan Interface, Protected Event Logging, Constrained Language Mode (with Applocker "Allow" mode) etc. Comparing PowerShell v2 - which comes installed by default in Windows 7 - with PowerShell 5.1 which is the default for Windows 10, the effort to restrict, track and log PowerShell usage on a box is clearly visible and effective.

Having used PowerShell for 7+ years for red team assessments and penetration tests, I look forward to every major release of PowerShell to change and upgrade my techniques and methodologies. With PowerShell 5.1, as an attacker, I am actually afraid that whatever I do on a foothold or launchpad box may be logged and (hopefully) monitored. During my Offensive PowerShell and Active Directory training, the attendees who are industry practitioners and researchers, always appreciate the logging capabilities of PowerShell and try to implement them in their organization's networks.

But with PowerShell v6, PowerShell logging features have been drastically reduced! This is almost certainly because v6 is based on .NET Core but there has been no authoritative word about it. This post is to compare the most interesting logging capabilities of PowerShell v6 with Windows PowerShell 5.1.


All the enhanced logging capabilities PowerShell has, can be deployed using Group Policy. But this doesn't hold true for v6! To enable whatever logging for v6, a script RegisterManifest.ps1 (found in the $PSHOME directory) needs to be executed on each machine to register PowerShellCore event provider (PowerShell remoting can be used to run this script on scale). Thanks Satoshi for pointing this out.

The ability to configure logging from Group Policy is much easier to manage and harder to tamper with whereas the PowerShellCore event provider can be unregistered by using the "-UnRegister" parameter of the script.

System-wide Transcription

When System-wide transcription is enabled, all the activity for every PowerShell host (powershell.exe, powershell_ise.exe, System.Management.Automation.dll or other custom host) is logged to the specified directory or the user's "My Documents" directory if none is specified. With proper implementation, that is, forwarding logs to secure storage and correlation, system-wide transcription could be very effective in detecting PowerShell attacks. 

This is how system-wide transcription looks like for PowerShell 5.1 (The execution is using InstallUtil)
PowerShell v6 does not support system-wide transcription.

Script Block Logging

PowerShell v5.1 has two types of script block logging: Warning level auto logging and Verbose logging that can be configured. Warning level auto logging logs known bad/suspicious commands and script blocks and logs them in Microsoft-Windows-PowerShell/Operational log as Event ID 4104 Warning. When Verbose logging is turned on, which can be done using Group Policy, PowerShell commands are logged as Event ID 4104 Verbose.
Yes, there are public bypasses for script block logging as blogged by Ryan Cobb here and here, still, it increases attacker costs.

PowerShell v6 has no automatic script block logging. But when The PowerShellCore provider is created, the suspicious script blocks are logged with Event ID 4103 in the PowerShellCore logs.
Interestingly, while testing the warning level logs, I found out that v6 excels over v5.1 and logs less false positives. For example, one of suspicious strings (see code here) "GetMembers" is logged by 5.1 even if it is just executed senselessly.
But in case of v6, the above is not logged unless, there is a proper use of "GetMembers".
I find this very interesting and will have an in-depth look at it later on. May be, it could help in some interesting findings.

AntiMalware Scan Interface (AMSI)

AMSI provides the content of a script tor script block to the registered antivirus before execution takes place. This enables the antivirus to detect known bad scripts and script blocks regardless of input method (disk, memory, manual) and even encoded and obfuscated scripts. I spoke about AMSI at BlackHat USA 2016 and did a detailed blog post.

Fortunately, AMSI is enabled for PowerShell v6 as well. Although, Matt's bypass still works with just a minor modification.
But, once again, since it still increases cost to an attacker, its great to have AMSI in v6.

Constrained Language Mode

If "Allow mode" is enforced for Applocker or Device Guard, PowerShell is restricted automatically to the Constrained Language Mode which restricts Windows API, interaction with COM etc. See Language Modes

That is not the case with v6!


Introducing the PowerShell Upgrade Attack

PowerShell downgrade attack is popular with red teams. If you can run PowerShell v2, ALL security measures we have seen are bypassed as v2 simply doesn't support them. Lee provided an excellent guide on how to detect and prevent such attacks. If v2 is blocked or no required .NET version is installed, what to do? Simply run pwsh from your PowerShell session and you will drop in a new PowerShell session (v6 - if installed) which has minimal security features compared to v5/5.1. I am calling it the PowerShell Upgrade Attack :P. On a serious note, please keep in mind that Windows PowerShell - with enhanced logging - is the default one on Windows OS. Also, v6 is not an update, it needs to be installed separately. Windows PowerShell and PowerShell Core can be installed on a single machine and both will work independently.

So, what next?

I hold the PowerShell Team in high regard (for creating such a useful tool, being open to criticism and acting on the feedback) and quite confident (and hope) that they will address these shortcomings soon. Jeffery already tweeted that the Constrained Language Mode will be fixed in 6.1. But, if your production environment is working fine with Windows PowerShell v5/5.1, I would not advise to install v6 on any system (at least not the production ones).

UPDATE (25-Jan-2018) - The PowerShell Core Roadmap is published and there is no mention of bringing Core logging in parity with Windows PowerShell 5.1. Thankfully, the DeviceGuard/Applocker policy enforcement will get fixed.