Initial commit - 611 cybersecurity skills across all subdomains

This commit is contained in:
mukul975
2026-02-25 10:47:44 +01:00
commit 22a7ab1462
1765 changed files with 280648 additions and 0 deletions
@@ -0,0 +1,135 @@
---
name: detecting-dcsync-attack-in-active-directory
description: Detect DCSync attacks where adversaries abuse Active Directory replication privileges to extract password hashes by monitoring for non-domain-controller accounts requesting directory replication via DsGetNCChanges.
domain: cybersecurity
subdomain: threat-hunting
tags: [threat-hunting, active-directory, dcsync, credential-theft, mitre-t1003-006, mimikatz, kerberos]
version: "1.0"
author: mahipal
license: MIT
---
# Detecting DCSync Attack in Active Directory
## When to Use
- When hunting for credential theft in Active Directory environments
- After compromise of accounts with Replicating Directory Changes permissions
- When investigating suspected use of Mimikatz or Impacket secretsdump
- During incident response involving lateral movement with domain admin credentials
- When auditing AD replication permissions as part of security hardening
## Prerequisites
- Windows Security Event Logs with Event ID 4662 (Object Access) enabled
- Advanced Audit Policy: Audit Directory Service Access enabled
- Domain Controller event forwarding to SIEM
- Knowledge of legitimate domain controller hostnames and IPs
- Directory Service Access auditing with SACL on domain object
## Workflow
1. **Identify Legitimate Replication Sources**: Document all domain controllers in the environment by hostname, IP, and computer account. Only these should perform directory replication.
2. **Enable Required Auditing**: Configure Advanced Audit Policy to capture Event ID 4662 on domain controllers with specific GUID monitoring for replication rights.
3. **Monitor Replication Rights Access**: Track access to three critical GUIDs -- DS-Replication-Get-Changes (1131f6aa-9c07-11d1-f79f-00c04fc2dcd2), DS-Replication-Get-Changes-All (1131f6ad-9c07-11d1-f79f-00c04fc2dcd2), and DS-Replication-Get-Changes-In-Filtered-Set (89e95b76-444d-4c62-991a-0facbeda640c).
4. **Detect Non-DC Replication Requests**: Alert when any account NOT associated with a domain controller requests replication rights.
5. **Correlate with Network Traffic**: DCSync generates replication traffic (MS-DRSR/RPC) from the attacker's machine to the DC. Monitor for DrsGetNCChanges RPC calls from non-DC IP addresses.
6. **Investigate Source Context**: Examine the process, user account, and machine originating the replication request.
7. **Check for Credential Abuse**: After DCSync detection, audit for subsequent use of extracted hashes (pass-the-hash, golden ticket creation).
## Key Concepts
| Concept | Description |
|---------|-------------|
| T1003.006 | OS Credential Dumping: DCSync |
| DCSync | Mimicking domain controller replication to extract credentials |
| DsGetNCChanges | RPC function used to request AD replication data |
| DS-Replication-Get-Changes | AD permission required (GUID: 1131f6aa-...) |
| DS-Replication-Get-Changes-All | Permission including confidential attributes (GUID: 1131f6ad-...) |
| MS-DRSR | Microsoft Directory Replication Service Remote Protocol |
| KRBTGT Hash | Key target of DCSync enabling Golden Ticket attacks |
| Event ID 4662 | Directory service object access audit event |
## Tools & Systems
| Tool | Purpose |
|------|---------|
| Mimikatz (lsadump::dcsync) | Primary DCSync attack tool |
| Impacket secretsdump.py | Python-based DCSync implementation |
| DSInternals | PowerShell module for AD replication |
| BloodHound | Map accounts with replication rights |
| Splunk / Elastic | SIEM correlation of 4662 events |
| Microsoft Defender for Identity | Native DCSync detection |
| CrowdStrike Falcon | EDR-based DCSync detection |
## Detection Queries
### Splunk -- DCSync Detection via Event 4662
```spl
index=wineventlog EventCode=4662
| where Properties IN ("*1131f6aa-9c07-11d1-f79f-00c04fc2dcd2*",
"*1131f6ad-9c07-11d1-f79f-00c04fc2dcd2*",
"*89e95b76-444d-4c62-991a-0facbeda640c*")
| where NOT match(SubjectUserName, ".*\\$$")
| where NOT SubjectUserName IN ("known_svc_account1", "known_svc_account2")
| stats count values(Properties) as ReplicationRights by SubjectUserName SubjectDomainName Computer
| where count > 0
| table SubjectUserName SubjectDomainName Computer count ReplicationRights
```
### KQL -- Microsoft Sentinel DCSync Detection
```kql
SecurityEvent
| where EventID == 4662
| where Properties has "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"
or Properties has "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2"
| where SubjectUserName !endswith "$"
| where SubjectUserName !in ("AzureADConnect", "MSOL_*")
| project TimeGenerated, SubjectUserName, SubjectDomainName, Computer, Properties
| sort by TimeGenerated desc
```
### Sigma Rule -- DCSync Activity
```yaml
title: DCSync Activity Detected - Non-DC Replication Request
status: stable
logsource:
product: windows
service: security
detection:
selection:
EventID: 4662
Properties|contains:
- '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2'
- '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2'
filter_dc:
SubjectUserName|endswith: '$'
condition: selection and not filter_dc
level: critical
tags:
- attack.credential_access
- attack.t1003.006
```
## Common Scenarios
1. **Mimikatz DCSync**: Attacker with Domain Admin privileges runs `lsadump::dcsync /user:krbtgt` to extract KRBTGT hash for Golden Ticket creation.
2. **Impacket secretsdump**: Remote DCSync via `secretsdump.py domain/user:password@dc-ip` extracting all domain hashes.
3. **Delegated Replication Rights**: Attacker grants themselves Replicating Directory Changes rights via ACL modification before performing DCSync.
4. **Azure AD Connect Abuse**: Compromising the Azure AD Connect service account which has legitimate replication rights.
5. **DSInternals PowerShell**: Using `Get-ADReplAccount` cmdlet to replicate specific account credentials.
## Output Format
```
Hunt ID: TH-DCSYNC-[DATE]-[SEQ]
Alert Severity: Critical
Source Account: [Account requesting replication]
Source Machine: [Hostname/IP of requestor]
Target DC: [Domain controller receiving request]
Replication Rights: [GUIDs accessed]
Timestamp: [Event time]
Legitimate DC: [Yes/No]
Known Service Account: [Yes/No]
Risk Assessment: [Critical - non-DC replication detected]
```
@@ -0,0 +1,47 @@
# DCSync Attack Detection Hunt Template
## Hunt Metadata
| Field | Value |
|-------|-------|
| Hunt ID | TH-DCSYNC-YYYY-MM-DD-NNN |
| Analyst | |
| Date | |
| Status | [ ] In Progress / [ ] Complete |
## Hypothesis
> An adversary with elevated AD privileges is performing DCSync to extract password hashes from Active Directory by replicating directory data from a non-domain-controller machine.
## Pre-Hunt Checklist
- [ ] Event ID 4662 audit policy enabled on all DCs
- [ ] SACL configured on domain root object
- [ ] Domain controller inventory documented
- [ ] Known service accounts with replication rights documented
- [ ] Azure AD Connect accounts identified (if hybrid)
## DCSync Detection Findings
| # | Timestamp | Subject Account | Source Machine | Target DC | Replication Rights | Severity |
|---|-----------|-----------------|----------------|-----------|-------------------|----------|
| 1 | | | | | | |
## Accounts with Replication Rights Audit
| Account | Type | Rights | Legitimate | Justification |
|---------|------|--------|-----------|---------------|
| | User/Service/Computer | Get-Changes / Get-Changes-All | Yes/No | |
## Post-DCSync Impact Assessment
| Check | Status | Notes |
|-------|--------|-------|
| KRBTGT hash potentially compromised | | |
| Domain Admin hashes extracted | | |
| Service account credentials at risk | | |
| Golden Ticket creation possible | | |
## Response Actions
1. **Disable**: [Compromised accounts]
2. **Reset**: [KRBTGT password -- twice, 12 hours apart]
3. **Revoke**: [Unauthorized replication rights]
4. **Investigate**: [Source machine forensics]
5. **Monitor**: [Subsequent credential abuse attempts]
@@ -0,0 +1,49 @@
# Standards and References - DCSync Attack Detection
## MITRE ATT&CK Credential Access (TA0006)
| Technique | Name | Relevance |
|-----------|------|-----------|
| T1003.006 | OS Credential Dumping: DCSync | Primary technique |
| T1003.001 | LSASS Memory | Often combined with DCSync for complete credential theft |
| T1003.003 | NTDS | Alternative to DCSync using ntdsutil or volume shadow copy |
| T1078.002 | Valid Accounts: Domain Accounts | Using dumped credentials |
| T1558.001 | Steal or Forge Kerberos Tickets: Golden Ticket | Primary goal of KRBTGT hash extraction |
| T1222.001 | File and Directory Permissions Modification | Granting replication rights |
## Critical Replication GUIDs
| GUID | Permission Name | Risk |
|------|----------------|------|
| 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 | DS-Replication-Get-Changes | Required for DCSync |
| 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2 | DS-Replication-Get-Changes-All | Includes confidential attributes (passwords) |
| 89e95b76-444d-4c62-991a-0facbeda640c | DS-Replication-Get-Changes-In-Filtered-Set | Partial replication rights |
## Windows Event IDs for DCSync Detection
| Event ID | Source | Description |
|----------|--------|-------------|
| 4662 | Security | Directory Service Object Access (primary detection) |
| 4624 | Security | Successful logon (correlate source of replication) |
| 4672 | Security | Special privileges assigned (admin logon) |
| 4738 | Security | User account changed (permission grants) |
| 5136 | Security | Directory Service Object modified (ACL changes) |
## Known Threat Actors Using DCSync
| Actor | Context |
|-------|---------|
| APT29 (Cozy Bear) | Used DCSync in SolarWinds campaign |
| FIN6 | DCSync for credential harvesting in retail/hospitality |
| Wizard Spider | TrickBot/Conti ransomware using DCSync pre-encryption |
| APT28 (Fancy Bear) | DCSync in government network intrusions |
| LAPSUS$ | DCSync after AD compromise for data theft |
## Legitimate Replication Sources
| Source | Reason | How to Distinguish |
|--------|--------|--------------------|
| Domain Controllers | Normal AD replication | Computer account ends with $ |
| Azure AD Connect | Hybrid identity sync | MSOL_ service account |
| Backup Software | AD backup operations | Documented service accounts |
| Migration Tools | Cross-forest migrations | Temporary, documented operations |
@@ -0,0 +1,99 @@
# Detailed Hunting Workflow - DCSync Attack Detection
## Phase 1: Enumerate Legitimate Replication Accounts
### Step 1.1 - List All Domain Controllers
```powershell
Get-ADDomainController -Filter * | Select-Object Name, IPv4Address, OperatingSystem
```
### Step 1.2 - Find Accounts with Replication Rights
```powershell
# Find all accounts with Replicating Directory Changes
Import-Module ActiveDirectory
$rootDSE = Get-ADRootDSE
$domainDN = $rootDSE.defaultNamingContext
$acl = Get-Acl "AD:\$domainDN"
$acl.Access | Where-Object {
$_.ObjectType -eq "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2" -or
$_.ObjectType -eq "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2"
} | Select-Object IdentityReference, ActiveDirectoryRights, ObjectType
```
### Step 1.3 - BloodHound Query for DCSync Rights
```cypher
MATCH p=(n)-[:GetChanges|GetChangesAll]->(d:Domain)
WHERE NOT n:Domain
RETURN n.name, labels(n)
```
## Phase 2: Deploy Detection
### Step 2.1 - Enable Required Audit Policy
```cmd
auditpol /set /subcategory:"Directory Service Access" /success:enable /failure:enable
```
### Step 2.2 - Configure SACL on Domain Object
Apply SACL to the domain root object monitoring for:
- Control Access rights
- Access to Replication GUIDs
- By Everyone or Authenticated Users
## Phase 3: Active Monitoring
### Step 3.1 - Splunk Real-Time Detection
```spl
index=wineventlog source="WinEventLog:Security" EventCode=4662
| rex field=Properties "(?<guid>\{[0-9a-f-]+\})"
| where guid IN ("{1131f6aa-9c07-11d1-f79f-00c04fc2dcd2}",
"{1131f6ad-9c07-11d1-f79f-00c04fc2dcd2}",
"{89e95b76-444d-4c62-991a-0facbeda640c}")
| lookup dc_accounts SubjectUserName OUTPUT is_dc
| where is_dc!="true"
| eval alert_severity="CRITICAL"
| table _time SubjectUserName SubjectDomainName Computer guid alert_severity
```
### Step 3.2 - Network-Level Detection
```spl
index=zeek sourcetype=dce_rpc
| where operation="DRSGetNCChanges"
| lookup domain_controllers src_ip OUTPUT is_dc
| where is_dc!="true"
| table _time src_ip dst_ip operation
```
## Phase 4: Investigation
### Step 4.1 - Determine Source Machine
Correlate Event 4662 with Event 4624 to identify the source workstation:
```spl
index=wineventlog EventCode=4624 LogonType=3
| where TargetUserName=[suspected_account]
| table _time TargetUserName IpAddress WorkstationName LogonType
```
### Step 4.2 - Check for Subsequent Credential Abuse
```spl
index=wineventlog EventCode=4769
| where ServiceName="krbtgt"
| where TicketEncryptionType="0x17"
| table _time TargetUserName ServiceName IpAddress TicketEncryptionType
```
## Phase 5: Response
### Step 5.1 - Immediate Containment
1. Disable compromised account immediately
2. Rotate KRBTGT password (twice, 12 hours apart)
3. Reset all service account passwords
4. Block source IP at network level
5. Isolate source machine for forensics
### Step 5.2 - Remediation
1. Remove unauthorized replication rights
2. Review all accounts with DCSync-capable permissions
3. Implement tiered administration model
4. Enable Microsoft Defender for Identity DCSync alerts
5. Deploy Protected Users security group for admin accounts
@@ -0,0 +1,154 @@
#!/usr/bin/env python3
"""
DCSync Attack Detection Script
Analyzes Windows Security Event 4662 logs to identify non-domain-controller
accounts requesting Active Directory replication rights.
"""
import json
import csv
import argparse
import datetime
import re
from pathlib import Path
REPLICATION_GUIDS = {
"1131f6aa-9c07-11d1-f79f-00c04fc2dcd2": "DS-Replication-Get-Changes",
"1131f6ad-9c07-11d1-f79f-00c04fc2dcd2": "DS-Replication-Get-Changes-All",
"89e95b76-444d-4c62-991a-0facbeda640c": "DS-Replication-Get-Changes-In-Filtered-Set",
}
GUID_PATTERN = re.compile(r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", re.IGNORECASE)
def load_dc_list(dc_file: str) -> set:
"""Load known domain controller accounts from file."""
dcs = set()
if dc_file:
path = Path(dc_file)
if path.exists():
with open(path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if line and not line.startswith("#"):
dcs.add(line.lower())
return dcs
def parse_events(input_path: str) -> list[dict]:
"""Parse Windows event log exports (JSON, CSV, EVTX-exported CSV)."""
path = Path(input_path)
events = []
if path.suffix == ".json":
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
events = data if isinstance(data, list) else data.get("events", [])
elif path.suffix == ".csv":
with open(path, "r", encoding="utf-8-sig") as f:
events = [dict(row) for row in csv.DictReader(f)]
return events
def detect_dcsync(events: list[dict], known_dcs: set) -> list[dict]:
"""Detect DCSync activity from Event 4662 logs."""
findings = []
for event in events:
event_id = str(event.get("EventID", event.get("EventCode", event.get("event_id", ""))))
if event_id != "4662":
continue
properties = event.get("Properties", event.get("properties", ""))
if not properties:
continue
found_guids = GUID_PATTERN.findall(properties.lower())
replication_guids = [g for g in found_guids if g in REPLICATION_GUIDS]
if not replication_guids:
continue
subject_user = event.get("SubjectUserName", event.get("subject_user_name", ""))
subject_domain = event.get("SubjectDomainName", event.get("subject_domain_name", ""))
computer = event.get("Computer", event.get("computer", ""))
timestamp = event.get("TimeCreated", event.get("_time", event.get("timestamp", "")))
# Check if this is a legitimate domain controller
is_dc = False
subject_lower = subject_user.lower()
if subject_lower.endswith("$"):
if subject_lower in known_dcs or subject_lower.rstrip("$") in known_dcs:
is_dc = True
if is_dc:
continue
replication_rights = [REPLICATION_GUIDS[g] for g in replication_guids]
has_get_changes_all = "DS-Replication-Get-Changes-All" in replication_rights
severity = "CRITICAL" if has_get_changes_all else "HIGH"
findings.append({
"timestamp": timestamp,
"subject_user": subject_user,
"subject_domain": subject_domain,
"computer": computer,
"replication_guids": replication_guids,
"replication_rights": replication_rights,
"has_get_changes_all": has_get_changes_all,
"is_machine_account": subject_user.endswith("$"),
"severity": severity,
"description": f"Non-DC account '{subject_user}' requested replication rights: {', '.join(replication_rights)}",
})
return sorted(findings, key=lambda x: x.get("timestamp", ""), reverse=True)
def run_hunt(input_path: str, dc_file: str, output_dir: str) -> None:
"""Execute DCSync detection hunt."""
print(f"[*] DCSync Detection Hunt - {datetime.datetime.now().isoformat()}")
known_dcs = load_dc_list(dc_file)
print(f"[*] Known domain controllers: {len(known_dcs)}")
events = parse_events(input_path)
print(f"[*] Loaded {len(events)} events")
findings = detect_dcsync(events, known_dcs)
print(f"[!] DCSync detections: {len(findings)}")
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
with open(output_path / "dcsync_findings.json", "w", encoding="utf-8") as f:
json.dump({
"hunt_id": f"TH-DCSYNC-{datetime.date.today().isoformat()}",
"total_events": len(events),
"findings_count": len(findings),
"findings": findings,
}, f, indent=2)
with open(output_path / "dcsync_report.md", "w", encoding="utf-8") as f:
f.write("# DCSync Attack Detection Report\n\n")
f.write(f"**Date**: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"**Events Analyzed**: {len(events)}\n")
f.write(f"**Findings**: {len(findings)}\n\n")
for finding in findings:
f.write(f"## [{finding['severity']}] {finding['subject_user']}\n")
f.write(f"- **Time**: {finding['timestamp']}\n")
f.write(f"- **Computer**: {finding['computer']}\n")
f.write(f"- **Rights**: {', '.join(finding['replication_rights'])}\n")
f.write(f"- **Description**: {finding['description']}\n\n")
print(f"[+] Results written to {output_dir}")
def main():
parser = argparse.ArgumentParser(description="DCSync Attack Detection")
parser.add_argument("--input", "-i", required=True, help="Path to Windows event logs")
parser.add_argument("--dc-list", "-d", default="", help="File with known DC accounts")
parser.add_argument("--output", "-o", default="./dcsync_hunt_output", help="Output directory")
args = parser.parse_args()
run_hunt(args.input, args.dc_list, args.output)
if __name__ == "__main__":
main()