mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-12 14:14:56 +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
242 lines
8.4 KiB
Python
242 lines
8.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for performing IoT security assessment.
|
|
|
|
Automates IoT device reconnaissance, firmware extraction with binwalk,
|
|
network traffic analysis, and service scanning for security testing.
|
|
"""
|
|
|
|
import subprocess
|
|
import json
|
|
import sys
|
|
import hashlib
|
|
from pathlib import Path
|
|
|
|
|
|
class IoTSecurityAgent:
|
|
"""Performs automated IoT device security assessments."""
|
|
|
|
def __init__(self, target_ip, output_dir):
|
|
self.target_ip = target_ip
|
|
self.output_dir = Path(output_dir)
|
|
self.output_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
def scan_services(self):
|
|
"""Scan target for open services using nmap."""
|
|
result = subprocess.run(
|
|
["nmap", "-sV", "-sC", "-p-", "-oJ", "-", self.target_ip],
|
|
capture_output=True, text=True, timeout=300,
|
|
)
|
|
services = []
|
|
for line in result.stdout.splitlines():
|
|
if "/tcp" in line or "/udp" in line:
|
|
parts = line.split()
|
|
if len(parts) >= 3:
|
|
services.append({
|
|
"port": parts[0],
|
|
"state": parts[1],
|
|
"service": " ".join(parts[2:]),
|
|
})
|
|
return {"target": self.target_ip, "services": services, "raw": result.stdout}
|
|
|
|
def check_default_credentials(self):
|
|
"""Test common default credentials against discovered services."""
|
|
default_creds = [
|
|
("admin", "admin"), ("admin", "password"), ("admin", "1234"),
|
|
("root", "root"), ("root", "admin"), ("root", "password"),
|
|
("admin", ""), ("user", "user"), ("guest", "guest"),
|
|
]
|
|
results = []
|
|
for username, password in default_creds:
|
|
result = subprocess.run(
|
|
["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}",
|
|
"-u", f"{username}:{password}",
|
|
f"http://{self.target_ip}/", "--max-time", "5"],
|
|
capture_output=True, text=True,
|
|
timeout=120,
|
|
)
|
|
status = result.stdout.strip()
|
|
if status in ("200", "301", "302"):
|
|
results.append({
|
|
"username": username,
|
|
"password": password,
|
|
"status": status,
|
|
"vulnerable": True,
|
|
})
|
|
return results
|
|
|
|
def analyze_firmware(self, firmware_path):
|
|
"""Analyze firmware image with binwalk."""
|
|
fw_path = Path(firmware_path)
|
|
if not fw_path.exists():
|
|
return {"error": f"Firmware file not found: {firmware_path}"}
|
|
|
|
sha256 = hashlib.sha256(fw_path.read_bytes()).hexdigest()
|
|
scan_result = subprocess.run(
|
|
["binwalk", str(fw_path)], capture_output=True, text=True,
|
|
timeout=120,
|
|
)
|
|
extract_dir = self.output_dir / "firmware_extracted"
|
|
subprocess.run(
|
|
["binwalk", "-eM", "-C", str(extract_dir), str(fw_path)],
|
|
capture_output=True, text=True,
|
|
timeout=120,
|
|
)
|
|
|
|
creds_found = []
|
|
for root, dirs, files in (extract_dir).rglob("*") if extract_dir.exists() else []:
|
|
pass
|
|
|
|
if extract_dir.exists():
|
|
grep_result = subprocess.run(
|
|
["grep", "-rn", "-i", "password\\|passwd\\|secret",
|
|
str(extract_dir)],
|
|
capture_output=True, text=True,
|
|
timeout=120,
|
|
)
|
|
for line in grep_result.stdout.splitlines()[:20]:
|
|
creds_found.append(line.strip())
|
|
|
|
return {
|
|
"sha256": sha256,
|
|
"size": fw_path.stat().st_size,
|
|
"binwalk_scan": scan_result.stdout,
|
|
"credentials_found": creds_found,
|
|
"extract_dir": str(extract_dir),
|
|
}
|
|
|
|
def capture_traffic(self, interface="eth0", duration=30):
|
|
"""Capture network traffic from the IoT device."""
|
|
pcap_path = self.output_dir / "iot_capture.pcap"
|
|
subprocess.run(
|
|
["timeout", str(duration), "tcpdump", "-i", interface,
|
|
f"host {self.target_ip}", "-w", str(pcap_path)],
|
|
capture_output=True, timeout=duration + 10,
|
|
)
|
|
if pcap_path.exists():
|
|
stats = subprocess.run(
|
|
["capinfos", str(pcap_path)], capture_output=True, text=True,
|
|
timeout=120,
|
|
)
|
|
return {"pcap": str(pcap_path), "stats": stats.stdout}
|
|
return {"error": "Capture failed"}
|
|
|
|
def check_tls_configuration(self, port=443):
|
|
"""Check TLS configuration on HTTPS services."""
|
|
result = subprocess.run(
|
|
["openssl", "s_client", "-connect", f"{self.target_ip}:{port}",
|
|
"-brief"],
|
|
input="", capture_output=True, text=True, timeout=10,
|
|
)
|
|
tls_info = {
|
|
"raw": result.stdout + result.stderr,
|
|
"self_signed": "self signed" in (result.stdout + result.stderr).lower(),
|
|
}
|
|
|
|
for line in (result.stdout + result.stderr).splitlines():
|
|
if "Protocol" in line:
|
|
tls_info["protocol"] = line.strip()
|
|
if "Cipher" in line:
|
|
tls_info["cipher"] = line.strip()
|
|
return tls_info
|
|
|
|
def check_upnp_exposure(self):
|
|
"""Check for UPnP service exposure."""
|
|
result = subprocess.run(
|
|
["nmap", "-sU", "-p", "1900", "--script=upnp-info", self.target_ip],
|
|
capture_output=True, text=True, timeout=30,
|
|
)
|
|
return {
|
|
"upnp_detected": "upnp" in result.stdout.lower(),
|
|
"output": result.stdout,
|
|
}
|
|
|
|
def check_mqtt(self, port=1883):
|
|
"""Check for unauthenticated MQTT access."""
|
|
try:
|
|
import paho.mqtt.client as mqtt
|
|
connected = False
|
|
topics = []
|
|
|
|
def on_connect(client, userdata, flags, rc):
|
|
nonlocal connected
|
|
connected = rc == 0
|
|
if connected:
|
|
client.subscribe("#")
|
|
|
|
def on_message(client, userdata, msg):
|
|
topics.append({"topic": msg.topic, "payload_len": len(msg.payload)})
|
|
|
|
client = mqtt.Client()
|
|
client.on_connect = on_connect
|
|
client.on_message = on_message
|
|
client.connect(self.target_ip, port, 5)
|
|
client.loop_start()
|
|
import time
|
|
time.sleep(5)
|
|
client.loop_stop()
|
|
client.disconnect()
|
|
|
|
return {
|
|
"unauthenticated_access": connected,
|
|
"topics_found": len(topics),
|
|
"sample_topics": topics[:10],
|
|
}
|
|
except Exception as e:
|
|
return {"error": str(e)}
|
|
|
|
def generate_report(self, firmware_path=None):
|
|
"""Run full IoT security assessment and generate report."""
|
|
report = {"target": self.target_ip, "findings": []}
|
|
|
|
services = self.scan_services()
|
|
report["services"] = services
|
|
|
|
creds = self.check_default_credentials()
|
|
if creds:
|
|
report["findings"].append({
|
|
"id": "IOT-001", "severity": "Critical",
|
|
"title": "Default Credentials Accepted",
|
|
"details": creds,
|
|
})
|
|
|
|
tls = self.check_tls_configuration()
|
|
if tls.get("self_signed"):
|
|
report["findings"].append({
|
|
"id": "IOT-002", "severity": "Medium",
|
|
"title": "Self-Signed TLS Certificate",
|
|
"details": tls,
|
|
})
|
|
|
|
if firmware_path:
|
|
fw = self.analyze_firmware(firmware_path)
|
|
report["firmware_analysis"] = fw
|
|
if fw.get("credentials_found"):
|
|
report["findings"].append({
|
|
"id": "IOT-003", "severity": "Critical",
|
|
"title": "Hardcoded Credentials in Firmware",
|
|
"count": len(fw["credentials_found"]),
|
|
})
|
|
|
|
report_path = self.output_dir / "iot_assessment_report.json"
|
|
with open(report_path, "w") as f:
|
|
json.dump(report, f, indent=2)
|
|
print(json.dumps(report, indent=2))
|
|
return report
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) < 3:
|
|
print("Usage: agent.py <target_ip> <output_dir> [firmware_path]")
|
|
sys.exit(1)
|
|
|
|
target_ip = sys.argv[1]
|
|
output_dir = sys.argv[2]
|
|
firmware_path = sys.argv[3] if len(sys.argv) > 3 else None
|
|
|
|
agent = IoTSecurityAgent(target_ip, output_dir)
|
|
agent.generate_report(firmware_path)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|