mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-11 10:03:42 +03:00
8cae0648ec
Demand-driven expansion targeting the fastest-growing 2025-2026 threat and
skills categories (ISC2/WEF/CrowdStrike/Mandiant signals):
- AI Security (NEW domain, 12 skills): LLM red-teaming with garak/PyRIT,
prompt injection (direct/indirect/RAG), MCP tool-poisoning, agentic tool
invocation, guardrails, model/data poisoning, system-prompt leakage,
embedding/vector weaknesses, model extraction, continuous red-teaming
- Supply Chain Security (NEW domain, 5 skills): SBOMs, dependency confusion,
malicious-npm triage, typosquatting, SLSA/Sigstore provenance
- Hardware & Firmware Security (NEW domain, 4 skills): CHIPSEC/UEFI audit,
Secure Boot bypass, TPM measured-boot attestation, ESP bootkit hunting
- Identity (10): Entra ID/ROADtools, GraphRunner, AADInternals, ADCS/Certipy,
shadow credentials, coercion, BloodHound CE, device-code phishing, SSO abuse
- Cloud-native (8): Stratus, Pacu, CloudFox, container escape, K8s RBAC,
Falco, Trivy, kube-bench
- Offensive C2 (6): Sliver, Havoc, NetExec, DPAPI, NTLM relay ESC8, redirectors
- DFIR (6): Hayabusa, Chainsaw, KAPE, Velociraptor, EZ Tools, Plaso
- Backfill (4): OpenCTI, MISP, honeytokens, post-quantum crypto migration
Each skill follows the repo taxonomy (SKILL.md + references/{standards,api-reference}.md
+ scripts/agent.py + LICENSE), with researched real tool commands (no placeholders),
complete frontmatter, and ATT&CK/ATLAS + NIST CSF mappings. Updates README domain
table, skill count, and index.json.
168 lines
5.7 KiB
Python
168 lines
5.7 KiB
Python
#!/usr/bin/env python3
|
|
# For authorized Kubernetes security assessments only. Run against clusters you
|
|
# own or are explicitly authorized in writing to test.
|
|
"""Kubernetes RBAC privilege-escalation auditor.
|
|
|
|
Wraps `kubectl auth can-i` to enumerate effective permissions for service
|
|
accounts and flag the RBAC primitives that are equivalent to cluster-admin
|
|
(create pods, read secrets, escalate/bind/impersonate, token minting, wildcards),
|
|
per the Kubernetes "RBAC Good Practices" guidance.
|
|
"""
|
|
|
|
import argparse
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from datetime import datetime, timezone
|
|
|
|
# (verb, resource) probes that indicate escalation potential
|
|
DANGEROUS_CHECKS = [
|
|
("*", "*"),
|
|
("create", "pods"),
|
|
("create", "pods/exec"),
|
|
("create", "pods/attach"),
|
|
("create", "pods/ephemeralcontainers"),
|
|
("get", "secrets"),
|
|
("list", "secrets"),
|
|
("create", "serviceaccounts/token"),
|
|
("impersonate", "users"),
|
|
("escalate", "roles"),
|
|
("bind", "clusterroles"),
|
|
("update", "clusterrolebindings"),
|
|
("update", "mutatingwebhookconfigurations"),
|
|
("create", "nodes/proxy"),
|
|
]
|
|
|
|
|
|
def _kubectl(args):
|
|
cmd = ["kubectl"] + args
|
|
try:
|
|
p = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
|
return p.returncode, p.stdout.strip(), p.stderr.strip()
|
|
except FileNotFoundError:
|
|
print("[!] kubectl not found on PATH", file=sys.stderr)
|
|
sys.exit(2)
|
|
except subprocess.TimeoutExpired:
|
|
return 124, "", "timeout"
|
|
|
|
|
|
def list_service_accounts(namespace=None):
|
|
args = ["get", "serviceaccounts", "-o",
|
|
"jsonpath={range .items[*]}{.metadata.namespace}/{.metadata.name}{\"\\n\"}{end}"]
|
|
if namespace:
|
|
args += ["-n", namespace]
|
|
else:
|
|
args += ["--all-namespaces"]
|
|
rc, out, err = _kubectl(args)
|
|
if rc != 0:
|
|
print(f"[!] failed to list service accounts: {err}", file=sys.stderr)
|
|
return []
|
|
return [line for line in out.splitlines() if "/" in line]
|
|
|
|
|
|
def can_i(verb, resource, subject=None, all_ns=True):
|
|
"""Return True if the (optionally impersonated) subject can verb/resource."""
|
|
args = ["auth", "can-i", verb, resource]
|
|
if all_ns:
|
|
args.append("--all-namespaces")
|
|
if subject:
|
|
args.append(f"--as=system:serviceaccount:{subject.split('/')[0]}:{subject.split('/')[1]}")
|
|
rc, out, _ = _kubectl(args)
|
|
return out.strip() == "yes"
|
|
|
|
|
|
def audit_subject(subject):
|
|
findings = []
|
|
for verb, resource in DANGEROUS_CHECKS:
|
|
if can_i(verb, resource, subject=subject):
|
|
findings.append({"verb": verb, "resource": resource})
|
|
severity = "none"
|
|
flat = {(f["verb"], f["resource"]) for f in findings}
|
|
if ("*", "*") in flat or ("escalate", "roles") in flat or \
|
|
("bind", "clusterroles") in flat or ("impersonate", "users") in flat:
|
|
severity = "critical"
|
|
elif ("create", "pods") in flat or ("list", "secrets") in flat or \
|
|
("create", "serviceaccounts/token") in flat:
|
|
severity = "high"
|
|
elif findings:
|
|
severity = "medium"
|
|
return {"subject": subject, "severity": severity,
|
|
"dangerous_permissions": findings}
|
|
|
|
|
|
def cluster_admin_bindings():
|
|
rc, out, _ = _kubectl([
|
|
"get", "clusterrolebindings", "-o", "json"])
|
|
if rc != 0:
|
|
return []
|
|
try:
|
|
data = json.loads(out)
|
|
except json.JSONDecodeError:
|
|
return []
|
|
result = []
|
|
for item in data.get("items", []):
|
|
if item.get("roleRef", {}).get("name") == "cluster-admin":
|
|
subs = [f"{s.get('kind')}:{s.get('name')}"
|
|
for s in (item.get("subjects") or [])]
|
|
result.append({"binding": item["metadata"]["name"], "subjects": subs})
|
|
return result
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser(
|
|
description="Audit Kubernetes RBAC for privilege-escalation paths")
|
|
ap.add_argument("-n", "--namespace", help="limit to one namespace")
|
|
ap.add_argument("-s", "--subject",
|
|
help="audit a single subject NS/SA instead of all")
|
|
ap.add_argument("-o", "--output", help="write JSON report to file")
|
|
args = ap.parse_args()
|
|
|
|
if not shutil.which("kubectl"):
|
|
print("[!] kubectl is required", file=sys.stderr)
|
|
return 2
|
|
|
|
print("=" * 60)
|
|
print(" KUBERNETES RBAC PRIVILEGE-ESCALATION AUDIT")
|
|
print(f" {datetime.now(timezone.utc).isoformat()}")
|
|
print("=" * 60)
|
|
|
|
admins = cluster_admin_bindings()
|
|
print(f"\n[+] cluster-admin bindings ({len(admins)}):")
|
|
for a in admins:
|
|
print(f" {a['binding']} -> {', '.join(a['subjects']) or '(none)'}")
|
|
|
|
subjects = [args.subject] if args.subject else list_service_accounts(args.namespace)
|
|
print(f"\n[+] Auditing {len(subjects)} service account(s)...")
|
|
|
|
results = []
|
|
for subj in subjects:
|
|
r = audit_subject(subj)
|
|
results.append(r)
|
|
if r["severity"] != "none":
|
|
perms = ", ".join(f"{f['verb']} {f['resource']}"
|
|
for f in r["dangerous_permissions"])
|
|
print(f" [{r['severity'].upper():8}] {subj}: {perms}")
|
|
|
|
report = {
|
|
"generated_utc": datetime.now(timezone.utc).isoformat(),
|
|
"cluster_admin_bindings": admins,
|
|
"subject_findings": results,
|
|
"summary": {
|
|
"critical": sum(1 for r in results if r["severity"] == "critical"),
|
|
"high": sum(1 for r in results if r["severity"] == "high"),
|
|
"medium": sum(1 for r in results if r["severity"] == "medium"),
|
|
},
|
|
}
|
|
print(f"\n[+] Summary: {report['summary']}")
|
|
|
|
if args.output:
|
|
with open(args.output, "w") as fh:
|
|
json.dump(report, fh, indent=2)
|
|
print(f"[+] Report written to {args.output}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|