mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-01 16:47:42 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
---
|
||||
name: performing-active-directory-vulnerability-assessment
|
||||
description: Assess Active Directory security posture using PingCastle, BloodHound, and Purple Knight to identify misconfigurations, privilege escalation paths, and attack vectors.
|
||||
domain: cybersecurity
|
||||
subdomain: vulnerability-management
|
||||
tags: [active-directory, pingcastle, bloodhound, purple-knight, ad-security, privilege-escalation, ldap, kerberos]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Performing Active Directory Vulnerability Assessment
|
||||
|
||||
## Overview
|
||||
|
||||
Active Directory (AD) is the primary identity and access management system in most enterprise environments, making it a critical attack target. This skill covers comprehensive AD security assessment using PingCastle for health checks, BloodHound for attack path analysis, and Purple Knight for security posture scoring. These tools identify misconfigurations, excessive privileges, Kerberos weaknesses, and lateral movement opportunities.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Domain-joined workstation or domain admin access for scanning
|
||||
- PingCastle (https://github.com/netwrix/pingcastle)
|
||||
- BloodHound Community Edition with SharpHound collector
|
||||
- Purple Knight from Semperis (free community tool)
|
||||
- Python 3.9+ for analysis scripts
|
||||
- .NET Framework 4.7+ for PingCastle on Windows
|
||||
|
||||
## Tool 1: PingCastle Health Check
|
||||
|
||||
### Installation and Execution
|
||||
```powershell
|
||||
# Download PingCastle
|
||||
Invoke-WebRequest -Uri "https://github.com/netwrix/pingcastle/releases/latest/download/PingCastle.zip" `
|
||||
-OutFile "PingCastle.zip"
|
||||
Expand-Archive PingCastle.zip -DestinationPath C:\Tools\PingCastle
|
||||
|
||||
# Run health check against current domain
|
||||
cd C:\Tools\PingCastle
|
||||
.\PingCastle.exe --healthcheck
|
||||
|
||||
# Run health check against specific domain
|
||||
.\PingCastle.exe --healthcheck --server dc01.corp.local --user CORP\scanner_account --password P@ssw0rd
|
||||
|
||||
# Run in scanner mode for multiple domains
|
||||
.\PingCastle.exe --scanner --scannerlp
|
||||
|
||||
# Generate consolidated report
|
||||
.\PingCastle.exe --healthcheck --level Full
|
||||
```
|
||||
|
||||
### PingCastle Scoring Categories
|
||||
|
||||
| Category | Description | Risk Areas |
|
||||
|----------|------------|------------|
|
||||
| **Stale Objects** | Inactive accounts, old passwords, obsolete OS | Ghost accounts, expired credentials |
|
||||
| **Privileged Accounts** | Excessive admin rights, nested groups | Domain Admin sprawl, SID history |
|
||||
| **Trusts** | Forest and domain trust configurations | Transitive trust abuse, SID filtering |
|
||||
| **Anomalies** | Security setting deviations | GPO misconfigurations, schema issues |
|
||||
|
||||
### Key PingCastle Checks
|
||||
```
|
||||
# Critical items to review in PingCastle report:
|
||||
- Accounts with "Password Never Expires" flag
|
||||
- Accounts with Kerberos pre-authentication disabled (AS-REP roastable)
|
||||
- Accounts with Kerberos delegation (unconstrained/constrained)
|
||||
- Domain Controllers running unsupported OS versions
|
||||
- AdminSDHolder permission modifications
|
||||
- Accounts in privileged groups (Domain Admins, Enterprise Admins, Schema Admins)
|
||||
- Trust relationships with SID filtering disabled
|
||||
- GPO vulnerabilities allowing privilege escalation
|
||||
```
|
||||
|
||||
## Tool 2: BloodHound Attack Path Analysis
|
||||
|
||||
### SharpHound Data Collection
|
||||
```powershell
|
||||
# Download SharpHound collector
|
||||
# https://github.com/SpecterOps/BloodHound/tree/main/packages/csharp/SharpHound
|
||||
|
||||
# Run SharpHound collection (all methods)
|
||||
.\SharpHound.exe --collectionmethods All --domain corp.local --zipfilename bloodhound_data.zip
|
||||
|
||||
# Stealthy collection (minimal noise)
|
||||
.\SharpHound.exe --collectionmethods Session,LoggedOn --domain corp.local --stealth
|
||||
|
||||
# Collection with specific domain controller
|
||||
.\SharpHound.exe --collectionmethods All --domain corp.local --domaincontroller dc01.corp.local
|
||||
|
||||
# Run via PowerShell
|
||||
Import-Module .\SharpHound.ps1
|
||||
Invoke-BloodHound -CollectionMethod All -Domain corp.local -OutputDirectory C:\BH_Data
|
||||
```
|
||||
|
||||
### BloodHound CE Setup
|
||||
```bash
|
||||
# Deploy BloodHound Community Edition with Docker
|
||||
curl -L https://ghst.ly/getbhce -o docker-compose.yml
|
||||
docker compose up -d
|
||||
|
||||
# Access BloodHound CE at http://localhost:8080
|
||||
# Default credentials shown in docker compose logs
|
||||
|
||||
# Upload SharpHound data through web UI or API
|
||||
curl -X POST "http://localhost:8080/api/v2/file-upload/start" \
|
||||
-H "Authorization: Bearer $BH_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"fileName": "bloodhound_data.zip"}'
|
||||
```
|
||||
|
||||
### Critical BloodHound Queries
|
||||
```cypher
|
||||
# Find shortest path to Domain Admin
|
||||
MATCH p=shortestPath((u:User)-[*1..]->(g:Group {name:"DOMAIN ADMINS@CORP.LOCAL"}))
|
||||
WHERE u.name <> "ADMINISTRATOR@CORP.LOCAL"
|
||||
RETURN p
|
||||
|
||||
# Find Kerberoastable accounts with admin privileges
|
||||
MATCH (u:User {hasspn:true})-[:MemberOf*1..]->(g:Group)
|
||||
WHERE g.name CONTAINS "ADMIN"
|
||||
RETURN u.name, u.serviceprincipalnames
|
||||
|
||||
# Find computers where Domain Admins are logged in
|
||||
MATCH (c:Computer)-[:HasSession]->(u:User)-[:MemberOf*1..]->(g:Group {name:"DOMAIN ADMINS@CORP.LOCAL"})
|
||||
RETURN c.name, u.name
|
||||
|
||||
# Find AS-REP roastable accounts
|
||||
MATCH (u:User {dontreqpreauth:true})
|
||||
RETURN u.name, u.description
|
||||
|
||||
# Find unconstrained delegation hosts
|
||||
MATCH (c:Computer {unconstraineddelegation:true})
|
||||
WHERE NOT c.name CONTAINS "DC"
|
||||
RETURN c.name
|
||||
|
||||
# Find GPO abuse paths
|
||||
MATCH p=(u:User)-[:GenericAll|GenericWrite|WriteOwner|WriteDacl]->(g:GPO)
|
||||
RETURN p
|
||||
```
|
||||
|
||||
## Tool 3: Purple Knight Assessment
|
||||
|
||||
```powershell
|
||||
# Download Purple Knight from https://www.purple-knight.com/
|
||||
# Run as domain admin or with appropriate read permissions
|
||||
|
||||
.\PurpleKnight.exe
|
||||
|
||||
# Purple Knight checks 130+ security indicators across:
|
||||
# - Account Security (password policies, privileged accounts)
|
||||
# - AD Infrastructure (replication, DNS, LDAP signing)
|
||||
# - Group Policy (GPO permissions, security settings)
|
||||
# - Kerberos Security (delegation, encryption types, SPN)
|
||||
# - AD Delegation (AdminSDHolder, OU permissions)
|
||||
```
|
||||
|
||||
### Purple Knight Score Categories
|
||||
| Score Range | Rating | Action Required |
|
||||
|------------|--------|----------------|
|
||||
| 90-100 | Excellent | Maintain current posture |
|
||||
| 75-89 | Good | Address high-risk findings |
|
||||
| 60-74 | Fair | Prioritize remediation plan |
|
||||
| 40-59 | Poor | Immediate remediation required |
|
||||
| 0-39 | Critical | Emergency response needed |
|
||||
|
||||
## Common AD Vulnerabilities
|
||||
|
||||
### 1. Kerberoasting Exposure
|
||||
```powershell
|
||||
# Find SPNs assigned to user accounts (Kerberoasting targets)
|
||||
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName |
|
||||
Select-Object Name, ServicePrincipalName, PasswordLastSet, Enabled
|
||||
```
|
||||
|
||||
### 2. AS-REP Roasting Exposure
|
||||
```powershell
|
||||
# Find accounts with pre-auth disabled
|
||||
Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} -Properties DoesNotRequirePreAuth |
|
||||
Select-Object Name, DoesNotRequirePreAuth, Enabled
|
||||
```
|
||||
|
||||
### 3. LLMNR/NBT-NS Poisoning Risk
|
||||
```powershell
|
||||
# Check if LLMNR is disabled via GPO
|
||||
Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" -Name EnableMulticast -ErrorAction SilentlyContinue
|
||||
```
|
||||
|
||||
### 4. Excessive Privileged Group Membership
|
||||
```powershell
|
||||
# Count members in critical groups
|
||||
$groups = @("Domain Admins", "Enterprise Admins", "Schema Admins", "Account Operators", "Backup Operators")
|
||||
foreach ($group in $groups) {
|
||||
$count = (Get-ADGroupMember -Identity $group -Recursive).Count
|
||||
Write-Output "$group : $count members"
|
||||
}
|
||||
```
|
||||
|
||||
## Remediation Priorities
|
||||
|
||||
| Finding | Risk | Remediation |
|
||||
|---------|------|-------------|
|
||||
| Kerberoastable admin accounts | Critical | Remove SPNs or use MSA/gMSA |
|
||||
| Unconstrained delegation on non-DCs | Critical | Switch to constrained/RBCD |
|
||||
| Password Never Expires on admins | High | Enable password rotation policy |
|
||||
| AS-REP roastable accounts | High | Enable Kerberos pre-authentication |
|
||||
| AdminSDHolder modification | High | Audit and restore default ACLs |
|
||||
| Stale computer accounts (90+ days) | Medium | Disable and move to quarantine OU |
|
||||
| LDAP signing not enforced | Medium | Enable via GPO on all DCs |
|
||||
|
||||
## References
|
||||
|
||||
- [PingCastle GitHub](https://github.com/netwrix/pingcastle)
|
||||
- [BloodHound CE](https://github.com/SpecterOps/BloodHound)
|
||||
- [Purple Knight](https://www.purple-knight.com/)
|
||||
- [MITRE ATT&CK - Active Directory](https://attack.mitre.org/techniques/T1484/)
|
||||
- [Microsoft AD Security Best Practices](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory)
|
||||
@@ -0,0 +1,63 @@
|
||||
# Active Directory Security Assessment Checklist
|
||||
|
||||
## Pre-Assessment Preparation
|
||||
- [ ] Obtain written authorization for AD security assessment
|
||||
- [ ] Identify domain controllers and AD forest/domain topology
|
||||
- [ ] Create dedicated scan account with Domain Admin read access
|
||||
- [ ] Document assessment scope (domains, OUs, forests)
|
||||
- [ ] Schedule assessment during maintenance window if using active scanning
|
||||
|
||||
## PingCastle Assessment
|
||||
- [ ] Run PingCastle --healthcheck against all in-scope domains
|
||||
- [ ] Review overall score and category breakdown
|
||||
- [ ] Document all findings with points >= 10
|
||||
- [ ] Export report as XML for automated processing
|
||||
- [ ] Check trust relationship security
|
||||
- [ ] Verify AdminSDHolder integrity
|
||||
|
||||
## BloodHound Assessment
|
||||
- [ ] Deploy SharpHound collector
|
||||
- [ ] Run full collection (All methods)
|
||||
- [ ] Upload data to BloodHound CE
|
||||
- [ ] Run shortest path to Domain Admin queries
|
||||
- [ ] Identify Kerberoastable admin accounts
|
||||
- [ ] Map unconstrained delegation hosts
|
||||
- [ ] Check for AS-REP roastable accounts
|
||||
- [ ] Analyze GPO abuse paths
|
||||
- [ ] Document all attack paths with 3 or fewer hops
|
||||
|
||||
## Purple Knight Assessment
|
||||
- [ ] Run Purple Knight community edition
|
||||
- [ ] Review score across all five categories
|
||||
- [ ] Document indicators below 75% score threshold
|
||||
|
||||
## Critical Findings Checklist
|
||||
|
||||
### Kerberos Security
|
||||
- [ ] No user accounts with SPNs in admin groups (Kerberoasting)
|
||||
- [ ] Kerberos pre-authentication enabled for all accounts
|
||||
- [ ] No unconstrained delegation on non-DC computers
|
||||
- [ ] AES-256 encryption enabled; RC4 and DES disabled
|
||||
- [ ] Kerberos ticket lifetime <= 10 hours
|
||||
|
||||
### Privileged Accounts
|
||||
- [ ] Domain Admins group has <= 5 members
|
||||
- [ ] Enterprise Admins group has <= 3 members
|
||||
- [ ] Schema Admins group is empty (only populated during schema changes)
|
||||
- [ ] All admin accounts have password expiration enabled
|
||||
- [ ] Protected Users group configured for Tier 0 accounts
|
||||
- [ ] Tiered admin model implemented (Tier 0/1/2)
|
||||
|
||||
### Password Policy
|
||||
- [ ] Minimum password length >= 14 characters
|
||||
- [ ] Password history >= 24 passwords
|
||||
- [ ] Account lockout threshold set (10-15 attempts)
|
||||
- [ ] Fine-grained password policy for admin accounts (25+ chars)
|
||||
|
||||
### Infrastructure Security
|
||||
- [ ] LDAP signing required on all domain controllers
|
||||
- [ ] LDAP channel binding set to Required
|
||||
- [ ] SMB signing required on DCs
|
||||
- [ ] NTLMv2 only (LM and NTLMv1 disabled)
|
||||
- [ ] All DCs running supported OS versions
|
||||
- [ ] LAPS deployed for local admin passwords
|
||||
@@ -0,0 +1,41 @@
|
||||
# Standards and References - AD Vulnerability Assessment
|
||||
|
||||
## Primary Standards
|
||||
|
||||
### MITRE ATT&CK - Active Directory Techniques
|
||||
- **URL**: https://attack.mitre.org/
|
||||
- **Key Techniques**:
|
||||
- T1558.003 - Kerberoasting
|
||||
- T1558.004 - AS-REP Roasting
|
||||
- T1557.001 - LLMNR/NBT-NS Poisoning
|
||||
- T1484.001 - Group Policy Modification
|
||||
- T1134.005 - SID-History Injection
|
||||
- T1003.006 - DCSync
|
||||
|
||||
### CIS Benchmark for Active Directory
|
||||
- **URL**: https://www.cisecurity.org/benchmark/active_directory
|
||||
- **Relevance**: Provides prescriptive hardening guidance for AD configuration
|
||||
|
||||
### Microsoft Security Compliance Toolkit
|
||||
- **URL**: https://www.microsoft.com/en-us/download/details.aspx?id=55319
|
||||
- **Relevance**: Baseline GPO settings for domain controllers and member servers
|
||||
|
||||
### NIST SP 800-63B
|
||||
- **Title**: Digital Identity Guidelines - Authentication and Lifecycle Management
|
||||
- **URL**: https://pages.nist.gov/800-63-3/sp800-63b.html
|
||||
- **Relevance**: Password policy requirements applicable to AD accounts
|
||||
|
||||
### NSA Active Directory Security Guidance
|
||||
- **Title**: Detecting and Preventing Active Directory Attacks
|
||||
- **Relevance**: NSA recommendations for securing AD against common attack techniques
|
||||
|
||||
## Tools
|
||||
|
||||
| Tool | License | URL |
|
||||
|------|---------|-----|
|
||||
| PingCastle | Open Source (Netwrix) | https://github.com/netwrix/pingcastle |
|
||||
| BloodHound CE | Apache 2.0 | https://github.com/SpecterOps/BloodHound |
|
||||
| SharpHound | Apache 2.0 | https://github.com/SpecterOps/BloodHound |
|
||||
| Purple Knight | Free Community | https://www.purple-knight.com/ |
|
||||
| ADRecon | MIT | https://github.com/adrecon/ADRecon |
|
||||
| Testimo | MIT | https://github.com/EvotecIT/Testimo |
|
||||
@@ -0,0 +1,45 @@
|
||||
# Workflows - AD Vulnerability Assessment
|
||||
|
||||
## Workflow 1: Comprehensive AD Security Assessment
|
||||
|
||||
### Steps
|
||||
1. Run PingCastle health check to get overall AD security score
|
||||
2. Review PingCastle report for stale objects, privilege issues, trust problems, and anomalies
|
||||
3. Run SharpHound data collection against the domain
|
||||
4. Upload SharpHound data to BloodHound CE
|
||||
5. Execute critical BloodHound queries (shortest path to DA, Kerberoastable admins, delegation issues)
|
||||
6. Run Purple Knight for additional security indicator checks
|
||||
7. Consolidate findings from all three tools into unified report
|
||||
8. Prioritize findings by risk severity and attack path impact
|
||||
9. Generate remediation plan with specific PowerShell/GPO fix commands
|
||||
|
||||
## Workflow 2: Attack Path Remediation
|
||||
|
||||
### Steps
|
||||
1. Identify top 5 shortest attack paths to Domain Admin from BloodHound
|
||||
2. For each path, determine the weakest link (misconfigured ACL, session reuse, etc.)
|
||||
3. Remediate weakest links to break attack paths
|
||||
4. Re-run BloodHound collection to verify paths are eliminated
|
||||
5. Document remediated paths and remaining risk
|
||||
|
||||
## Workflow 3: Privileged Account Hardening
|
||||
|
||||
### Steps
|
||||
1. Export all members of privileged groups from PingCastle report
|
||||
2. Validate each account has legitimate business need for privilege
|
||||
3. Remove unnecessary privileged group memberships
|
||||
4. Implement tiered administration model (Tier 0/1/2)
|
||||
5. Enable Protected Users group for sensitive accounts
|
||||
6. Configure AdminSDHolder with correct ACLs
|
||||
7. Verify changes with follow-up PingCastle scan
|
||||
|
||||
## Workflow 4: Kerberos Security Hardening
|
||||
|
||||
### Steps
|
||||
1. Identify all Kerberoastable accounts from BloodHound
|
||||
2. Convert user-assigned SPNs to Managed Service Accounts (MSA/gMSA) where possible
|
||||
3. For remaining SPNs, ensure 25+ character passwords with rotation
|
||||
4. Disable DES and RC4 encryption for Kerberos
|
||||
5. Enable AES-256 encryption for all accounts
|
||||
6. Enable Kerberos pre-authentication for all accounts
|
||||
7. Configure constrained delegation to replace unconstrained delegation
|
||||
@@ -0,0 +1,211 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Active Directory Vulnerability Assessment Analyzer.
|
||||
|
||||
Parses PingCastle and BloodHound output to generate consolidated
|
||||
AD security assessment reports with prioritized remediation actions.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import csv
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
RISK_WEIGHTS = {
|
||||
"kerberoastable_admin": 10,
|
||||
"unconstrained_delegation": 9,
|
||||
"as_rep_roastable": 8,
|
||||
"password_never_expires_admin": 8,
|
||||
"adminsdholder_modified": 8,
|
||||
"dcsync_non_dc": 9,
|
||||
"gpo_abuse_path": 7,
|
||||
"stale_admin_account": 6,
|
||||
"ldap_signing_disabled": 6,
|
||||
"ntlm_not_restricted": 5,
|
||||
"excessive_domain_admins": 7,
|
||||
"sid_history_present": 6,
|
||||
"trust_sid_filtering_disabled": 7,
|
||||
"unsupported_os_dc": 9,
|
||||
"password_policy_weak": 5,
|
||||
}
|
||||
|
||||
|
||||
def parse_pingcastle_xml(xml_path):
|
||||
"""Parse PingCastle HTML/XML health check report."""
|
||||
findings = []
|
||||
try:
|
||||
tree = ET.parse(xml_path)
|
||||
root = tree.getroot()
|
||||
for risk in root.iter("RiskRule"):
|
||||
finding = {
|
||||
"source": "PingCastle",
|
||||
"category": risk.findtext("Category", ""),
|
||||
"rule_id": risk.findtext("RiskId", ""),
|
||||
"title": risk.findtext("Rationale", ""),
|
||||
"description": risk.findtext("Detail", ""),
|
||||
"points": int(risk.findtext("Points", "0")),
|
||||
}
|
||||
findings.append(finding)
|
||||
except ET.ParseError:
|
||||
print(f"[-] Could not parse PingCastle XML: {xml_path}")
|
||||
print(" Try exporting PingCastle results as XML format")
|
||||
return findings
|
||||
|
||||
|
||||
def parse_bloodhound_json(json_path):
|
||||
"""Parse BloodHound CE exported data for critical findings."""
|
||||
findings = []
|
||||
with open(json_path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
if isinstance(data, dict):
|
||||
nodes = data.get("nodes", [])
|
||||
edges = data.get("edges", [])
|
||||
elif isinstance(data, list):
|
||||
nodes = data
|
||||
edges = []
|
||||
else:
|
||||
return findings
|
||||
|
||||
for node in nodes:
|
||||
props = node.get("properties", node.get("Properties", {}))
|
||||
kind = node.get("kind", node.get("label", ""))
|
||||
|
||||
if kind == "User":
|
||||
if props.get("hasspn", False) and props.get("admincount", False):
|
||||
findings.append({
|
||||
"source": "BloodHound",
|
||||
"category": "Kerberos",
|
||||
"rule_id": "kerberoastable_admin",
|
||||
"title": f"Kerberoastable admin account: {props.get('name', 'unknown')}",
|
||||
"description": f"User {props.get('name')} has SPN set and is in admin group",
|
||||
"risk_weight": RISK_WEIGHTS["kerberoastable_admin"],
|
||||
})
|
||||
if props.get("dontreqpreauth", False):
|
||||
findings.append({
|
||||
"source": "BloodHound",
|
||||
"category": "Kerberos",
|
||||
"rule_id": "as_rep_roastable",
|
||||
"title": f"AS-REP roastable account: {props.get('name', 'unknown')}",
|
||||
"description": f"User {props.get('name')} has Kerberos pre-auth disabled",
|
||||
"risk_weight": RISK_WEIGHTS["as_rep_roastable"],
|
||||
})
|
||||
if props.get("pwdneverexpires", False) and props.get("admincount", False):
|
||||
findings.append({
|
||||
"source": "BloodHound",
|
||||
"category": "Privileged Accounts",
|
||||
"rule_id": "password_never_expires_admin",
|
||||
"title": f"Admin with non-expiring password: {props.get('name', 'unknown')}",
|
||||
"description": f"Privileged user {props.get('name')} has password set to never expire",
|
||||
"risk_weight": RISK_WEIGHTS["password_never_expires_admin"],
|
||||
})
|
||||
|
||||
elif kind == "Computer":
|
||||
if props.get("unconstraineddelegation", False):
|
||||
name = props.get("name", "unknown")
|
||||
if "DC" not in name.upper():
|
||||
findings.append({
|
||||
"source": "BloodHound",
|
||||
"category": "Kerberos",
|
||||
"rule_id": "unconstrained_delegation",
|
||||
"title": f"Unconstrained delegation on non-DC: {name}",
|
||||
"description": f"Computer {name} has unconstrained delegation enabled",
|
||||
"risk_weight": RISK_WEIGHTS["unconstrained_delegation"],
|
||||
})
|
||||
|
||||
return findings
|
||||
|
||||
|
||||
def consolidate_findings(pingcastle_findings, bloodhound_findings):
|
||||
"""Merge and deduplicate findings from multiple tools."""
|
||||
all_findings = pingcastle_findings + bloodhound_findings
|
||||
|
||||
for finding in all_findings:
|
||||
if "risk_weight" not in finding:
|
||||
points = finding.get("points", 0)
|
||||
if points >= 30:
|
||||
finding["risk_weight"] = 10
|
||||
elif points >= 20:
|
||||
finding["risk_weight"] = 8
|
||||
elif points >= 10:
|
||||
finding["risk_weight"] = 6
|
||||
elif points >= 5:
|
||||
finding["risk_weight"] = 4
|
||||
else:
|
||||
finding["risk_weight"] = 2
|
||||
|
||||
rule_id = finding.get("rule_id", "")
|
||||
if rule_id in RISK_WEIGHTS:
|
||||
finding["risk_weight"] = max(finding["risk_weight"], RISK_WEIGHTS[rule_id])
|
||||
|
||||
all_findings.sort(key=lambda f: f.get("risk_weight", 0), reverse=True)
|
||||
return all_findings
|
||||
|
||||
|
||||
def generate_report(findings, output_path):
|
||||
"""Generate consolidated AD assessment report."""
|
||||
report = {
|
||||
"generated_at": datetime.now(timezone.utc).isoformat(),
|
||||
"total_findings": len(findings),
|
||||
"critical": len([f for f in findings if f.get("risk_weight", 0) >= 9]),
|
||||
"high": len([f for f in findings if 7 <= f.get("risk_weight", 0) < 9]),
|
||||
"medium": len([f for f in findings if 4 <= f.get("risk_weight", 0) < 7]),
|
||||
"low": len([f for f in findings if f.get("risk_weight", 0) < 4]),
|
||||
"findings": findings,
|
||||
"categories": {},
|
||||
}
|
||||
|
||||
for f in findings:
|
||||
cat = f.get("category", "Other")
|
||||
if cat not in report["categories"]:
|
||||
report["categories"][cat] = 0
|
||||
report["categories"][cat] += 1
|
||||
|
||||
with open(output_path, "w", encoding="utf-8") as fh:
|
||||
json.dump(report, fh, indent=2)
|
||||
|
||||
print(f"[+] AD Assessment Report: {output_path}")
|
||||
print(f" Total findings: {report['total_findings']}")
|
||||
print(f" Critical: {report['critical']}")
|
||||
print(f" High: {report['high']}")
|
||||
print(f" Medium: {report['medium']}")
|
||||
print(f" Low: {report['low']}")
|
||||
print(f" Categories: {json.dumps(report['categories'], indent=6)}")
|
||||
return report
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="AD Vulnerability Assessment Analyzer")
|
||||
parser.add_argument("--pingcastle", help="PingCastle XML report path")
|
||||
parser.add_argument("--bloodhound", help="BloodHound JSON export path")
|
||||
parser.add_argument("--output", default="ad_assessment_report.json", help="Output report path")
|
||||
args = parser.parse_args()
|
||||
|
||||
pc_findings = []
|
||||
bh_findings = []
|
||||
|
||||
if args.pingcastle:
|
||||
print(f"[*] Parsing PingCastle report: {args.pingcastle}")
|
||||
pc_findings = parse_pingcastle_xml(args.pingcastle)
|
||||
print(f" Found {len(pc_findings)} PingCastle findings")
|
||||
|
||||
if args.bloodhound:
|
||||
print(f"[*] Parsing BloodHound data: {args.bloodhound}")
|
||||
bh_findings = parse_bloodhound_json(args.bloodhound)
|
||||
print(f" Found {len(bh_findings)} BloodHound findings")
|
||||
|
||||
if not pc_findings and not bh_findings:
|
||||
print("[-] No input files provided. Use --pingcastle and/or --bloodhound")
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
findings = consolidate_findings(pc_findings, bh_findings)
|
||||
generate_report(findings, args.output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user