Thursday, April 5, 2018

Secretsdump: DcSync

Been awhile since I wrote a post. But on forward. The following write up will be around trying to come up with a method for detecting dcsync.

My previous post was somewhat sporadic. In an attempt to introduce some structure to the writing, I wanted to loosely answer the questions outlined in Sergio Caltagirone's awesome article, Building Threat Hunting Strategies with the Diamond Model (source). 


What am I looking for?
I am looking for a user account performing dcsync operations
in the network. Typically you will see servers, particularly domain controllers, performing this
function thus observing a user account should raise some suspicion.


Why am I looking for it?
Dcsync , as explained by Sean Metcalf, “effectively “impersonates”
a Domain Controller and requests account password data from the
targeted Domain Controller.” (source) The combination of rights required to perform
this operation is replicating directory changes, replicating directory changes all, and replicating directory changes in a
filtered set (source). Simply put, if an attacker has compromised an account with the rights to dcsync, they could possibly gather
all NTLM hashes for your domain or just dcsync the KRBTGT hash, create a golden ticket and plunder.



How do I find it?
There are two methods in my experience, to identify this behavior.
Through network monitoring, if  your organization has internal Bro network sensors logging traffic to and from Domain Controllers, this Bro script can trigger an event whenever an IP not associated with a Domain Controller attempts the DRSGetNCChanges DCE-RPC operation. :

#loading smb is necessary at times
@load policy/protocols/smb


@load base/frameworks/notice


export {
       redef enum Notice::Type += {
               ## Indicates that a host was attempting a replication of the domain_controller.
               DCSync_attempt::Found
       };


#this is where you would place your domain controllers
const domain_controllers: set[addr] = {  
} &redef;


}


event dce_rpc_request(c: connection, fid: count, opnum: count, stub_len: count)
{ if ( c$id$orig_h in domain_controllers ) { return; } if ( c$dce_rpc?$operation && c$dce_rpc$operation == "DRSGetNCChanges" ) { NOTICE([$note=DCSync_attempt::Found, $msg=fmt("---- Replication from an unauthorized address ---"), $conn=c]); } }


Since I have not been able to test this script in a large enterprise environment :(, I cannot honestly relay
the signal to noise ratio.
With the help of the pentesting team I work with, we were able to identify that event code 4662, an operation was performed on an object, is triggered when a user attempts the DCSync operation. We will focus on the following key events to hopefully generate an accurate alert:

index=wineventlog sourcetype="WinEventLog:Security" EventCode=4662 Account_Name!="*\$" Access_Mask=0x100 Object_Type=domainDNS AND ("Replicating Directory Changes all"  OR “1131f6ad-9c07-11d1-f79f-00c04fc2dcd2” OR "{1131f6ad-9c07-11d1-f79f-00c04fc2dcd2}" ) | table _time Account_Name ComputerName Object_Server Object_Type Object_Name Accesses Access_Mask




You will first need to change the auditing policy in the Audit Directory Service Access subcategory in order
to begin seeing logs forward to splunk. This event code generates a good amount of noise so before it is forwarded, you could specify that you only want any account name that does not end with a $, eg Account_Name!="*\$". This will ensure that you filter out hosts that perform this function, typically Active Directory servers that need to replicate this information. However as a warning, if an attacker performs this action with a computer account, the signature will not trigger on the event.

The properties field for this event code is where you will find some crucial information. As explained in microsoft documentation, “first part is the type of access that was used. This Typically has the same value as Accesses field.



Highlighted is the value "for which operation was performed." 



Second part is a tree of GUID values of Active Directory classes or property sets, for which operation was performed.”(source) In our case, the operation that was performed that we want to focus on is the replicating directory changes all. However I have seen at times that the GUID is not converted to its display name, so that’s why in our signature we specify both the display name and GUID. 




What do I do when the alert triggers?
The unfortunate thing for either detection method, is that it does not identify which credentials were transfered
from domain controller to host. However once someone has the rights to conduct this attack, you may need to
assume that the attacker is capable of acquiring the KRBTGT hash which should raise an alert. An analyst also must
determine whether this is a false positive or not. Has this account performed this operation in the past? What actions
are associated with this account prior to triggering this alert? Do you have a cloud-based Azure Active Directory
instance that synchronizes user passwords from an on-premise Active Directory instance via a service account?(source) Are there any other instances where an account would need to synchronize user passwords from one Active Directory server to another?
How often is this performed? Does this request from the account always originate from the same IP? Do you have a relationship with your sysadmins where you could ask about account activity and rights delegated? Hopefully these questions are a few you ask yourself when filtering
out false positives.  As a caveat, the Windows detection signature is fairly experimental. Though it has worked for me, I would highly recommend, as with any new detection, testing before deploying. 


References: http://www.activeresponse.org/building-threat-hunting-strategy-with-the-diamond-model/
https://adsecurity.org/?page_id=1821#LSADUMPDCSync
https://adsecurity.org/?p=1729
https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4662

Saturday, December 16, 2017

Impacket part 1: psexec.py

As a SOC analyst we are often tasked with finding out either pentester or malicious
 activity that occurs in the monitored environment and creating signatures for
 these findings. In a recent pentesing engagement (after of course running freely in the
 network), they shared that they used the Impacket tools for much of their movement. 
This short series will be analyzing some of the various tools offered in the
Impacket set. Through this analysis we will attempt to identify elements of the tools
 that signatures can be created for. Although attackers have a seemingly limitless amount of 
tools, in your analysis you may discover a shared immutable principle between these tools 
that may lend insight to attack techniques in general.

We will begin with impacket tool psexec.py. The original psexec, written by Windows guru
 and all around savage Mark Russinovich, was created to help administrators remote
 into hosts and perform their administrative duties. It can also be an excellent tool for 
lateral movement in an environment. Psexec.py uses RemcomSVC to perform the same
 functions psexec can. As explained in the github page for RemcomSvc, it is :

“a small (10KB upx packed) remoteshell / telnet replacement that lets you execute processes on remote 
windows systems, copy files on remote systems, process their output and stream it back. It allows execution 
of remote shell commands directly with full interactive console without having to install any client software.”Source.

Below is a great succinct description provided in an article titled ‘Psexec Demystified’ on
 how PSExec works:

[PSExec] has a Windows Service image inside of its executable.

  1. It takes this service and deploys it to the Admin$ share on the remote machine
  2. It then uses the DCE/RPC interface over SMB to access the Windows Service Control Manager API.
    It turns on the PSExec service on the remote machine.
  3. The PSExec service then creates a named pipe that can be used to send commands to the system.”Source.


    We will go through each step with the psexec.py version with network traffic and host log examples.

    1. It takes this service and deploys it to the Admin$ share on the remote machine.    
    The Admin share is typically used to deploy software on a remote machine. Source. With Psexec.py,
     This is completed by authenticating to the remote machine  with NTLM over SMB,
     though Kerberos authentication can be used as well. The first oddity that stands out after 
    authenticating, is that psexec.py sends an SMB Create Request file named “BETO “
     to the remote host. Once it receives a response, it sends a setinfo command that requests
     the file to be deleted when closed. According to Microsoft the setinfo packet is sent by a 
    client to, “ request either creation of or access to a file. In case of a named pipe or printer, 
    the server MUST create a new file.” By going through the code I can see that the author's
     name is beto with a twitter handle of @agsolino. Perhaps the author did it to ensure they
     can create files on the $ADMIN share. Following this action, psexec.py connects back to 
    the $ADMIN share and writes a randomly generated eight character executable.
    The sha1 hash for this exe is  23873bf2670cf64c2440058130548d4e4da412dd.

    2. It then uses the DCE/RPC interface over SMB to access the Windows Service Control
     Manager API. It turns on the PSExec service on the remote machine.    
    In order to complete this part, the attacker must connect to the dce-rpc svcctl interface
     which is, “used to manage Windows services via the SCM (Service Control Manager)”, Source 
    and perform the following operations illustrated in the figure below.


    These were gathered from the dce_rpc.log from bro that I would highly recommend using as it
     is not only a great logging framework but a powerful scripting language as well. 
    When psexec.py performs the OpenSCManager operation it identifies the MachineName as DUMMY.
     When I used both remcom and the original psexec, they identified the machine name with the
     ip address of the remote host. This activity could also be viewed by looking for the windows event
     code 7045, a new service being installed and other ways through the windows logs that we will go
     through in the signatures section.

    3. The PSExec service then creates a named pipe that can be used to send commands to the system.
    This last action is completed through the  IPC(Inter Process Communication) share which
     allows for this type of communication between two remote hosts. In order for named pipe
     communications to occur, two packets must be sent: the SMB IOCTL request and Create 
    Request File packets. The SMB IOCTL packet requires the following before it is sent:
    • “A handle to the TreeConnect identifying the connection to the IPC$ share
    •  The name of the named pipe, omitting any prefixes such as "\pipe\".Source.
    What matters to us, is the identification of the connection to the IPC$ share and the name of the named
     pipe. For psexec.py, the names for the named pipes are RemCom_communication, 
    RemCom_stdin[a-z0-9]{8}, RemCom_stdout[a-z0-9]{8} and RemCom_stderr[a-z0-9]{8}. 
    The Create Request File packet contains the access mask for each of these named pipes requests, 
    which is the other significant aspect to make note of. The access mask provides insight into what the
     attacker wants to do when they access the remote host. For the RemCom_communication named
     pipe pictured below, it contains the access mask of 0x0012019f. This is the same access mask many
     msrpc named pipes request when establishing a communication channel. Remcom stdin, requests 0x6, 
    which is write and append and stdout and stderr both request 0x1, which is read. By looking at these
     access masks and knowing their values, you can infer that psexec.py allows for some form of
     interactive communication over this named pipe.
    access_mask.png




    Signatures

    The signatures we will be creating, will be from Windows event logs forwarded to Splunk, since, 
    at least in my limited experience, network taps are almost never placed where you want them; 
     typically being placed at the perimeter, making every network defender cry :(. If you want to follow 
    along, I would recommend installing Splunk in your home lab. DA_667 has released a book on how 
    to  create a lab and there’s an awesome section on how to install Splunk.
    We can begin with some easy ones that generate an alert from some of the strings we pointed out
     earlier.
    iindex=wineventlog sourcetype=wineventlog:security EventCode=5145 Relative_Target_Name="BETO" | table _time Source_Address Account_Name Share_Name Share_Path Relative_Target_Name Access_Mask

    index=wineventlog sourcetype=wineventlog:security Relative_Target_Name="RemCom*" EventCode=5145 | table _time Source_Address Account_Name ComputerName Share_Name Relative_Target_Name Access_Mask

    Some others would require you to profile the activity that occurs in the network. 
    Should users/service accounts be accessing the $ADMIN share in your environment?
    If so, who does? From what IP? Is that IP always the same? Why do they usually access this share and on which hosts
    does this activity typically occur? Even looking for writes to the Admin share may yield some interesting discoveries:

    index=wineventlog sourcetype=wineventlog:security EventCode=5145
    (Access_Mask=0x120196 OR Access_Mask=0x2 OR Access_Mask=0x6 OR Access_Mask=0x130197) | table _time Source_Address Account_Name ComputerName Share_Name Relative_Target_Name Access_Mask

    Again though, there may be service accounts that  trigger these queries, so it's best to run these first as far back as you can to filter out false positives or to determine whether this is applicable in your environment.

    What about services installed on a host? How many times does this occur and by which user accounts?

    sourcetype="WinEventLog:Security" index=wineventlog EventCode=5145 AND (Access_Mask="0x2" OR Access_Mask="0x6" OR Access_Mask="0x12019f") | bucket _time span=3s | rex "(?<masks>(0x2|0x6|0x12019f))" | stats values(Relative_Target_Name) AS Relative_Target_Name values(Account_Name) AS Account_Name values(Source_Address) AS Source_Address dc(masks) AS distinct_masks by _time ComputerName | search distinct_masks=3 | table _time Source_Address Account_Name ComputerName Relative_Target_Name distinct_masks

    This signature is a bit different from the other ones. As the other ones look for identifiable
     strings, this one is more for the behavioral aspect. It looks for for a write to a share (0x2) 
    along with the write and append (0x6) and for the create file request (0x12019f)
     within a small period of time on the same host.  This signature was a revision of one created by
     jackcr in his blog findingbad.blogspot.com. Jackr is an excellent resource for developing and 
    honing your analytical process when looking for adversaries. Source

    index=wineventlog sourcetype=wineventlog:security  (EventCode=4688) OR (EventCode=5145 Access_Mask=0x120196 OR Access_Mask=0x2 OR Access_Mask=0x6 OR Access_Mask=0x130197)
    | bucket _time span=1s
    | stats values(Process_Command_Line) AS Process_Command_Line values(Relative_Target_Name) AS Relative_Target_Name values(Account_Name) AS Account_Name by _time  ComputerName
    | search Relative_Target_Name!="NULL" AND Process_Command_Line!="NULL"
    | table _time  Account_Name ComputerName Process_Command_Line Relative_Target_Name


    This signature, pictured below, looks for  writes to an smb share and command line 
    execution within a one second time span. The selection of access masks are relatively rare, 
    thus when those are used I would want to observe if there was any command line activity within 
    that time.



    index=wineventlog (sourcetype="wineventlog:security" EventCode=5145 Access_Mask=0x2
     OR Access_Mask=0x120196 OR Access_Mask=0x6) OR
     (sourcetype="wineventlog:system" EventCode=7045)
    | rex field=Service_File_Name "(?<file_name>[^\\\]*$)"
    | bucket _time span=1s
     | stats values(file_name) AS file_name values(Relative_Target_Name) 
    AS Relative_Target_Name values(EventCode) AS EventCode values(Account_Name)
     AS Account_Name by _time ComputerName
      | search file_name!="NULL" AND Relative_Target_Name!="NULL"
    | table _time Account_Name file_name Relative_Target_Name ComputerName

    This signature is very similar to the previous query however it looks for service created rather than
     process executed.






    index=wineventlog (sourcetype="wineventlog:security" EventCode=5145 Access_Mask=0x2
    OR Access_Mask=0x120196 OR Access_Mask=0x6 OR Access_Mask=0x130197)
    OR (sourcetype="wineventlog:system" EventCode=7045)
     | rex field=Service_File_Name "(?<process>[^\\\]*$)"
      | streamstats count by EventCode process Relative_Target_Name
     | bucket _time span=1s
      | stats values(process) AS process values(Relative_Target_Name) AS Relative_Target_Name values(EventCode) AS EventCode by _time ComputerName
       | eval status = if(match(process,Relative_Target_Name), "Match", "No Match")
       | search status="Match"

    This signature looks for whether process executed and the file written to the share are the same within a one second time span and if they match, return the results.








    Sources:






    http://www.hsc.fr/ressources/articles/win_net_srv/msrpc_svcctl.html




    Tuesday, December 5, 2017

    What will follow will be intermittent protocol and log analysis. I will attempt to organize my ramblings into something coherent and worth reading. But mostly I want a place to record my thoughts so I can come back to them later.