mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-16 12:45:17 +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,116 @@
|
||||
# API Reference: Docker Container Forensics Tools
|
||||
|
||||
## docker inspect - Container Details
|
||||
|
||||
### Syntax
|
||||
```bash
|
||||
docker inspect <container_id>
|
||||
docker inspect --format '{{.HostConfig.Privileged}}' <container_id>
|
||||
docker inspect --format '{{json .Mounts}}' <container_id> | jq
|
||||
docker inspect --format '{{.GraphDriver.Data.MergedDir}}' <container_id>
|
||||
```
|
||||
|
||||
### Key JSON Paths
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `.HostConfig.Privileged` | Privileged mode status |
|
||||
| `.HostConfig.CapAdd` | Added capabilities |
|
||||
| `.HostConfig.PidMode` | PID namespace mode |
|
||||
| `.HostConfig.NetworkMode` | Network namespace mode |
|
||||
| `.Mounts` | Volume mount configuration |
|
||||
| `.Config.User` | Container user |
|
||||
| `.Config.Env` | Environment variables |
|
||||
| `.Config.Image` | Source image name |
|
||||
| `.State.StartedAt` | Container start time |
|
||||
|
||||
## docker diff - Filesystem Changes
|
||||
|
||||
### Syntax
|
||||
```bash
|
||||
docker diff <container_id>
|
||||
```
|
||||
|
||||
### Output Codes
|
||||
| Code | Meaning |
|
||||
|------|---------|
|
||||
| `A` | File or directory was added |
|
||||
| `C` | File or directory was changed |
|
||||
| `D` | File or directory was deleted |
|
||||
|
||||
## docker export - Container Filesystem Export
|
||||
|
||||
### Syntax
|
||||
```bash
|
||||
docker export <container_id> > container_fs.tar
|
||||
docker export <container_id> | gzip > container_fs.tar.gz
|
||||
```
|
||||
|
||||
## docker commit / docker save - Image Preservation
|
||||
|
||||
### Syntax
|
||||
```bash
|
||||
docker commit <container_id> forensic-evidence:case001
|
||||
docker save forensic-evidence:case001 > evidence_image.tar
|
||||
```
|
||||
|
||||
## docker logs - Container Log Retrieval
|
||||
|
||||
### Syntax
|
||||
```bash
|
||||
docker logs --timestamps <container_id>
|
||||
docker logs --since 2024-01-15 <container_id>
|
||||
docker logs --tail 1000 <container_id>
|
||||
docker logs -f <container_id> # Follow (live)
|
||||
```
|
||||
|
||||
## dive - Image Layer Analysis
|
||||
|
||||
### Syntax
|
||||
```bash
|
||||
dive <image_name> # Interactive mode
|
||||
dive <image_name> --ci # CI mode (non-interactive)
|
||||
dive <image_name> --ci --json out.json # JSON output
|
||||
```
|
||||
|
||||
### Output Includes
|
||||
- Layer-by-layer filesystem changes
|
||||
- Image efficiency score
|
||||
- Wasted space analysis
|
||||
|
||||
## container-diff - Image Comparison
|
||||
|
||||
### Syntax
|
||||
```bash
|
||||
container-diff diff daemon://nginx:latest daemon://suspect:latest \
|
||||
--type=file --type=apt --type=history --json
|
||||
```
|
||||
|
||||
### Diff Types
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `file` | File system differences |
|
||||
| `apt` | APT package differences |
|
||||
| `pip` | Python package differences |
|
||||
| `history` | Docker build history differences |
|
||||
|
||||
## Trivy - Vulnerability Scanning
|
||||
|
||||
### Syntax
|
||||
```bash
|
||||
trivy image <image_name>
|
||||
trivy image --format json <image_name>
|
||||
trivy image --scanners vuln,secret <image_name>
|
||||
trivy fs /path/to/exported/container/
|
||||
```
|
||||
|
||||
### Severity Levels
|
||||
`CRITICAL` | `HIGH` | `MEDIUM` | `LOW` | `UNKNOWN`
|
||||
|
||||
## docker-explorer - Offline Forensics
|
||||
|
||||
### Syntax
|
||||
```bash
|
||||
de.py -r /var/lib/docker list
|
||||
de.py -r /var/lib/docker mount <container_id> /mnt/forensic
|
||||
de.py -r /var/lib/docker history <container_id>
|
||||
```
|
||||
@@ -0,0 +1,231 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Docker container forensics agent for investigating compromised containers."""
|
||||
|
||||
import subprocess
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import hashlib
|
||||
import datetime
|
||||
|
||||
|
||||
def run_cmd(cmd):
|
||||
"""Execute a shell command and return output."""
|
||||
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
return result.stdout.strip(), result.stderr.strip(), result.returncode
|
||||
|
||||
|
||||
def list_containers(all_containers=True):
|
||||
"""List Docker containers with detailed information."""
|
||||
flags = "-a" if all_containers else ""
|
||||
cmd = f"docker ps {flags} --no-trunc --format '{{{{json .}}}}'"
|
||||
stdout, _, rc = run_cmd(cmd)
|
||||
containers = []
|
||||
if rc == 0 and stdout:
|
||||
for line in stdout.splitlines():
|
||||
try:
|
||||
containers.append(json.loads(line))
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
return containers
|
||||
|
||||
|
||||
def inspect_container(container_id):
|
||||
"""Get detailed container inspection data."""
|
||||
stdout, _, rc = run_cmd(f"docker inspect {container_id}")
|
||||
if rc == 0 and stdout:
|
||||
return json.loads(stdout)
|
||||
return None
|
||||
|
||||
|
||||
def analyze_security_config(inspect_data):
|
||||
"""Analyze container security configuration for misconfigurations."""
|
||||
if isinstance(inspect_data, list):
|
||||
inspect_data = inspect_data[0]
|
||||
findings = []
|
||||
host_config = inspect_data.get("HostConfig", {})
|
||||
config = inspect_data.get("Config", {})
|
||||
|
||||
if host_config.get("Privileged"):
|
||||
findings.append({"severity": "CRITICAL", "finding": "Container running in PRIVILEGED mode"})
|
||||
|
||||
cap_add = host_config.get("CapAdd") or []
|
||||
dangerous_caps = ["SYS_ADMIN", "SYS_PTRACE", "NET_ADMIN", "SYS_MODULE",
|
||||
"DAC_OVERRIDE", "NET_RAW"]
|
||||
for cap in cap_add:
|
||||
if cap in dangerous_caps:
|
||||
findings.append({"severity": "HIGH", "finding": f"Dangerous capability added: {cap}"})
|
||||
|
||||
if host_config.get("PidMode") == "host":
|
||||
findings.append({"severity": "HIGH", "finding": "Shares host PID namespace"})
|
||||
|
||||
if host_config.get("NetworkMode") == "host":
|
||||
findings.append({"severity": "HIGH", "finding": "Shares host network namespace"})
|
||||
|
||||
mounts = inspect_data.get("Mounts", [])
|
||||
sensitive_paths = ["/", "/etc", "/var", "/root", "/home", "/var/run/docker.sock"]
|
||||
for mount in mounts:
|
||||
src = mount.get("Source", "")
|
||||
rw = mount.get("RW", False)
|
||||
if src in sensitive_paths and rw:
|
||||
findings.append({
|
||||
"severity": "CRITICAL",
|
||||
"finding": f"Sensitive host path mounted RW: {src} -> {mount.get('Destination')}"
|
||||
})
|
||||
if "docker.sock" in src:
|
||||
findings.append({
|
||||
"severity": "CRITICAL",
|
||||
"finding": "Docker socket mounted (container can control Docker daemon)"
|
||||
})
|
||||
|
||||
user = config.get("User", "")
|
||||
if not user or user == "root":
|
||||
findings.append({"severity": "MEDIUM", "finding": "Running as root user"})
|
||||
|
||||
env_vars = config.get("Env", [])
|
||||
secret_keywords = ["PASSWORD", "SECRET", "KEY", "TOKEN", "CREDENTIAL", "API_KEY"]
|
||||
for env in env_vars:
|
||||
key = env.split("=")[0]
|
||||
if any(s in key.upper() for s in secret_keywords):
|
||||
findings.append({"severity": "HIGH", "finding": f"Sensitive env var exposed: {key}"})
|
||||
|
||||
return findings
|
||||
|
||||
|
||||
def get_filesystem_changes(container_id):
|
||||
"""Get filesystem changes between container and its image."""
|
||||
stdout, _, rc = run_cmd(f"docker diff {container_id}")
|
||||
changes = {"added": [], "changed": [], "deleted": []}
|
||||
if rc == 0 and stdout:
|
||||
for line in stdout.splitlines():
|
||||
line = line.strip()
|
||||
if line.startswith("A "):
|
||||
changes["added"].append(line[2:])
|
||||
elif line.startswith("C "):
|
||||
changes["changed"].append(line[2:])
|
||||
elif line.startswith("D "):
|
||||
changes["deleted"].append(line[2:])
|
||||
return changes
|
||||
|
||||
|
||||
def detect_suspicious_files(changes):
|
||||
"""Analyze filesystem changes for indicators of compromise."""
|
||||
suspicious_patterns = [
|
||||
"/tmp/", "/dev/shm/", "/root/", ".sh", ".py", ".elf",
|
||||
"reverse", "shell", "backdoor", "miner", "xmr", "nc ",
|
||||
".php", "webshell", "c2", "beacon",
|
||||
]
|
||||
suspicious_changes = ["/etc/passwd", "/etc/shadow", "/etc/crontab",
|
||||
"/etc/ssh", ".bashrc", "/etc/sudoers", "authorized_keys"]
|
||||
|
||||
findings = []
|
||||
for f in changes["added"]:
|
||||
for pattern in suspicious_patterns:
|
||||
if pattern in f.lower():
|
||||
findings.append({"type": "ADDED", "path": f, "reason": f"Matches pattern: {pattern}"})
|
||||
break
|
||||
for f in changes["changed"]:
|
||||
for pattern in suspicious_changes:
|
||||
if pattern in f.lower():
|
||||
findings.append({"type": "CHANGED", "path": f, "reason": f"Critical file modified"})
|
||||
break
|
||||
return findings
|
||||
|
||||
|
||||
def export_container(container_id, output_path):
|
||||
"""Export container filesystem as a tarball for offline analysis."""
|
||||
cmd = f"docker export {container_id} > {output_path}"
|
||||
_, _, rc = run_cmd(cmd)
|
||||
if rc == 0 and os.path.exists(output_path):
|
||||
sha256 = hashlib.sha256()
|
||||
with open(output_path, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(65536), b""):
|
||||
sha256.update(chunk)
|
||||
return True, sha256.hexdigest()
|
||||
return False, None
|
||||
|
||||
|
||||
def get_container_logs(container_id, tail=500):
|
||||
"""Retrieve container logs with timestamps."""
|
||||
stdout, stderr, rc = run_cmd(f"docker logs --timestamps --tail {tail} {container_id}")
|
||||
return stdout + "\n" + stderr if rc == 0 else None
|
||||
|
||||
|
||||
def scan_image_vulnerabilities(image_name):
|
||||
"""Run Trivy vulnerability scan on a container image."""
|
||||
cmd = f"trivy image --format json {image_name}"
|
||||
stdout, _, rc = run_cmd(cmd)
|
||||
if rc == 0 and stdout:
|
||||
try:
|
||||
return json.loads(stdout)
|
||||
except json.JSONDecodeError:
|
||||
return None
|
||||
return None
|
||||
|
||||
|
||||
def generate_report(container_id, inspect_data, security_findings,
|
||||
fs_changes, suspicious_files):
|
||||
"""Generate a forensic analysis report."""
|
||||
container_name = "unknown"
|
||||
image = "unknown"
|
||||
if inspect_data:
|
||||
data = inspect_data[0] if isinstance(inspect_data, list) else inspect_data
|
||||
container_name = data.get("Name", "").lstrip("/")
|
||||
image = data.get("Config", {}).get("Image", "unknown")
|
||||
|
||||
report = {
|
||||
"report_type": "Docker Container Forensics",
|
||||
"timestamp": datetime.datetime.utcnow().isoformat() + "Z",
|
||||
"container_id": container_id,
|
||||
"container_name": container_name,
|
||||
"image": image,
|
||||
"security_findings": security_findings,
|
||||
"filesystem_changes": {
|
||||
"added": len(fs_changes["added"]),
|
||||
"changed": len(fs_changes["changed"]),
|
||||
"deleted": len(fs_changes["deleted"]),
|
||||
},
|
||||
"suspicious_files": suspicious_files,
|
||||
}
|
||||
return report
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("Docker Container Forensics Agent")
|
||||
print("Security analysis, filesystem diffing, evidence collection")
|
||||
print("=" * 60)
|
||||
|
||||
container_id = sys.argv[1] if len(sys.argv) > 1 else None
|
||||
|
||||
if container_id:
|
||||
print(f"\n[*] Analyzing container: {container_id}")
|
||||
|
||||
inspect_data = inspect_container(container_id)
|
||||
if not inspect_data:
|
||||
print("[ERROR] Failed to inspect container. Is Docker running?")
|
||||
sys.exit(1)
|
||||
|
||||
print("\n--- Security Configuration Analysis ---")
|
||||
findings = analyze_security_config(inspect_data)
|
||||
for f in findings:
|
||||
print(f"[{f['severity']}] {f['finding']}")
|
||||
|
||||
print("\n--- Filesystem Changes ---")
|
||||
changes = get_filesystem_changes(container_id)
|
||||
print(f" Added: {len(changes['added'])}, Changed: {len(changes['changed'])}, "
|
||||
f"Deleted: {len(changes['deleted'])}")
|
||||
|
||||
print("\n--- Suspicious Files ---")
|
||||
suspicious = detect_suspicious_files(changes)
|
||||
for s in suspicious:
|
||||
print(f"[!] {s['type']}: {s['path']} ({s['reason']})")
|
||||
|
||||
report = generate_report(container_id, inspect_data, findings, changes, suspicious)
|
||||
print(f"\n[*] Report:\n{json.dumps(report, indent=2)}")
|
||||
else:
|
||||
print("\n[*] Listing all containers...")
|
||||
containers = list_containers()
|
||||
for c in containers:
|
||||
print(f" {c.get('ID', '?')[:12]} {c.get('Names', '?')} {c.get('Status', '?')}")
|
||||
print(f"\n[DEMO] Usage: python agent.py <container_id>")
|
||||
Reference in New Issue
Block a user