mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-24 21:40:58 +03:00
Complete folder anatomy for all 649 cybersecurity skills + update LICENSE to Mahipal
- 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
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for performing Kubernetes penetration testing — authorized testing only."""
|
||||
|
||||
import json
|
||||
import argparse
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def enumerate_cluster_info():
|
||||
"""Enumerate basic cluster information for reconnaissance."""
|
||||
results = {}
|
||||
cmds = {
|
||||
"version": ["kubectl", "version", "--output=json"],
|
||||
"nodes": ["kubectl", "get", "nodes", "-o", "json"],
|
||||
"namespaces": ["kubectl", "get", "namespaces", "-o", "json"],
|
||||
"services": ["kubectl", "get", "services", "--all-namespaces", "-o", "json"],
|
||||
}
|
||||
for key, cmd in cmds.items():
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
data = json.loads(result.stdout) if result.returncode == 0 else {"error": result.stderr[:200]}
|
||||
if key == "nodes":
|
||||
results[key] = [{"name": n["metadata"]["name"],
|
||||
"roles": [l.replace("node-role.kubernetes.io/", "") for l in n["metadata"].get("labels", {}) if l.startswith("node-role")],
|
||||
"os": n.get("status", {}).get("nodeInfo", {}).get("osImage", ""),
|
||||
"kubelet": n.get("status", {}).get("nodeInfo", {}).get("kubeletVersion", "")}
|
||||
for n in data.get("items", [])]
|
||||
elif key == "namespaces":
|
||||
results[key] = [n["metadata"]["name"] for n in data.get("items", [])]
|
||||
elif key == "services":
|
||||
results[key] = [{"name": s["metadata"]["name"], "ns": s["metadata"]["namespace"],
|
||||
"type": s["spec"]["type"], "ports": [p.get("port") for p in s["spec"].get("ports", [])]}
|
||||
for s in data.get("items", [])]
|
||||
else:
|
||||
results[key] = data
|
||||
except Exception as e:
|
||||
results[key] = {"error": str(e)}
|
||||
return {"timestamp": datetime.utcnow().isoformat(), **results}
|
||||
|
||||
|
||||
def test_service_account_permissions(namespace="default"):
|
||||
"""Test what the default service account can do."""
|
||||
checks = [
|
||||
("get_pods", ["kubectl", "auth", "can-i", "get", "pods", "-n", namespace]),
|
||||
("list_secrets", ["kubectl", "auth", "can-i", "list", "secrets", "-n", namespace]),
|
||||
("create_pods", ["kubectl", "auth", "can-i", "create", "pods", "-n", namespace]),
|
||||
("exec_pods", ["kubectl", "auth", "can-i", "create", "pods/exec", "-n", namespace]),
|
||||
("get_nodes", ["kubectl", "auth", "can-i", "get", "nodes"]),
|
||||
("list_namespaces", ["kubectl", "auth", "can-i", "list", "namespaces"]),
|
||||
("create_clusterroles", ["kubectl", "auth", "can-i", "create", "clusterroles"]),
|
||||
("get_secrets_all", ["kubectl", "auth", "can-i", "get", "secrets", "--all-namespaces"]),
|
||||
]
|
||||
results = []
|
||||
for name, cmd in checks:
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
|
||||
allowed = "yes" in result.stdout.lower()
|
||||
results.append({"check": name, "allowed": allowed})
|
||||
except Exception as e:
|
||||
results.append({"check": name, "error": str(e)})
|
||||
dangerous = [r for r in results if r.get("allowed") and r["check"] in ("list_secrets", "create_pods", "exec_pods", "create_clusterroles", "get_secrets_all")]
|
||||
return {
|
||||
"namespace": namespace, "permissions": results,
|
||||
"dangerous_permissions": dangerous,
|
||||
"risk": "CRITICAL" if dangerous else "LOW",
|
||||
}
|
||||
|
||||
|
||||
def scan_exposed_dashboards():
|
||||
"""Check for exposed Kubernetes dashboards and management interfaces."""
|
||||
cmd = ["kubectl", "get", "services", "--all-namespaces", "-o", "json"]
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
data = json.loads(result.stdout)
|
||||
dashboard_patterns = ["dashboard", "grafana", "prometheus", "kibana", "jaeger", "argocd", "rancher", "lens"]
|
||||
exposed = []
|
||||
for svc in data.get("items", []):
|
||||
name = svc["metadata"]["name"].lower()
|
||||
svc_type = svc["spec"]["type"]
|
||||
if any(p in name for p in dashboard_patterns):
|
||||
ports = [{"port": p.get("port"), "nodePort": p.get("nodePort")} for p in svc["spec"].get("ports", [])]
|
||||
exposed.append({
|
||||
"name": svc["metadata"]["name"], "namespace": svc["metadata"]["namespace"],
|
||||
"type": svc_type, "ports": ports,
|
||||
"externally_accessible": svc_type in ("LoadBalancer", "NodePort"),
|
||||
})
|
||||
return {"dashboards_found": len(exposed), "exposed": exposed}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
def check_pod_escape_vectors(namespace="default"):
|
||||
"""Check for container escape vectors in running pods."""
|
||||
cmd = ["kubectl", "get", "pods", "-n", namespace, "-o", "json"]
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
data = json.loads(result.stdout)
|
||||
escape_vectors = []
|
||||
for pod in data.get("items", []):
|
||||
name = pod["metadata"]["name"]
|
||||
for c in pod.get("spec", {}).get("containers", []):
|
||||
vectors = []
|
||||
sc = c.get("securityContext", {})
|
||||
if sc.get("privileged"):
|
||||
vectors.append("PRIVILEGED_MODE")
|
||||
caps = sc.get("capabilities", {}).get("add", [])
|
||||
if "SYS_ADMIN" in caps:
|
||||
vectors.append("CAP_SYS_ADMIN")
|
||||
if "SYS_PTRACE" in caps:
|
||||
vectors.append("CAP_SYS_PTRACE")
|
||||
for vol in pod.get("spec", {}).get("volumes", []):
|
||||
hp = vol.get("hostPath", {}).get("path", "")
|
||||
if hp in ("/", "/etc", "/var/run/docker.sock", "/proc", "/sys"):
|
||||
vectors.append(f"HOST_PATH_MOUNT:{hp}")
|
||||
if pod.get("spec", {}).get("hostPID"):
|
||||
vectors.append("HOST_PID_NAMESPACE")
|
||||
if pod.get("spec", {}).get("hostNetwork"):
|
||||
vectors.append("HOST_NETWORK")
|
||||
if vectors:
|
||||
escape_vectors.append({"pod": name, "container": c["name"], "vectors": vectors})
|
||||
return {
|
||||
"namespace": namespace, "pods_checked": len(data.get("items", [])),
|
||||
"pods_with_escape_vectors": len(escape_vectors),
|
||||
"details": escape_vectors,
|
||||
}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Kubernetes Penetration Testing Agent (Authorized Only)")
|
||||
sub = parser.add_subparsers(dest="command")
|
||||
sub.add_parser("recon", help="Enumerate cluster info")
|
||||
sa = sub.add_parser("sa-perms", help="Test service account permissions")
|
||||
sa.add_argument("--namespace", default="default")
|
||||
sub.add_parser("dashboards", help="Find exposed dashboards")
|
||||
e = sub.add_parser("escape", help="Check container escape vectors")
|
||||
e.add_argument("--namespace", default="default")
|
||||
args = parser.parse_args()
|
||||
if args.command == "recon":
|
||||
result = enumerate_cluster_info()
|
||||
elif args.command == "sa-perms":
|
||||
result = test_service_account_permissions(args.namespace)
|
||||
elif args.command == "dashboards":
|
||||
result = scan_exposed_dashboards()
|
||||
elif args.command == "escape":
|
||||
result = check_pod_escape_vectors(args.namespace)
|
||||
else:
|
||||
parser.print_help()
|
||||
return
|
||||
print(json.dumps(result, indent=2, default=str))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user