mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-24 13:40:57 +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,62 @@
|
||||
# API Reference: SMB Vulnerability Assessment Agent
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Library | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| impacket | >=0.11.0 | SMB connection, negotiation, share enumeration |
|
||||
|
||||
## CLI Usage
|
||||
|
||||
```bash
|
||||
python scripts/agent.py \
|
||||
--targets 10.10.0.0/24 \
|
||||
--username testuser --password 'P@ss' --domain CORP \
|
||||
--output smb_report.json
|
||||
```
|
||||
|
||||
## Functions
|
||||
|
||||
### `check_smb_port(target, port, timeout) -> bool`
|
||||
TCP connect check on port 445.
|
||||
|
||||
### `enumerate_smb(target, username, password, domain) -> dict`
|
||||
Connects via `SMBConnection`, checks signing status, enumerates OS info and shares. Tests null session if no credentials provided.
|
||||
|
||||
### `scan_network(targets, username, password, domain) -> list`
|
||||
Iterates over targets calling `enumerate_smb` on each.
|
||||
|
||||
### `find_relay_targets(results) -> list`
|
||||
Returns IPs where `isSigningRequired()` returns `False` (vulnerable to NTLM relay).
|
||||
|
||||
### `check_null_sessions(results) -> list`
|
||||
Returns IPs accepting anonymous SMB connections.
|
||||
|
||||
### `expand_cidr(cidr) -> list`
|
||||
Expands CIDR notation to individual host IPs using `ipaddress.ip_network`.
|
||||
|
||||
### `generate_report(results) -> dict`
|
||||
Compiles findings: signing status, null sessions, accessible shares, risk summary.
|
||||
|
||||
## Impacket SMBConnection Methods
|
||||
|
||||
| Method | Purpose |
|
||||
|--------|---------|
|
||||
| `SMBConnection(host, host)` | Initialize SMB connection |
|
||||
| `negotiateSession()` | Negotiate SMB dialect |
|
||||
| `isSigningRequired()` | Check if message signing is enforced |
|
||||
| `login(user, pass, domain)` | Authenticate with credentials |
|
||||
| `listShares()` | Enumerate available SMB shares |
|
||||
| `getServerOS()` | Retrieve OS version string |
|
||||
|
||||
## Output Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"smb_hosts_found": 15,
|
||||
"signing_disabled_hosts": ["10.10.0.5", "10.10.0.12"],
|
||||
"null_session_hosts": ["10.10.0.5"],
|
||||
"accessible_shares": [{"host": "10.10.0.5", "share": "Users"}],
|
||||
"findings": ["HIGH: 2/15 hosts have SMB signing disabled"]
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env python3
|
||||
# For authorized testing in lab/CTF environments only
|
||||
"""SMB vulnerability assessment agent using Impacket for enumeration and signing checks."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
try:
|
||||
from impacket.smbconnection import SMBConnection
|
||||
from impacket.nmb import NetBIOSTimeout
|
||||
from impacket import smbconnection
|
||||
except ImportError:
|
||||
sys.exit("impacket is required: pip install impacket")
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def check_smb_port(target: str, port: int = 445, timeout: int = 5) -> bool:
|
||||
"""Check if SMB port is open on the target."""
|
||||
import socket
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.settimeout(timeout)
|
||||
s.connect((target, port))
|
||||
s.close()
|
||||
return True
|
||||
except (socket.timeout, ConnectionRefusedError, OSError):
|
||||
return False
|
||||
|
||||
|
||||
def enumerate_smb(target: str, username: str = "", password: str = "",
|
||||
domain: str = "") -> dict:
|
||||
"""Enumerate SMB service information on a target host."""
|
||||
result = {
|
||||
"target": target,
|
||||
"port_open": check_smb_port(target),
|
||||
"os_info": "",
|
||||
"smb_version": "",
|
||||
"signing_required": True,
|
||||
"shares": [],
|
||||
"error": None,
|
||||
}
|
||||
if not result["port_open"]:
|
||||
result["error"] = "SMB port 445 not reachable"
|
||||
return result
|
||||
|
||||
try:
|
||||
smb = SMBConnection(target, target, sess_port=445, timeout=10)
|
||||
smb.negotiateSession()
|
||||
result["signing_required"] = smb.isSigningRequired()
|
||||
result["smb_version"] = f"SMBv{smb.getDialect()}"
|
||||
|
||||
if username:
|
||||
smb.login(username, password, domain)
|
||||
result["os_info"] = smb.getServerOS()
|
||||
shares = smb.listShares()
|
||||
for share in shares:
|
||||
share_name = share["shi1_netname"][:-1]
|
||||
share_type = share["shi1_type"]
|
||||
result["shares"].append({
|
||||
"name": share_name,
|
||||
"type": share_type,
|
||||
"remark": share["shi1_remark"][:-1] if share["shi1_remark"] else "",
|
||||
})
|
||||
smb.logoff()
|
||||
else:
|
||||
try:
|
||||
smb.login("", "")
|
||||
result["null_session"] = True
|
||||
shares = smb.listShares()
|
||||
for share in shares:
|
||||
result["shares"].append({"name": share["shi1_netname"][:-1]})
|
||||
smb.logoff()
|
||||
except Exception:
|
||||
result["null_session"] = False
|
||||
|
||||
smb.close()
|
||||
except Exception as exc:
|
||||
result["error"] = str(exc)
|
||||
logger.warning("SMB enum failed on %s: %s", target, exc)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def scan_network(targets: List[str], username: str = "", password: str = "",
|
||||
domain: str = "") -> List[dict]:
|
||||
"""Scan multiple targets for SMB services."""
|
||||
results = []
|
||||
for target in targets:
|
||||
logger.info("Scanning %s...", target)
|
||||
info = enumerate_smb(target, username, password, domain)
|
||||
results.append(info)
|
||||
return results
|
||||
|
||||
|
||||
def find_relay_targets(results: List[dict]) -> List[str]:
|
||||
"""Identify hosts where SMB signing is not required (relay targets)."""
|
||||
targets = [r["target"] for r in results if not r.get("signing_required", True) and r["port_open"]]
|
||||
logger.info("Found %d SMB relay targets (signing disabled)", len(targets))
|
||||
return targets
|
||||
|
||||
|
||||
def check_null_sessions(results: List[dict]) -> List[str]:
|
||||
"""Identify hosts accepting null SMB sessions."""
|
||||
return [r["target"] for r in results if r.get("null_session")]
|
||||
|
||||
|
||||
def generate_report(results: List[dict]) -> dict:
|
||||
"""Generate SMB vulnerability assessment report."""
|
||||
smb_hosts = [r for r in results if r["port_open"]]
|
||||
relay_targets = find_relay_targets(results)
|
||||
null_hosts = check_null_sessions(results)
|
||||
|
||||
findings = []
|
||||
if relay_targets:
|
||||
findings.append(
|
||||
f"HIGH: {len(relay_targets)}/{len(smb_hosts)} hosts have SMB signing disabled"
|
||||
)
|
||||
if null_hosts:
|
||||
findings.append(
|
||||
f"MEDIUM: {len(null_hosts)} hosts accept null SMB sessions"
|
||||
)
|
||||
|
||||
all_shares = []
|
||||
for r in smb_hosts:
|
||||
for s in r.get("shares", []):
|
||||
all_shares.append({"host": r["target"], "share": s["name"]})
|
||||
|
||||
return {
|
||||
"assessment_date": datetime.utcnow().isoformat(),
|
||||
"total_targets_scanned": len(results),
|
||||
"smb_hosts_found": len(smb_hosts),
|
||||
"signing_disabled_hosts": relay_targets,
|
||||
"null_session_hosts": null_hosts,
|
||||
"accessible_shares": all_shares,
|
||||
"findings": findings,
|
||||
}
|
||||
|
||||
|
||||
def expand_cidr(cidr: str) -> List[str]:
|
||||
"""Expand a CIDR range to individual IPs (supports /24 and smaller)."""
|
||||
import ipaddress
|
||||
try:
|
||||
network = ipaddress.ip_network(cidr, strict=False)
|
||||
return [str(ip) for ip in network.hosts()]
|
||||
except ValueError:
|
||||
return [cidr]
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="SMB Vulnerability Assessment Agent")
|
||||
parser.add_argument("--targets", nargs="+", required=True, help="Target IPs or CIDR ranges")
|
||||
parser.add_argument("--username", default="", help="Domain username")
|
||||
parser.add_argument("--password", default="", help="Password")
|
||||
parser.add_argument("--domain", default="", help="Domain name")
|
||||
parser.add_argument("--output", default="smb_report.json")
|
||||
args = parser.parse_args()
|
||||
|
||||
all_targets = []
|
||||
for t in args.targets:
|
||||
all_targets.extend(expand_cidr(t))
|
||||
|
||||
results = scan_network(all_targets, args.username, args.password, args.domain)
|
||||
report = generate_report(results)
|
||||
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
logger.info("Report saved to %s", args.output)
|
||||
print(json.dumps(report, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user