mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-23 21:21:00 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
name: performing-container-escape-detection
|
||||
description: >
|
||||
Detects container escape attempts by analyzing namespace configurations, privileged
|
||||
container checks, dangerous capability assignments, and host path mounts using the
|
||||
kubernetes Python client. Identifies CVE-2022-0492 style escapes via cgroup abuse.
|
||||
Use when auditing container security posture or investigating escape attempts.
|
||||
---
|
||||
|
||||
# Performing Container Escape Detection
|
||||
|
||||
## Instructions
|
||||
|
||||
Audit Kubernetes pods for container escape vectors including privileged mode,
|
||||
dangerous capabilities, host namespace sharing, and writable hostPath mounts.
|
||||
|
||||
```python
|
||||
from kubernetes import client, config
|
||||
config.load_kube_config()
|
||||
v1 = client.CoreV1Api()
|
||||
|
||||
pods = v1.list_pod_for_all_namespaces()
|
||||
for pod in pods.items:
|
||||
for container in pod.spec.containers:
|
||||
sc = container.security_context
|
||||
if sc and sc.privileged:
|
||||
print(f"PRIVILEGED: {pod.metadata.namespace}/{pod.metadata.name}")
|
||||
```
|
||||
|
||||
Key escape vectors:
|
||||
1. Privileged containers (full host access)
|
||||
2. CAP_SYS_ADMIN capability
|
||||
3. Host PID/Network/IPC namespace sharing
|
||||
4. Writable hostPath mounts to / or /etc
|
||||
5. Docker socket mount (/var/run/docker.sock)
|
||||
|
||||
## Examples
|
||||
|
||||
```python
|
||||
# Check for docker socket mounts
|
||||
for vol in pod.spec.volumes or []:
|
||||
if vol.host_path and "docker.sock" in (vol.host_path.path or ""):
|
||||
print(f"Docker socket exposed: {pod.metadata.name}")
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
# API Reference: Performing Container Escape Detection
|
||||
|
||||
## kubernetes Python Client
|
||||
|
||||
```python
|
||||
from kubernetes import client, config
|
||||
|
||||
config.load_kube_config() # or config.load_incluster_config()
|
||||
v1 = client.CoreV1Api()
|
||||
|
||||
pods = v1.list_pod_for_all_namespaces()
|
||||
for pod in pods.items:
|
||||
spec = pod.spec
|
||||
# Check host namespace sharing
|
||||
print(spec.host_pid, spec.host_network, spec.host_ipc)
|
||||
for c in spec.containers:
|
||||
sc = c.security_context
|
||||
if sc:
|
||||
print(sc.privileged, sc.capabilities, sc.run_as_user)
|
||||
for vol in spec.volumes or []:
|
||||
if vol.host_path:
|
||||
print(vol.host_path.path)
|
||||
```
|
||||
|
||||
## Container Escape Vectors
|
||||
|
||||
| Vector | Field | Severity |
|
||||
|--------|-------|----------|
|
||||
| Privileged mode | `securityContext.privileged` | CRITICAL |
|
||||
| SYS_ADMIN cap | `capabilities.add` | CRITICAL |
|
||||
| Docker socket | `hostPath: /var/run/docker.sock` | CRITICAL |
|
||||
| Host PID ns | `hostPID: true` | HIGH |
|
||||
| Host Network | `hostNetwork: true` | HIGH |
|
||||
| Writable / mount | `hostPath: /` | CRITICAL |
|
||||
| Run as root | `runAsUser: 0` | MEDIUM |
|
||||
|
||||
## Dangerous Linux Capabilities
|
||||
|
||||
```
|
||||
SYS_ADMIN, SYS_PTRACE, SYS_RAWIO, SYS_MODULE,
|
||||
DAC_READ_SEARCH, NET_ADMIN, NET_RAW
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- kubernetes Python client: https://github.com/kubernetes-client/python
|
||||
- Pod Security Standards: https://kubernetes.io/docs/concepts/security/pod-security-standards/
|
||||
- Container escapes: https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/
|
||||
@@ -0,0 +1,197 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for detecting container escape vectors in Kubernetes."""
|
||||
|
||||
import json
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
|
||||
from kubernetes import client, config
|
||||
|
||||
|
||||
DANGEROUS_CAPS = [
|
||||
"SYS_ADMIN", "SYS_PTRACE", "SYS_RAWIO", "SYS_MODULE",
|
||||
"DAC_READ_SEARCH", "NET_ADMIN", "NET_RAW",
|
||||
]
|
||||
|
||||
DANGEROUS_HOST_PATHS = ["/", "/etc", "/root", "/var/run/docker.sock",
|
||||
"/var/run/crio", "/proc", "/sys"]
|
||||
|
||||
|
||||
def load_kube_config():
|
||||
"""Load Kubernetes configuration."""
|
||||
try:
|
||||
config.load_incluster_config()
|
||||
except config.ConfigException:
|
||||
config.load_kube_config()
|
||||
|
||||
|
||||
def check_privileged_containers(v1):
|
||||
"""Find pods running privileged containers."""
|
||||
findings = []
|
||||
pods = v1.list_pod_for_all_namespaces()
|
||||
for pod in pods.items:
|
||||
for container in pod.spec.containers or []:
|
||||
sc = container.security_context
|
||||
if sc and sc.privileged:
|
||||
findings.append({
|
||||
"namespace": pod.metadata.namespace,
|
||||
"pod": pod.metadata.name,
|
||||
"container": container.name,
|
||||
"issue": "privileged container",
|
||||
"severity": "CRITICAL",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def check_dangerous_capabilities(v1):
|
||||
"""Find containers with dangerous Linux capabilities."""
|
||||
findings = []
|
||||
pods = v1.list_pod_for_all_namespaces()
|
||||
for pod in pods.items:
|
||||
for container in pod.spec.containers or []:
|
||||
sc = container.security_context
|
||||
if not sc or not sc.capabilities or not sc.capabilities.add:
|
||||
continue
|
||||
for cap in sc.capabilities.add:
|
||||
if cap in DANGEROUS_CAPS:
|
||||
findings.append({
|
||||
"namespace": pod.metadata.namespace,
|
||||
"pod": pod.metadata.name,
|
||||
"container": container.name,
|
||||
"capability": cap,
|
||||
"severity": "HIGH",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def check_host_namespaces(v1):
|
||||
"""Find pods sharing host PID, network, or IPC namespaces."""
|
||||
findings = []
|
||||
pods = v1.list_pod_for_all_namespaces()
|
||||
for pod in pods.items:
|
||||
spec = pod.spec
|
||||
ns_issues = []
|
||||
if spec.host_pid:
|
||||
ns_issues.append("hostPID")
|
||||
if spec.host_network:
|
||||
ns_issues.append("hostNetwork")
|
||||
if spec.host_ipc:
|
||||
ns_issues.append("hostIPC")
|
||||
if ns_issues:
|
||||
findings.append({
|
||||
"namespace": pod.metadata.namespace,
|
||||
"pod": pod.metadata.name,
|
||||
"host_namespaces": ns_issues,
|
||||
"severity": "HIGH",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def check_dangerous_mounts(v1):
|
||||
"""Find pods with dangerous hostPath volume mounts."""
|
||||
findings = []
|
||||
pods = v1.list_pod_for_all_namespaces()
|
||||
for pod in pods.items:
|
||||
for vol in pod.spec.volumes or []:
|
||||
if not vol.host_path:
|
||||
continue
|
||||
path = vol.host_path.path
|
||||
if any(path == dp or path.startswith(dp + "/") for dp in DANGEROUS_HOST_PATHS):
|
||||
findings.append({
|
||||
"namespace": pod.metadata.namespace,
|
||||
"pod": pod.metadata.name,
|
||||
"volume": vol.name,
|
||||
"host_path": path,
|
||||
"severity": "CRITICAL" if path in ("/", "/var/run/docker.sock") else "HIGH",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def check_docker_socket(v1):
|
||||
"""Specifically detect Docker/CRI socket mounts."""
|
||||
findings = []
|
||||
sockets = ["/var/run/docker.sock", "/var/run/crio/crio.sock",
|
||||
"/run/containerd/containerd.sock"]
|
||||
pods = v1.list_pod_for_all_namespaces()
|
||||
for pod in pods.items:
|
||||
for vol in pod.spec.volumes or []:
|
||||
if vol.host_path and vol.host_path.path in sockets:
|
||||
findings.append({
|
||||
"namespace": pod.metadata.namespace,
|
||||
"pod": pod.metadata.name,
|
||||
"socket_path": vol.host_path.path,
|
||||
"severity": "CRITICAL",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def check_root_containers(v1):
|
||||
"""Find containers running as root."""
|
||||
findings = []
|
||||
pods = v1.list_pod_for_all_namespaces()
|
||||
for pod in pods.items:
|
||||
for container in pod.spec.containers or []:
|
||||
sc = container.security_context
|
||||
if sc and sc.run_as_user == 0:
|
||||
findings.append({
|
||||
"namespace": pod.metadata.namespace,
|
||||
"pod": pod.metadata.name,
|
||||
"container": container.name,
|
||||
"issue": "running as UID 0",
|
||||
"severity": "MEDIUM",
|
||||
})
|
||||
elif not sc or sc.run_as_non_root is not True:
|
||||
findings.append({
|
||||
"namespace": pod.metadata.namespace,
|
||||
"pod": pod.metadata.name,
|
||||
"container": container.name,
|
||||
"issue": "runAsNonRoot not enforced",
|
||||
"severity": "LOW",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Container Escape Detection Agent")
|
||||
parser.add_argument("--output", default="container_escape_report.json")
|
||||
parser.add_argument("--action", choices=[
|
||||
"privileged", "capabilities", "namespaces", "mounts", "socket", "full_scan"
|
||||
], default="full_scan")
|
||||
args = parser.parse_args()
|
||||
|
||||
load_kube_config()
|
||||
v1 = client.CoreV1Api()
|
||||
report = {"generated_at": datetime.utcnow().isoformat(), "findings": {}}
|
||||
|
||||
if args.action in ("privileged", "full_scan"):
|
||||
findings = check_privileged_containers(v1)
|
||||
report["findings"]["privileged"] = findings
|
||||
print(f"[+] Privileged containers: {len(findings)}")
|
||||
|
||||
if args.action in ("capabilities", "full_scan"):
|
||||
findings = check_dangerous_capabilities(v1)
|
||||
report["findings"]["dangerous_caps"] = findings
|
||||
print(f"[+] Dangerous capabilities: {len(findings)}")
|
||||
|
||||
if args.action in ("namespaces", "full_scan"):
|
||||
findings = check_host_namespaces(v1)
|
||||
report["findings"]["host_namespaces"] = findings
|
||||
print(f"[+] Host namespace sharing: {len(findings)}")
|
||||
|
||||
if args.action in ("mounts", "full_scan"):
|
||||
findings = check_dangerous_mounts(v1)
|
||||
report["findings"]["dangerous_mounts"] = findings
|
||||
print(f"[+] Dangerous mounts: {len(findings)}")
|
||||
|
||||
if args.action in ("socket", "full_scan"):
|
||||
findings = check_docker_socket(v1)
|
||||
report["findings"]["socket_mounts"] = findings
|
||||
print(f"[+] Container runtime socket mounts: {len(findings)}")
|
||||
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2, default=str)
|
||||
print(f"[+] Report saved to {args.output}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user