mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-14 11:51:16 +03:00
c21af3347e
- Add scripts/agent.py and references/api-reference.md to all remaining skills - Update all 648 LICENSE files: copyright now reads 'Mahipal' - Add implementing-security-monitoring-with-datadog (new skill with full anatomy) - All 649 skills now have: SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
157 lines
5.7 KiB
Python
157 lines
5.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for auditing Windows endpoints against CIS Benchmark hardening controls."""
|
|
|
|
import argparse
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from datetime import datetime, timezone
|
|
|
|
|
|
def run_ps(command, timeout=15):
|
|
"""Run PowerShell command and return output."""
|
|
try:
|
|
return subprocess.check_output(
|
|
["powershell", "-NoProfile", "-Command", command],
|
|
text=True, errors="replace", timeout=timeout
|
|
).strip()
|
|
except subprocess.SubprocessError:
|
|
return ""
|
|
|
|
|
|
def check_password_policy():
|
|
"""CIS 1.1 — Password Policy."""
|
|
findings = []
|
|
result = run_ps("net accounts")
|
|
for line in result.splitlines():
|
|
if "Minimum password length" in line:
|
|
val = int(line.split(":")[-1].strip())
|
|
if val < 14:
|
|
findings.append({"check": "1.1.4", "issue": f"Min password length: {val} (should be >= 14)", "severity": "HIGH"})
|
|
if "Maximum password age" in line:
|
|
val = line.split(":")[-1].strip()
|
|
if val == "Unlimited":
|
|
findings.append({"check": "1.1.2", "issue": "No max password age", "severity": "MEDIUM"})
|
|
if "Lockout threshold" in line:
|
|
val = line.split(":")[-1].strip()
|
|
if val == "Never" or (val.isdigit() and int(val) > 10):
|
|
findings.append({"check": "1.2.1", "issue": f"Account lockout threshold: {val}", "severity": "MEDIUM"})
|
|
return findings
|
|
|
|
|
|
def check_audit_policy():
|
|
"""CIS 17 — Advanced Audit Policy."""
|
|
findings = []
|
|
result = run_ps("auditpol /get /category:*")
|
|
required_audits = {
|
|
"Credential Validation": "Success and Failure",
|
|
"Logon": "Success and Failure",
|
|
"Security Group Management": "Success",
|
|
"User Account Management": "Success and Failure",
|
|
"Process Creation": "Success",
|
|
}
|
|
for subcategory, expected in required_audits.items():
|
|
if subcategory in result:
|
|
for line in result.splitlines():
|
|
if subcategory in line:
|
|
if "No Auditing" in line:
|
|
findings.append({
|
|
"check": "17.x", "issue": f"Audit not configured: {subcategory}",
|
|
"severity": "HIGH",
|
|
})
|
|
return findings
|
|
|
|
|
|
def check_windows_firewall():
|
|
"""CIS 9 — Windows Firewall."""
|
|
findings = []
|
|
profiles = ["Domain", "Private", "Public"]
|
|
for profile in profiles:
|
|
result = run_ps(f"Get-NetFirewallProfile -Name {profile} | Select-Object Enabled | ConvertTo-Json")
|
|
try:
|
|
data = json.loads(result) if result else {}
|
|
if not data.get("Enabled"):
|
|
findings.append({"check": "9.1", "issue": f"Firewall {profile} profile disabled", "severity": "HIGH"})
|
|
except json.JSONDecodeError:
|
|
pass
|
|
return findings
|
|
|
|
|
|
def check_security_options():
|
|
"""CIS 2.3 — Security Options."""
|
|
findings = []
|
|
checks = [
|
|
("HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa", "LmCompatibilityLevel", 5,
|
|
"2.3.11.7", "LAN Manager auth level not NTLMv2 only"),
|
|
("HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", "EnableLUA", 1,
|
|
"2.3.17.1", "UAC not enabled"),
|
|
("HKLM:\\SYSTEM\\CurrentControlSet\\Services\\LanManServer\\Parameters", "SMB1", 0,
|
|
"18.3.2", "SMBv1 not disabled"),
|
|
]
|
|
for path, name, expected, cis_id, desc in checks:
|
|
result = run_ps(
|
|
f"(Get-ItemProperty -Path '{path}' -Name '{name}' -ErrorAction SilentlyContinue).{name}"
|
|
)
|
|
if result.strip().isdigit() and int(result.strip()) != expected:
|
|
findings.append({"check": cis_id, "issue": desc, "current": result.strip(), "severity": "HIGH"})
|
|
return findings
|
|
|
|
|
|
def check_windows_features():
|
|
"""CIS 18 — Windows Features."""
|
|
findings = []
|
|
risky_features = ["SMB1Protocol", "TelnetClient", "TFTP"]
|
|
for feature in risky_features:
|
|
result = run_ps(
|
|
f"Get-WindowsOptionalFeature -Online -FeatureName {feature} 2>$null | "
|
|
f"Select-Object State | ConvertTo-Json"
|
|
)
|
|
try:
|
|
data = json.loads(result) if result else {}
|
|
if data.get("State") == 1: # Enabled
|
|
findings.append({"check": "18.x", "issue": f"Risky feature enabled: {feature}", "severity": "MEDIUM"})
|
|
except json.JSONDecodeError:
|
|
pass
|
|
return findings
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Audit Windows endpoint against CIS Benchmark"
|
|
)
|
|
parser.add_argument("--output", "-o", help="Output JSON report")
|
|
args = parser.parse_args()
|
|
|
|
print("[*] Windows CIS Benchmark Hardening Audit Agent")
|
|
if sys.platform != "win32":
|
|
print("[!] This agent requires Windows")
|
|
return
|
|
|
|
all_findings = []
|
|
all_findings.extend(check_password_policy())
|
|
all_findings.extend(check_audit_policy())
|
|
all_findings.extend(check_windows_firewall())
|
|
all_findings.extend(check_security_options())
|
|
all_findings.extend(check_windows_features())
|
|
|
|
high = sum(1 for f in all_findings if f["severity"] == "HIGH")
|
|
report = {
|
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
"findings": all_findings,
|
|
"total": len(all_findings),
|
|
"high_severity": high,
|
|
"compliance_score": max(0, 100 - len(all_findings) * 5),
|
|
}
|
|
print(f"[*] Findings: {len(all_findings)} (HIGH: {high})")
|
|
|
|
if args.output:
|
|
with open(args.output, "w") as f:
|
|
json.dump(report, f, indent=2)
|
|
print(f"[*] Report saved to {args.output}")
|
|
else:
|
|
print(json.dumps(report, indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|