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,168 @@
---
name: performing-active-directory-compromise-investigation
description: Investigate Active Directory compromise by analyzing authentication logs, replication metadata, Group Policy changes, and Kerberos ticket anomalies to identify attacker persistence and lateral movement paths.
domain: cybersecurity
subdomain: incident-response
tags: [active-directory, compromise-investigation, identity-forensics, kerberos, lateral-movement, dfir, ntds-dit, golden-ticket]
version: "1.0"
author: mahipal
license: MIT
---
# Performing Active Directory Compromise Investigation
## Overview
Active Directory (AD) compromise investigation is a critical incident response capability that focuses on identifying how attackers gained access to domain services, what persistence mechanisms they established, and the scope of credential compromise. Since 88% of breaches involve compromised credentials (Verizon 2025 DBIR), AD is the primary target for enterprise-wide attacks. Investigators must analyze NTDS.dit database integrity, Kerberos ticket-granting activity, Group Policy modifications, replication metadata, and privileged group membership changes to reconstruct the attack chain and determine full compromise scope.
## Key Investigation Areas
### 1. NTDS.dit Database Analysis
The NTDS.dit file is the core Active Directory credential database containing all password hashes for domain accounts. Attackers commonly exfiltrate this file using tools like ntdsutil, secretsdump.py, or DCSync attacks via Mimikatz.
**Detection indicators:**
- Event ID 4662: Access to directory service objects with replication permissions
- Event ID 4742: Computer account modifications on domain controllers
- Volume Shadow Copy creation on domain controllers (Event ID 8222)
- Unusual ntdsutil.exe or vssadmin.exe execution
- Replication traffic from non-DC sources (DCSync detection)
### 2. Kerberos Attack Detection
**Golden Ticket indicators:**
- TGT tickets with abnormally long lifetimes (default is 10 hours)
- Event ID 4769 with encryption type 0x17 (RC4) instead of AES
- TGT issued without corresponding Event ID 4768 (AS-REQ)
- Kerberos tickets referencing non-existent or disabled accounts
**Silver Ticket indicators:**
- Service tickets without corresponding TGT requests
- Event ID 4769 with unusual service names
- Tickets with forged PAC data
**Kerberoasting indicators:**
- High volume of Event ID 4769 for service accounts
- RC4 encryption requests for accounts that support AES
- Requests from workstations not normally accessing those services
### 3. Group Policy Abuse
- GPO modifications granting new privileges (Event ID 5136)
- Scheduled task deployment via GPO
- Software installation policies added to domain
- Login script modifications
- Registry-based policy changes for persistence
### 4. Privileged Group Enumeration
Track modifications to these critical groups:
- Domain Admins, Enterprise Admins, Schema Admins
- Account Operators, Backup Operators
- DnsAdmins (can execute arbitrary DLLs on DCs)
- Group Policy Creator Owners
- Protected Users group membership changes
### 5. Trust Relationship Analysis
- New forest/domain trusts created (Event ID 4706)
- SID History injection for privilege escalation
- Trust ticket forgery indicators
- Cross-domain authentication anomalies
## Investigation Methodology
### Phase 1: Scoping and Evidence Collection
```
1. Identify potentially compromised domain controllers
2. Collect Security, System, Directory Service event logs
3. Extract AD replication metadata using repadmin
4. Capture ntdsutil snapshots for offline analysis
5. Collect DNS server logs and zone transfer records
6. Export Group Policy Object configurations
7. Document current privileged group memberships
```
### Phase 2: Authentication Log Analysis
```
1. Parse Event ID 4624/4625 for logon patterns
2. Identify pass-the-hash indicators (Event ID 4624 Type 3 with NTLM)
3. Analyze Event ID 4768/4769/4771 for Kerberos anomalies
4. Review Event ID 4776 for NTLM authentication failures
5. Cross-reference logon events with known compromised accounts
6. Map lateral movement paths through authentication chains
```
### Phase 3: Persistence and Backdoor Detection
```
1. Enumerate AdminSDHolder ACL modifications
2. Check for SID History abuse on accounts
3. Verify krbtgt account password age
4. Audit DSRM password configuration
5. Check for skeleton key malware indicators
6. Review AD Certificate Services for rogue certificates
7. Validate DNS records for poisoning
```
### Phase 4: Remediation Planning
```
1. Double-rotate krbtgt password (wait replication between rotations)
2. Reset all compromised account passwords
3. Remove unauthorized privileged group members
4. Revoke rogue certificates if AD CS compromised
5. Rebuild domain controllers from clean media if needed
6. Implement tiered administration model
7. Enable Protected Users group for privileged accounts
```
## Critical Event IDs for AD Investigation
| Event ID | Source | Description |
|----------|--------|-------------|
| 4624 | Security | Successful logon |
| 4625 | Security | Failed logon |
| 4648 | Security | Explicit credential logon |
| 4662 | Security | Operation on AD object |
| 4768 | Security | Kerberos TGT requested |
| 4769 | Security | Kerberos service ticket requested |
| 4771 | Security | Kerberos pre-authentication failed |
| 4776 | Security | NTLM credential validation |
| 5136 | Security | Directory object modified |
| 5137 | Security | Directory object created |
| 4706 | Security | Trust created |
| 4707 | Security | Trust removed |
| 4742 | Security | Computer account changed |
| 8222 | System | Shadow copy created |
## Tools for AD Investigation
| Tool | Purpose |
|------|---------|
| **BloodHound** | Attack path mapping and privilege escalation analysis |
| **Pingcastle** | AD security assessment and risk scoring |
| **Purple Knight** | AD vulnerability scanning by Semperis |
| **ADRecon** | Active Directory data gathering |
| **Mimikatz** | Credential extraction and Kerberos analysis |
| **Impacket** | DCSync detection and NTLM relay analysis |
| **Velociraptor** | Remote forensic artifact collection |
| **Timeline Explorer** | Event log timeline analysis |
## MITRE ATT&CK Mapping
| Technique | ID | Relevance |
|-----------|----|-----------|
| DCSync | T1003.006 | NTDS.dit credential extraction |
| Golden Ticket | T1558.001 | Kerberos TGT forgery |
| Silver Ticket | T1558.002 | Service ticket forgery |
| Kerberoasting | T1558.003 | Service account hash extraction |
| Pass-the-Hash | T1550.002 | NTLM hash reuse |
| Group Policy Modification | T1484.001 | Persistence via GPO |
| Account Manipulation | T1098 | Privileged group changes |
| SID-History Injection | T1134.005 | Privilege escalation |
## References
- [CISA: Detecting and Mitigating Active Directory Compromises](https://www.cisa.gov/resources-tools/resources/detecting-and-mitigating-active-directory-compromises)
- [Microsoft: Total Identity Compromise IR Lessons](https://techcommunity.microsoft.com/blog/microsoftsecurityexperts/total-identity-compromise-microsoft-incident-response-lessons-on-securing-active/3753391)
- [Semperis: Top 10 Active Directory Risks](https://www.semperis.com/blog/10-ad-risks-caught-by-identity-forensics-and-incident-response/)
- [Fidelis: Active Directory Compromise Response](https://fidelissecurity.com/threatgeek/active-directory-security/respond-after-an-active-directory-compromise/)
@@ -0,0 +1,147 @@
# Active Directory Compromise Investigation Report Template
## Case Information
| Field | Details |
|-------|---------|
| Case ID | IR-AD-YYYY-XXX |
| Investigator | |
| Date Initiated | |
| Organization | |
| Domain(s) Affected | |
| Domain Controllers | |
| Estimated Compromise Date | |
## Executive Summary
[Brief description of the AD compromise, scope, and critical findings]
## Scope of Investigation
### Domain Controllers Examined
| DC Name | OS Version | IP Address | Role | Status |
|---------|-----------|------------|------|--------|
| | | | | |
### Log Sources Collected
- [ ] Security Event Logs (all DCs)
- [ ] System Event Logs
- [ ] Directory Service Logs
- [ ] DNS Server Logs
- [ ] PowerShell Transcription Logs
- [ ] Replication Metadata
- [ ] GPO Configuration Export
- [ ] Privileged Group Membership Export
## Attack Timeline
| Timestamp | Event | Source | Severity |
|-----------|-------|--------|----------|
| | Initial access | | |
| | Privilege escalation | | |
| | Lateral movement | | |
| | Domain compromise | | |
| | Data access/exfiltration | | |
## Findings
### Finding 1: [Attack Category]
- **Severity:** CRITICAL / HIGH / MEDIUM / LOW
- **Evidence:** [Event IDs, log entries, artifacts]
- **Impact:** [Accounts, systems, data affected]
- **MITRE ATT&CK:** [Technique ID and name]
### Finding 2: [Attack Category]
- **Severity:**
- **Evidence:**
- **Impact:**
- **MITRE ATT&CK:**
## Compromised Accounts
| Account | Type | Privileges | Compromise Method | Status |
|---------|------|------------|-------------------|--------|
| | Domain Admin | | DCSync | Disabled |
| | Service Account | | Kerberoasting | Reset |
## Kerberos Analysis
### Golden Ticket Assessment
- [ ] krbtgt password age: _____ days
- [ ] TGTs with abnormal lifetimes detected: Yes / No
- [ ] RC4 encryption on tickets detected: Yes / No
- [ ] Service tickets without TGT requests: Yes / No
### Kerberoasting Assessment
- [ ] Bulk TGS requests from single source: Yes / No
- [ ] Service accounts with weak passwords: Yes / No
- [ ] Service accounts targeted: _____ accounts
## Lateral Movement Map
```
[Source] --> [Hop 1] --> [Hop 2] --> [Domain Controller]
|
+--> [Hop 1b] --> [File Server]
```
## Persistence Mechanisms Found
- [ ] AdminSDHolder ACL modifications
- [ ] SID History injection
- [ ] Rogue GPO policies
- [ ] Skeleton Key malware
- [ ] DCShadow objects
- [ ] Rogue AD CS certificates
- [ ] Scheduled tasks via GPO
- [ ] Modified login scripts
- [ ] Custom WMI subscriptions
## Remediation Actions
### Immediate (0-24 hours)
- [ ] Disable all compromised accounts
- [ ] Isolate compromised systems
- [ ] Block attacker IP addresses at firewall
- [ ] Double-rotate krbtgt password
- [ ] Revoke all active sessions
### Short-term (24-72 hours)
- [ ] Reset all privileged account passwords
- [ ] Reset all service account passwords
- [ ] Remove unauthorized group memberships
- [ ] Revert malicious GPO changes
- [ ] Remove persistence mechanisms
### Long-term (1-4 weeks)
- [ ] Force all user password changes
- [ ] Implement tiered administration model
- [ ] Deploy Privileged Access Workstations
- [ ] Enable Microsoft Defender for Identity
- [ ] Implement LAPS for local admin passwords
- [ ] Configure advanced audit policies
- [ ] Add critical accounts to Protected Users group
## Indicators of Compromise
### Accounts
| Account | Type | Activity |
|---------|------|----------|
| | | |
### IP Addresses
| IP | Activity | First Seen | Last Seen |
|----|----------|------------|-----------|
| | | | |
### Tools Detected
| Tool | Hash | Location | Purpose |
|------|------|----------|---------|
| | | | |
## Appendix
### Event Log Analysis Summary
### BloodHound Attack Path Diagrams
### GPO Change Detail
### Network Diagram with Lateral Movement Overlay
@@ -0,0 +1,54 @@
# Standards and Frameworks for AD Compromise Investigation
## NIST SP 800-61 Rev 2 - Computer Security Incident Handling Guide
- Provides incident response lifecycle: Preparation, Detection & Analysis, Containment, Eradication & Recovery, Post-Incident Activity
- AD compromise investigations follow all four phases with emphasis on scoping the identity compromise
## CISA Alert: Detecting and Mitigating Active Directory Compromises
- Published guidance on AD-specific threats and detection methods
- Covers DCSync, Golden Ticket, Silver Ticket, and Kerberoasting attacks
- Recommends tiered administration, Protected Users group, and credential hygiene
- Reference: https://www.cisa.gov/resources-tools/resources/detecting-and-mitigating-active-directory-compromises
## MITRE ATT&CK Framework - Credential Access Tactics
- T1003.006: OS Credential Dumping - DCSync
- T1558.001: Steal or Forge Kerberos Tickets - Golden Ticket
- T1558.002: Steal or Forge Kerberos Tickets - Silver Ticket
- T1558.003: Steal or Forge Kerberos Tickets - Kerberoasting
- T1550.002: Use Alternate Authentication Material - Pass the Hash
- T1484.001: Domain Policy Modification - Group Policy Modification
- T1098: Account Manipulation
## Microsoft Security Best Practices
- Tiered administration model for Active Directory
- Privileged Access Workstations (PAWs) for domain admin tasks
- Microsoft Advanced Threat Analytics (ATA) / Defender for Identity
- LAPS (Local Administrator Password Solution) deployment
- Protected Users security group enforcement
- Reference: https://learn.microsoft.com/en-us/security/privileged-access-workstations/overview
## CIS Benchmarks for Active Directory
- CIS Microsoft Windows Server Benchmark for DC hardening
- Password policy requirements (minimum 14 characters)
- Account lockout policy configuration
- Audit policy settings for security event logging
- GPO security baseline configurations
## SANS FOR500 - Windows Forensic Analysis
- Windows artifact analysis methodology
- Registry analysis for persistence detection
- Event log forensics for authentication tracking
- Timeline analysis techniques for AD compromise
## Semperis Identity Forensics and Incident Response (IFIR)
- AD-specific forensic methodology
- Replication metadata analysis
- Change tracking and rollback capabilities
- Forest recovery procedures
- Reference: https://www.semperis.com/solutions/active-directory-breach-forensics/
## Key Windows Security Event IDs for AD Monitoring
- Microsoft documentation on security auditing events
- Advanced Audit Policy Configuration for DCs
- Kerberos event logging requirements
- Directory Service Access auditing
@@ -0,0 +1,151 @@
# AD Compromise Investigation Workflows
## Workflow 1: Initial Triage and Scoping
```
START: AD Compromise Alert Received
|
v
[Determine Scope of Potential Compromise]
|-- Single account compromised?
|-- Multiple accounts compromised?
|-- Domain controller compromised?
|-- Full domain compromise suspected?
|
v
[Collect Initial Evidence]
|-- Export Security event logs from all DCs
|-- Snapshot AD replication metadata
|-- Export current GPO configurations
|-- Document privileged group memberships
|
v
[Identify Compromised Accounts]
|-- Analyze logon events (4624/4625)
|-- Check for pass-the-hash patterns
|-- Review Kerberos ticket activity
|-- Cross-reference with threat intelligence
|
v
[Determine Attack Timeline]
|-- First known malicious activity
|-- Privilege escalation events
|-- Lateral movement chain
|-- Data access and exfiltration
|
v
[Report Findings and Escalate]
```
## Workflow 2: Kerberos Attack Investigation
```
START: Suspicious Kerberos Activity Detected
|
v
[Analyze Event ID 4768 - TGT Requests]
|-- Normal TGT requests from user workstations?
|-- TGT requests from unusual sources?
|-- Encryption type analysis (AES vs RC4)
|
v
[Analyze Event ID 4769 - Service Ticket Requests]
|-- High volume from single source? --> Kerberoasting
|-- Service tickets without prior TGT? --> Silver Ticket
|-- Unusual service names or SPNs?
|
v
[Check for Golden Ticket Indicators]
|-- TGT lifetime exceeds 10 hours?
|-- TGT for non-existent accounts?
|-- TGT without matching AS-REQ?
|-- krbtgt account age analysis
|
v
[Determine Remediation Actions]
|-- Kerberoasting: Reset affected service account passwords
|-- Golden Ticket: Double-rotate krbtgt password
|-- Silver Ticket: Reset affected service account passwords
|-- All: Review and harden SPN configurations
|
v
END: Remediation Complete + Monitoring Enhanced
```
## Workflow 3: DCSync Attack Investigation
```
START: Replication from Non-DC Source Detected
|
v
[Verify Replication Source]
|-- Is source a legitimate domain controller?
|-- Check Event ID 4662 for replication rights usage
|-- Verify account has DS-Replication-Get-Changes-All
|
v
[If Unauthorized Replication Detected]
|-- Identify compromised account with replication rights
|-- Determine which credentials were replicated
|-- Check for Mimikatz/Impacket artifacts on source
|
v
[Assess Credential Exposure]
|-- All domain password hashes potentially compromised
|-- krbtgt hash exposure enables Golden Ticket
|-- Service account hashes enable Silver Tickets
|-- Trust keys enable cross-domain attacks
|
v
[Execute Full Credential Reset]
|-- Double-rotate krbtgt (wait for replication)
|-- Reset all privileged account passwords
|-- Reset all service account passwords
|-- Force password change for all users
|
v
END: Monitor for Continued Unauthorized Replication
```
## Workflow 4: Post-Compromise Remediation
```
START: Compromise Scope Determined
|
v
[Immediate Containment]
|-- Disable compromised accounts
|-- Block attacker IP addresses
|-- Isolate compromised systems
|-- Revoke active sessions and tokens
|
v
[Credential Reset Sequence]
|-- Step 1: Reset krbtgt (first rotation)
|-- Step 2: Wait for full AD replication
|-- Step 3: Reset krbtgt (second rotation)
|-- Step 4: Wait for full AD replication
|-- Step 5: Reset all privileged accounts
|-- Step 6: Reset all service accounts
|-- Step 7: Force user password changes
|
v
[Persistence Removal]
|-- Remove unauthorized GPO modifications
|-- Clean AdminSDHolder ACL entries
|-- Remove SID History entries
|-- Revoke rogue AD CS certificates
|-- Remove skeleton key if detected
|-- Clean scheduled tasks and services
|
v
[Hardening Implementation]
|-- Deploy tiered administration model
|-- Enable Protected Users group
|-- Implement PAW for admin tasks
|-- Deploy LAPS for local admin
|-- Configure advanced audit policies
|
v
END: Continuous Monitoring Established
```
@@ -0,0 +1,558 @@
"""
Active Directory Compromise Investigation Script
Analyzes Windows Security event logs for indicators of AD compromise
including DCSync, Golden Ticket, Kerberoasting, and lateral movement.
"""
import json
import csv
import os
import re
import xml.etree.ElementTree as ET
from datetime import datetime, timedelta
from collections import defaultdict, Counter
from pathlib import Path
class ADCompromiseInvestigator:
"""Investigates Active Directory compromise through event log analysis."""
# Critical Event IDs for AD investigation
EVENT_IDS = {
4624: "Successful Logon",
4625: "Failed Logon",
4648: "Explicit Credential Logon",
4662: "AD Object Operation",
4768: "Kerberos TGT Request (AS-REQ)",
4769: "Kerberos Service Ticket Request (TGS-REQ)",
4771: "Kerberos Pre-Auth Failed",
4776: "NTLM Credential Validation",
5136: "Directory Object Modified",
5137: "Directory Object Created",
4706: "Trust Created",
4707: "Trust Removed",
4728: "Member Added to Security-Enabled Global Group",
4732: "Member Added to Security-Enabled Local Group",
4756: "Member Added to Security-Enabled Universal Group",
4742: "Computer Account Changed",
8222: "Shadow Copy Created",
}
PRIVILEGED_GROUPS = [
"Domain Admins",
"Enterprise Admins",
"Schema Admins",
"Account Operators",
"Backup Operators",
"DnsAdmins",
"Group Policy Creator Owners",
"Server Operators",
"Print Operators",
"Protected Users",
]
DCSYNC_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
]
def __init__(self, output_dir="ad_investigation_results"):
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
self.findings = []
self.compromised_accounts = set()
self.lateral_movement_chain = []
self.kerberos_anomalies = []
self.privilege_escalations = []
def parse_evtx_xml(self, xml_file):
"""Parse exported Windows event log XML file."""
events = []
try:
tree = ET.parse(xml_file)
root = tree.getroot()
ns = {"ns": "http://schemas.microsoft.com/win/2004/08/events/event"}
for event_elem in root.findall(".//ns:Event", ns):
event = self._extract_event_data(event_elem, ns)
if event:
events.append(event)
except ET.ParseError as e:
print(f"[ERROR] XML parse error in {xml_file}: {e}")
return events
def _extract_event_data(self, event_elem, ns):
"""Extract structured data from an event XML element."""
system = event_elem.find("ns:System", ns)
if system is None:
return None
event_id_elem = system.find("ns:EventID", ns)
time_elem = system.find("ns:TimeCreated", ns)
computer_elem = system.find("ns:Computer", ns)
event = {
"event_id": int(event_id_elem.text) if event_id_elem is not None else 0,
"timestamp": time_elem.get("SystemTime", "") if time_elem is not None else "",
"computer": computer_elem.text if computer_elem is not None else "",
"data": {},
}
event_data = event_elem.find("ns:EventData", ns)
if event_data is not None:
for data in event_data.findall("ns:Data", ns):
name = data.get("Name", "")
value = data.text or ""
event[" data"][name] = value
return event
def analyze_dcsync_activity(self, events):
"""Detect DCSync attacks by analyzing replication permission usage."""
print("[*] Analyzing for DCSync activity...")
dcsync_events = []
for event in events:
if event["event_id"] != 4662:
continue
properties = event["data"].get("Properties", "")
for guid in self.DCSYNC_GUIDS:
if guid.lower() in properties.lower():
subject = event["data"].get("SubjectUserName", "Unknown")
dcsync_events.append({
"timestamp": event["timestamp"],
"account": subject,
"computer": event["computer"],
"guid": guid,
"severity": "CRITICAL",
"description": f"DCSync replication rights used by {subject}",
})
self.compromised_accounts.add(subject)
if dcsync_events:
finding = {
"category": "DCSync Attack",
"severity": "CRITICAL",
"count": len(dcsync_events),
"details": dcsync_events,
"recommendation": "Immediately revoke replication rights from non-DC accounts. "
"Double-rotate krbtgt password. Reset all domain passwords.",
}
self.findings.append(finding)
print(f" [!] CRITICAL: {len(dcsync_events)} DCSync events detected!")
else:
print(" [+] No DCSync activity detected.")
return dcsync_events
def analyze_golden_ticket_indicators(self, events):
"""Detect Golden Ticket usage through Kerberos anomalies."""
print("[*] Analyzing for Golden Ticket indicators...")
golden_ticket_indicators = []
tgt_requests = {}
service_tickets = []
for event in events:
if event["event_id"] == 4768:
account = event["data"].get("TargetUserName", "")
tgt_requests[account] = event
elif event["event_id"] == 4769:
service_tickets.append(event)
for ticket in service_tickets:
account = ticket["data"].get("TargetUserName", "")
encryption = ticket["data"].get("TicketEncryptionType", "")
# RC4 encryption (0x17) when AES should be used indicates forged ticket
if encryption == "0x17":
golden_ticket_indicators.append({
"timestamp": ticket["timestamp"],
"account": account,
"indicator": "RC4 encryption on service ticket (should be AES)",
"encryption_type": encryption,
"severity": "HIGH",
})
# Service ticket without corresponding TGT request
if account and account not in tgt_requests:
golden_ticket_indicators.append({
"timestamp": ticket["timestamp"],
"account": account,
"indicator": "Service ticket without matching TGT request",
"severity": "CRITICAL",
})
if golden_ticket_indicators:
finding = {
"category": "Golden Ticket Indicators",
"severity": "CRITICAL",
"count": len(golden_ticket_indicators),
"details": golden_ticket_indicators,
"recommendation": "Double-rotate krbtgt password immediately. "
"Wait for full replication between rotations.",
}
self.findings.append(finding)
print(f" [!] CRITICAL: {len(golden_ticket_indicators)} Golden Ticket indicators!")
else:
print(" [+] No Golden Ticket indicators detected.")
return golden_ticket_indicators
def analyze_kerberoasting(self, events):
"""Detect Kerberoasting by analyzing bulk service ticket requests."""
print("[*] Analyzing for Kerberoasting activity...")
tgs_requests_by_source = defaultdict(list)
for event in events:
if event["event_id"] != 4769:
continue
source_ip = event["data"].get("IpAddress", "")
service_name = event["data"].get("ServiceName", "")
encryption = event["data"].get("TicketEncryptionType", "")
account = event["data"].get("TargetUserName", "")
if service_name and not service_name.endswith("$"):
tgs_requests_by_source[source_ip].append({
"timestamp": event["timestamp"],
"service": service_name,
"account": account,
"encryption": encryption,
})
kerberoasting_sources = []
for source_ip, requests in tgs_requests_by_source.items():
# Threshold: more than 5 unique service tickets in short timeframe
unique_services = set(r["service"] for r in requests)
if len(unique_services) >= 5:
kerberoasting_sources.append({
"source_ip": source_ip,
"unique_services_requested": len(unique_services),
"total_requests": len(requests),
"services": list(unique_services)[:20],
"severity": "HIGH",
})
if kerberoasting_sources:
finding = {
"category": "Kerberoasting Activity",
"severity": "HIGH",
"count": len(kerberoasting_sources),
"details": kerberoasting_sources,
"recommendation": "Reset passwords of targeted service accounts. "
"Use Group Managed Service Accounts (gMSA) where possible. "
"Enforce long, complex passwords on service accounts.",
}
self.findings.append(finding)
print(f" [!] HIGH: {len(kerberoasting_sources)} sources performing Kerberoasting!")
else:
print(" [+] No Kerberoasting activity detected.")
return kerberoasting_sources
def analyze_pass_the_hash(self, events):
"""Detect Pass-the-Hash through NTLM logon analysis."""
print("[*] Analyzing for Pass-the-Hash indicators...")
pth_indicators = []
for event in events:
if event["event_id"] != 4624:
continue
logon_type = event["data"].get("LogonType", "")
auth_package = event["data"].get("AuthenticationPackageName", "")
logon_process = event["data"].get("LogonProcessName", "")
# Type 3 (Network) + NTLM + NtLmSsp = potential PtH
if logon_type == "3" and "NTLM" in auth_package and "NtLmSsp" in logon_process:
account = event["data"].get("TargetUserName", "")
source_ip = event["data"].get("IpAddress", "")
workstation = event["data"].get("WorkstationName", "")
pth_indicators.append({
"timestamp": event["timestamp"],
"account": account,
"source_ip": source_ip,
"workstation": workstation,
"severity": "HIGH",
"description": f"NTLM network logon from {source_ip} as {account}",
})
if pth_indicators:
finding = {
"category": "Pass-the-Hash Indicators",
"severity": "HIGH",
"count": len(pth_indicators),
"details": pth_indicators[:50],
"recommendation": "Enable Credential Guard. Enforce NTLMv2 only. "
"Add privileged accounts to Protected Users group. "
"Implement tiered administration.",
}
self.findings.append(finding)
print(f" [!] HIGH: {len(pth_indicators)} Pass-the-Hash indicators detected!")
else:
print(" [+] No Pass-the-Hash indicators detected.")
return pth_indicators
def analyze_privilege_escalation(self, events):
"""Detect unauthorized additions to privileged groups."""
print("[*] Analyzing for privilege escalation via group membership...")
escalations = []
group_change_events = [4728, 4732, 4756]
for event in events:
if event["event_id"] not in group_change_events:
continue
group_name = event["data"].get("TargetUserName", "")
member_added = event["data"].get("MemberName", "")
changed_by = event["data"].get("SubjectUserName", "")
for priv_group in self.PRIVILEGED_GROUPS:
if priv_group.lower() in group_name.lower():
escalations.append({
"timestamp": event["timestamp"],
"group": group_name,
"member_added": member_added,
"changed_by": changed_by,
"computer": event["computer"],
"severity": "CRITICAL",
})
self.privilege_escalations = escalations
if escalations:
finding = {
"category": "Privileged Group Modification",
"severity": "CRITICAL",
"count": len(escalations),
"details": escalations,
"recommendation": "Review all privileged group membership changes. "
"Remove unauthorized members. Audit AdminSDHolder.",
}
self.findings.append(finding)
print(f" [!] CRITICAL: {len(escalations)} privileged group modifications!")
else:
print(" [+] No suspicious privileged group modifications detected.")
return escalations
def analyze_lateral_movement(self, events):
"""Map lateral movement chains through authentication patterns."""
print("[*] Analyzing lateral movement patterns...")
auth_chain = defaultdict(lambda: defaultdict(set))
for event in events:
if event["event_id"] != 4624:
continue
logon_type = event["data"].get("LogonType", "")
if logon_type not in ("3", "10"):
continue
account = event["data"].get("TargetUserName", "")
source_ip = event["data"].get("IpAddress", "")
target = event["computer"]
if source_ip and account and not account.endswith("$"):
auth_chain[account][source_ip].add(target)
movement_paths = []
for account, sources in auth_chain.items():
for source_ip, targets in sources.items():
if len(targets) >= 3:
movement_paths.append({
"account": account,
"source_ip": source_ip,
"targets_accessed": list(targets),
"target_count": len(targets),
"severity": "HIGH" if len(targets) >= 5 else "MEDIUM",
})
if movement_paths:
finding = {
"category": "Lateral Movement Patterns",
"severity": "HIGH",
"count": len(movement_paths),
"details": sorted(movement_paths, key=lambda x: x["target_count"], reverse=True)[:20],
"recommendation": "Investigate accounts with wide lateral movement. "
"Implement network segmentation. Enable credential guard.",
}
self.findings.append(finding)
print(f" [!] HIGH: {len(movement_paths)} lateral movement patterns detected!")
else:
print(" [+] No significant lateral movement patterns detected.")
return movement_paths
def analyze_gpo_modifications(self, events):
"""Detect suspicious Group Policy Object modifications."""
print("[*] Analyzing GPO modifications...")
gpo_changes = []
for event in events:
if event["event_id"] != 5136:
continue
object_class = event["data"].get("ObjectClass", "")
if "grouppolicycontainer" in object_class.lower():
changed_by = event["data"].get("SubjectUserName", "")
attribute = event["data"].get("AttributeLDAPDisplayName", "")
value = event["data"].get("AttributeValue", "")
gpo_changes.append({
"timestamp": event["timestamp"],
"changed_by": changed_by,
"attribute": attribute,
"value": value[:200],
"computer": event["computer"],
"severity": "HIGH",
})
if gpo_changes:
finding = {
"category": "GPO Modifications",
"severity": "HIGH",
"count": len(gpo_changes),
"details": gpo_changes,
"recommendation": "Review all GPO changes for unauthorized modifications. "
"Check for malicious scheduled tasks, login scripts, "
"or software installation policies.",
}
self.findings.append(finding)
print(f" [!] HIGH: {len(gpo_changes)} GPO modifications detected!")
else:
print(" [+] No GPO modifications detected.")
return gpo_changes
def generate_report(self):
"""Generate comprehensive investigation report."""
report = {
"investigation_report": "Active Directory Compromise Investigation",
"generated_at": datetime.utcnow().isoformat(),
"summary": {
"total_findings": len(self.findings),
"critical_findings": sum(1 for f in self.findings if f["severity"] == "CRITICAL"),
"high_findings": sum(1 for f in self.findings if f["severity"] == "HIGH"),
"compromised_accounts": list(self.compromised_accounts),
},
"findings": self.findings,
"recommendations": self._generate_recommendations(),
}
report_path = self.output_dir / "ad_investigation_report.json"
with open(report_path, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"\n[+] Report saved to {report_path}")
self._print_summary(report)
return report
def _generate_recommendations(self):
"""Generate prioritized remediation recommendations."""
recommendations = []
has_critical = any(f["severity"] == "CRITICAL" for f in self.findings)
if has_critical:
recommendations.append({
"priority": 1,
"action": "Double-rotate krbtgt password",
"detail": "Reset krbtgt twice with full AD replication between rotations. "
"This invalidates all Kerberos tickets including Golden Tickets.",
})
recommendations.append({
"priority": 2,
"action": "Reset all privileged account passwords",
"detail": "Reset passwords for Domain Admins, Enterprise Admins, "
"and all service accounts with SPNs.",
})
if self.compromised_accounts:
recommendations.append({
"priority": 3,
"action": "Disable and investigate compromised accounts",
"detail": f"Accounts to investigate: {', '.join(self.compromised_accounts)}",
})
recommendations.extend([
{
"priority": 4,
"action": "Implement tiered administration model",
"detail": "Separate Tier 0 (AD), Tier 1 (servers), Tier 2 (workstations) "
"with no credential reuse across tiers.",
},
{
"priority": 5,
"action": "Deploy advanced monitoring",
"detail": "Enable Microsoft Defender for Identity or equivalent. "
"Configure advanced audit policies on all DCs.",
},
])
return recommendations
def _print_summary(self, report):
"""Print investigation summary to console."""
summary = report["summary"]
print("\n" + "=" * 60)
print("AD COMPROMISE INVESTIGATION SUMMARY")
print("=" * 60)
print(f"Total Findings: {summary['total_findings']}")
print(f"Critical: {summary['critical_findings']}")
print(f"High: {summary['high_findings']}")
print(f"Compromised Accounts: {len(summary['compromised_accounts'])}")
if summary["compromised_accounts"]:
for account in summary["compromised_accounts"]:
print(f" - {account}")
print("=" * 60)
def run_full_investigation(self, event_log_files):
"""Run complete AD compromise investigation."""
print("[*] Starting Active Directory Compromise Investigation")
print(f"[*] Processing {len(event_log_files)} event log files...")
all_events = []
for log_file in event_log_files:
events = self.parse_evtx_xml(log_file)
all_events.extend(events)
print(f" Parsed {len(events)} events from {log_file}")
print(f"[*] Total events to analyze: {len(all_events)}")
self.analyze_dcsync_activity(all_events)
self.analyze_golden_ticket_indicators(all_events)
self.analyze_kerberoasting(all_events)
self.analyze_pass_the_hash(all_events)
self.analyze_privilege_escalation(all_events)
self.analyze_lateral_movement(all_events)
self.analyze_gpo_modifications(all_events)
return self.generate_report()
def main():
import argparse
parser = argparse.ArgumentParser(
description="Active Directory Compromise Investigation Tool"
)
parser.add_argument(
"log_files",
nargs="+",
help="Windows Security event log XML files to analyze",
)
parser.add_argument(
"-o", "--output",
default="ad_investigation_results",
help="Output directory for investigation results",
)
args = parser.parse_args()
investigator = ADCompromiseInvestigator(output_dir=args.output)
report = investigator.run_full_investigation(args.log_files)
if report["summary"]["critical_findings"] > 0:
print("\n[!!!] CRITICAL FINDINGS DETECTED - IMMEDIATE ACTION REQUIRED")
exit(1)
if __name__ == "__main__":
main()