mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-06 10:50:19 +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,57 @@
|
||||
# API Reference: Web Application Scanning with Nikto
|
||||
|
||||
## Nikto CLI Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-h <host>` | Target hostname or IP |
|
||||
| `-port <ports>` | Target ports (comma-separated) |
|
||||
| `-ssl` | Force SSL/TLS connection |
|
||||
| `-Format xml\|json\|csv\|htm` | Output format |
|
||||
| `-output <file>` | Save results to file |
|
||||
| `-Tuning <options>` | Scan tuning categories |
|
||||
| `-Plugins <list>` | Specific plugins to run |
|
||||
| `-maxtime <seconds>s` | Maximum scan duration |
|
||||
| `-nointeractive` | Disable interactive prompts |
|
||||
| `-useproxy <url>` | Use HTTP proxy |
|
||||
| `-id <user:pass>` | HTTP Basic auth credentials |
|
||||
|
||||
## Tuning Categories
|
||||
|
||||
| Code | Category |
|
||||
|------|----------|
|
||||
| 1 | Interesting File / Seen in logs |
|
||||
| 2 | Misconfiguration / Default File |
|
||||
| 3 | Information Disclosure |
|
||||
| 4 | Injection (XSS/Script/HTML) |
|
||||
| 5 | Remote File Retrieval - Inside Web Root |
|
||||
| 6 | Denial of Service |
|
||||
| 7 | Remote File Retrieval - Server Wide |
|
||||
| 8 | Command Execution / Remote Shell |
|
||||
| 9 | SQL Injection |
|
||||
| 0 | File Upload |
|
||||
|
||||
## XML Output Structure
|
||||
|
||||
| Element | Description |
|
||||
|---------|-------------|
|
||||
| `<niktoscan>` | Root element |
|
||||
| `<scandetails>` | Scan metadata |
|
||||
| `<item>` | Individual finding |
|
||||
| `<item id="..." osvdbid="...">` | Finding with OSVDB reference |
|
||||
| `<uri>` | Affected URI path |
|
||||
| `<description>` | Finding description |
|
||||
|
||||
## Python Libraries
|
||||
|
||||
| Library | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| `subprocess` | stdlib | Execute Nikto CLI |
|
||||
| `xml.etree.ElementTree` | stdlib | Parse Nikto XML output |
|
||||
| `json` | stdlib | Report generation |
|
||||
|
||||
## References
|
||||
|
||||
- Nikto GitHub: https://github.com/sullo/nikto
|
||||
- Nikto Documentation: https://cirt.net/Nikto2
|
||||
- OSVDB (archived): https://vulndb.cyberriskanalytics.com/
|
||||
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for web application scanning with Nikto.
|
||||
|
||||
Runs Nikto via subprocess for web server vulnerability scanning,
|
||||
parses XML/JSON output, classifies findings by OSVDB/CVE, and
|
||||
generates a structured security assessment report.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import json
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class NiktoScanAgent:
|
||||
"""Automates Nikto web vulnerability scanning and reporting."""
|
||||
|
||||
def __init__(self, target, output_dir="./nikto_scans"):
|
||||
self.target = target
|
||||
self.output_dir = Path(output_dir)
|
||||
self.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.findings = []
|
||||
|
||||
def run_scan(self, ports="80,443", tuning=None, plugins=None,
|
||||
ssl_mode=False, timeout=600):
|
||||
"""Execute Nikto scan against the target."""
|
||||
xml_output = self.output_dir / f"nikto_{self.target.replace('/', '_')}.xml"
|
||||
cmd = ["nikto", "-h", self.target, "-port", ports,
|
||||
"-Format", "xml", "-output", str(xml_output), "-nointeractive"]
|
||||
if ssl_mode:
|
||||
cmd.extend(["-ssl"])
|
||||
if tuning:
|
||||
cmd.extend(["-Tuning", tuning])
|
||||
if plugins:
|
||||
cmd.extend(["-Plugins", plugins])
|
||||
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True,
|
||||
timeout=timeout)
|
||||
return {"return_code": result.returncode,
|
||||
"xml_output": str(xml_output),
|
||||
"stderr": result.stderr[:500] if result.stderr else ""}
|
||||
except FileNotFoundError:
|
||||
return {"error": "nikto not installed. Install: apt install nikto"}
|
||||
except subprocess.TimeoutExpired:
|
||||
return {"error": f"Scan timed out after {timeout}s"}
|
||||
|
||||
def parse_xml_results(self, xml_path=None):
|
||||
"""Parse Nikto XML output into structured findings."""
|
||||
if xml_path is None:
|
||||
xml_path = self.output_dir / f"nikto_{self.target.replace('/', '_')}.xml"
|
||||
try:
|
||||
tree = ET.parse(xml_path)
|
||||
root = tree.getroot()
|
||||
except (ET.ParseError, FileNotFoundError) as exc:
|
||||
return {"error": str(exc)}
|
||||
|
||||
for item in root.iter("item"):
|
||||
finding = {
|
||||
"id": item.get("id", ""),
|
||||
"osvdb": item.get("osvdbid", ""),
|
||||
"method": item.get("method", "GET"),
|
||||
"uri": "",
|
||||
"description": "",
|
||||
"references": [],
|
||||
}
|
||||
uri_elem = item.find("uri")
|
||||
if uri_elem is not None:
|
||||
finding["uri"] = uri_elem.text or ""
|
||||
desc_elem = item.find("description")
|
||||
if desc_elem is not None:
|
||||
finding["description"] = desc_elem.text or ""
|
||||
|
||||
desc_lower = finding["description"].lower()
|
||||
if any(kw in desc_lower for kw in ["remote code", "rce", "command injection"]):
|
||||
finding["severity"] = "Critical"
|
||||
elif any(kw in desc_lower for kw in ["sql injection", "xss", "file inclusion"]):
|
||||
finding["severity"] = "High"
|
||||
elif any(kw in desc_lower for kw in ["directory listing", "information disclosure"]):
|
||||
finding["severity"] = "Medium"
|
||||
else:
|
||||
finding["severity"] = "Low"
|
||||
|
||||
self.findings.append(finding)
|
||||
return self.findings
|
||||
|
||||
def run_quick_scan(self, timeout=300):
|
||||
"""Run a fast Nikto scan with essential checks only."""
|
||||
cmd = ["nikto", "-h", self.target, "-Tuning", "123", "-maxtime",
|
||||
str(timeout) + "s", "-nointeractive"]
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True,
|
||||
timeout=timeout + 30)
|
||||
lines = result.stdout.splitlines()
|
||||
for line in lines:
|
||||
if "+ " in line and "OSVDB" in line:
|
||||
self.findings.append({
|
||||
"description": line.strip().lstrip("+ "),
|
||||
"severity": "Medium", "source": "stdout",
|
||||
})
|
||||
return {"lines": len(lines), "findings": len(self.findings)}
|
||||
except (FileNotFoundError, subprocess.TimeoutExpired) as exc:
|
||||
return {"error": str(exc)}
|
||||
|
||||
def generate_report(self):
|
||||
"""Generate scan report with severity distribution."""
|
||||
severity_counts = {}
|
||||
for f in self.findings:
|
||||
sev = f.get("severity", "Info")
|
||||
severity_counts[sev] = severity_counts.get(sev, 0) + 1
|
||||
|
||||
report = {
|
||||
"target": self.target,
|
||||
"scan_date": datetime.utcnow().isoformat(),
|
||||
"total_findings": len(self.findings),
|
||||
"severity_distribution": severity_counts,
|
||||
"findings": self.findings[:100],
|
||||
}
|
||||
report_path = self.output_dir / "nikto_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():
|
||||
target = sys.argv[1] if len(sys.argv) > 1 else "http://localhost"
|
||||
agent = NiktoScanAgent(target)
|
||||
result = agent.run_scan()
|
||||
if "error" not in result:
|
||||
agent.parse_xml_results()
|
||||
else:
|
||||
agent.run_quick_scan()
|
||||
agent.generate_report()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user