mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-17 21:19:40 +03:00
c47eed6a64
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
214 lines
6.9 KiB
Python
214 lines
6.9 KiB
Python
#!/usr/bin/env python3
|
|
"""AWS GuardDuty findings automation and detection agent."""
|
|
|
|
import json
|
|
import sys
|
|
import argparse
|
|
from datetime import datetime
|
|
|
|
try:
|
|
import boto3
|
|
except ImportError:
|
|
print("Install: pip install boto3")
|
|
sys.exit(1)
|
|
|
|
|
|
def get_guardduty_detector(session):
|
|
"""Get the active GuardDuty detector ID."""
|
|
gd = session.client("guardduty")
|
|
detectors = gd.list_detectors()["DetectorIds"]
|
|
if not detectors:
|
|
return None
|
|
return detectors[0]
|
|
|
|
|
|
def list_findings(session, detector_id, severity_min=4.0, max_results=50):
|
|
"""List GuardDuty findings filtered by severity."""
|
|
gd = session.client("guardduty")
|
|
criteria = {
|
|
"Criterion": {
|
|
"severity": {"Gte": severity_min},
|
|
"service.archived": {"Eq": ["false"]},
|
|
}
|
|
}
|
|
finding_ids = gd.list_findings(
|
|
DetectorId=detector_id,
|
|
FindingCriteria=criteria,
|
|
SortCriteria={"AttributeName": "severity", "OrderBy": "DESC"},
|
|
MaxResults=max_results,
|
|
)["FindingIds"]
|
|
|
|
if not finding_ids:
|
|
return []
|
|
|
|
details = gd.get_findings(
|
|
DetectorId=detector_id, FindingIds=finding_ids
|
|
)["Findings"]
|
|
|
|
results = []
|
|
for f in details:
|
|
results.append({
|
|
"id": f.get("Id", ""),
|
|
"type": f.get("Type", ""),
|
|
"severity": f.get("Severity", 0),
|
|
"title": f.get("Title", ""),
|
|
"description": f.get("Description", "")[:200],
|
|
"resource_type": f.get("Resource", {}).get("ResourceType", ""),
|
|
"region": f.get("Region", ""),
|
|
"first_seen": f.get("Service", {}).get("EventFirstSeen", ""),
|
|
"last_seen": f.get("Service", {}).get("EventLastSeen", ""),
|
|
"count": f.get("Service", {}).get("Count", 0),
|
|
"action_type": f.get("Service", {}).get("Action", {}).get("ActionType", ""),
|
|
})
|
|
return results
|
|
|
|
|
|
def get_finding_statistics(session, detector_id):
|
|
"""Get finding count grouped by type and severity."""
|
|
gd = session.client("guardduty")
|
|
stats = gd.get_findings_statistics(
|
|
DetectorId=detector_id,
|
|
FindingStatisticTypes=["COUNT_BY_SEVERITY"],
|
|
)
|
|
return stats.get("FindingStatistics", {})
|
|
|
|
|
|
def check_detector_configuration(session, detector_id):
|
|
"""Audit GuardDuty detector configuration for coverage gaps."""
|
|
gd = session.client("guardduty")
|
|
findings = []
|
|
|
|
detector = gd.get_detector(DetectorId=detector_id)
|
|
status = detector.get("Status", "")
|
|
if status != "ENABLED":
|
|
findings.append({
|
|
"check": "Detector status",
|
|
"status": status,
|
|
"severity": "CRITICAL",
|
|
"issue": "GuardDuty detector is not enabled",
|
|
})
|
|
|
|
features = detector.get("Features", [])
|
|
expected_features = {
|
|
"S3_DATA_EVENTS", "EKS_AUDIT_LOGS", "EBS_MALWARE_PROTECTION",
|
|
"RDS_LOGIN_EVENTS", "LAMBDA_NETWORK_LOGS", "RUNTIME_MONITORING",
|
|
}
|
|
enabled_features = set()
|
|
for feat in features:
|
|
if feat.get("Status") == "ENABLED":
|
|
enabled_features.add(feat.get("Name", ""))
|
|
|
|
missing = expected_features - enabled_features
|
|
for m in missing:
|
|
findings.append({
|
|
"check": f"Feature: {m}",
|
|
"status": "DISABLED",
|
|
"severity": "HIGH",
|
|
"issue": f"GuardDuty feature {m} not enabled — reduced detection coverage",
|
|
})
|
|
|
|
return findings
|
|
|
|
|
|
def check_member_accounts(session, detector_id):
|
|
"""Check GuardDuty member account enrollment in multi-account setup."""
|
|
gd = session.client("guardduty")
|
|
members = gd.list_members(
|
|
DetectorId=detector_id, OnlyAssociated="true"
|
|
).get("Members", [])
|
|
|
|
results = []
|
|
for m in members:
|
|
status = m.get("RelationshipStatus", "")
|
|
results.append({
|
|
"account_id": m.get("AccountId", ""),
|
|
"email": m.get("Email", ""),
|
|
"status": status,
|
|
"detector_id": m.get("DetectorId", ""),
|
|
})
|
|
if status != "Enabled":
|
|
results[-1]["finding"] = f"Member account not fully enabled: {status}"
|
|
results[-1]["severity"] = "HIGH"
|
|
return results
|
|
|
|
|
|
def auto_archive_low_severity(session, detector_id, threshold=2.0):
|
|
"""Auto-archive findings below severity threshold."""
|
|
gd = session.client("guardduty")
|
|
criteria = {
|
|
"Criterion": {
|
|
"severity": {"Lt": threshold},
|
|
"service.archived": {"Eq": ["false"]},
|
|
}
|
|
}
|
|
finding_ids = gd.list_findings(
|
|
DetectorId=detector_id,
|
|
FindingCriteria=criteria,
|
|
MaxResults=100,
|
|
)["FindingIds"]
|
|
|
|
if finding_ids:
|
|
gd.archive_findings(DetectorId=detector_id, FindingIds=finding_ids)
|
|
return {"archived_count": len(finding_ids)}
|
|
|
|
|
|
def run_audit(args):
|
|
"""Execute GuardDuty findings automation audit."""
|
|
print(f"\n{'='*60}")
|
|
print(f" AWS GUARDDUTY FINDINGS AUTOMATION")
|
|
print(f" Generated: {datetime.utcnow().isoformat()} UTC")
|
|
print(f"{'='*60}\n")
|
|
|
|
session = boto3.Session(profile_name=args.profile, region_name=args.region)
|
|
report = {}
|
|
|
|
detector_id = get_guardduty_detector(session)
|
|
if not detector_id:
|
|
print("ERROR: No GuardDuty detector found")
|
|
return {"error": "No detector found"}
|
|
|
|
report["detector_id"] = detector_id
|
|
print(f"Detector ID: {detector_id}\n")
|
|
|
|
config_findings = check_detector_configuration(session, detector_id)
|
|
report["configuration_findings"] = config_findings
|
|
print(f"--- CONFIGURATION AUDIT ({len(config_findings)} findings) ---")
|
|
for f in config_findings:
|
|
print(f" [{f['severity']}] {f['check']}: {f['issue']}")
|
|
|
|
findings = list_findings(session, detector_id, args.min_severity)
|
|
report["active_findings"] = len(findings)
|
|
print(f"\n--- ACTIVE FINDINGS ({len(findings)}, severity >= {args.min_severity}) ---")
|
|
for f in findings[:15]:
|
|
print(f" [{f['severity']:.1f}] {f['type']}")
|
|
print(f" {f['title'][:80]}")
|
|
|
|
members = check_member_accounts(session, detector_id)
|
|
report["member_accounts"] = members
|
|
print(f"\n--- MEMBER ACCOUNTS ({len(members)}) ---")
|
|
for m in members:
|
|
status_icon = "OK" if m["status"] == "Enabled" else "WARN"
|
|
print(f" [{status_icon}] {m['account_id']}: {m['status']}")
|
|
|
|
return report
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="GuardDuty Findings Automation Agent")
|
|
parser.add_argument("--profile", default=None, help="AWS profile name")
|
|
parser.add_argument("--region", default="us-east-1", help="AWS region")
|
|
parser.add_argument("--min-severity", type=float, default=4.0,
|
|
help="Minimum severity threshold (default: 4.0)")
|
|
parser.add_argument("--output", help="Save report to JSON file")
|
|
args = parser.parse_args()
|
|
|
|
report = run_audit(args)
|
|
if args.output:
|
|
with open(args.output, "w") as f:
|
|
json.dump(report, f, indent=2, default=str)
|
|
print(f"\n[+] Report saved to {args.output}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|