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,75 @@
|
||||
# API Reference: Vulnerability Scanning with Nessus Agent
|
||||
|
||||
## Overview
|
||||
|
||||
Manages Tenable Nessus vulnerability scans via the REST API: scan creation, launch, monitoring, result analysis, and CSV/PDF export.
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| requests | >= 2.28 | HTTP client for Nessus REST API |
|
||||
| urllib3 | >= 1.26 | TLS warning suppression |
|
||||
|
||||
## NessusAPI Class
|
||||
|
||||
### Constructor
|
||||
|
||||
```python
|
||||
NessusAPI(url="https://localhost:8834", access_key=None, secret_key=None)
|
||||
```
|
||||
|
||||
Authentication via `X-ApiKeys` header with access/secret key pair.
|
||||
|
||||
### Methods
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `get_server_status()` | Check Nessus server readiness | `dict` |
|
||||
| `list_scans()` | List all scans with id, name, status | `list[dict]` |
|
||||
| `get_scan_details(scan_id)` | Full scan results with severity counts and top vulns | `dict` |
|
||||
| `create_scan(name, targets, policy_id, template)` | Create new scan configuration | `dict` |
|
||||
| `launch_scan(scan_id)` | Start a configured scan | `dict` |
|
||||
| `get_scan_status(scan_id)` | Poll scan status | `str` |
|
||||
| `wait_for_scan(scan_id, poll_interval, timeout)` | Block until scan completes | `bool` |
|
||||
| `export_scan(scan_id, fmt)` | Export results as csv, html, or pdf | `bytes` |
|
||||
| `check_auth_status(scan_id)` | Verify authenticated scanning via plugin 19506 | `list[dict]` |
|
||||
|
||||
## Nessus REST API Endpoints
|
||||
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `/server/status` | GET | Server health check |
|
||||
| `/scans` | GET | List all scans |
|
||||
| `/scans` | POST | Create new scan |
|
||||
| `/scans/{id}` | GET | Scan details and results |
|
||||
| `/scans/{id}/launch` | POST | Launch scan |
|
||||
| `/scans/{id}/export` | POST | Initiate report export |
|
||||
| `/scans/{id}/export/{file_id}/download` | GET | Download exported report |
|
||||
| `/editor/scan/templates` | GET | Available scan templates |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `NESSUS_URL` | No | Nessus server URL (default: https://localhost:8834) |
|
||||
| `NESSUS_ACCESS_KEY` | Yes | API access key |
|
||||
| `NESSUS_SECRET_KEY` | Yes | API secret key |
|
||||
|
||||
## Severity Mapping
|
||||
|
||||
| Value | Label | CVSS Range |
|
||||
|-------|-------|------------|
|
||||
| 4 | Critical | 9.0-10.0 |
|
||||
| 3 | High | 7.0-8.9 |
|
||||
| 2 | Medium | 4.0-6.9 |
|
||||
| 1 | Low | 0.1-3.9 |
|
||||
| 0 | Info | N/A |
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
export NESSUS_ACCESS_KEY="your-access-key"
|
||||
export NESSUS_SECRET_KEY="your-secret-key"
|
||||
python agent.py
|
||||
```
|
||||
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Vulnerability scanning agent using the Nessus REST API."""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
import urllib3
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
print("Install: pip install requests")
|
||||
sys.exit(1)
|
||||
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
|
||||
|
||||
class NessusAPI:
|
||||
def __init__(self, url="https://localhost:8834", access_key=None, secret_key=None):
|
||||
self.url = url.rstrip("/")
|
||||
self.session = requests.Session()
|
||||
self.session.verify = False
|
||||
if access_key and secret_key:
|
||||
self.session.headers.update({
|
||||
"X-ApiKeys": f"accessKey={access_key}; secretKey={secret_key}"
|
||||
})
|
||||
|
||||
def _get(self, endpoint):
|
||||
resp = self.session.get(f"{self.url}{endpoint}")
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def _post(self, endpoint, data=None):
|
||||
resp = self.session.post(f"{self.url}{endpoint}", json=data)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def _put(self, endpoint, data=None):
|
||||
resp = self.session.put(f"{self.url}{endpoint}", json=data)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def get_server_status(self):
|
||||
return self._get("/server/status")
|
||||
|
||||
def list_scans(self):
|
||||
data = self._get("/scans")
|
||||
scans = []
|
||||
for scan in data.get("scans", []):
|
||||
scans.append({
|
||||
"id": scan["id"], "name": scan["name"],
|
||||
"status": scan["status"],
|
||||
"folder_id": scan.get("folder_id"),
|
||||
})
|
||||
return scans
|
||||
|
||||
def get_scan_details(self, scan_id):
|
||||
data = self._get(f"/scans/{scan_id}")
|
||||
info = data.get("info", {})
|
||||
hosts = data.get("hosts", [])
|
||||
vulns = data.get("vulnerabilities", [])
|
||||
return {
|
||||
"scan_id": scan_id,
|
||||
"name": info.get("name"),
|
||||
"status": info.get("status"),
|
||||
"host_count": info.get("hostcount", len(hosts)),
|
||||
"targets": info.get("targets"),
|
||||
"start_time": info.get("scanner_start"),
|
||||
"end_time": info.get("scanner_end"),
|
||||
"policy": info.get("policy"),
|
||||
"severity_counts": {
|
||||
"critical": sum(1 for v in vulns if v.get("severity") == 4),
|
||||
"high": sum(1 for v in vulns if v.get("severity") == 3),
|
||||
"medium": sum(1 for v in vulns if v.get("severity") == 2),
|
||||
"low": sum(1 for v in vulns if v.get("severity") == 1),
|
||||
"info": sum(1 for v in vulns if v.get("severity") == 0),
|
||||
},
|
||||
"vulnerabilities": [
|
||||
{
|
||||
"plugin_id": v["plugin_id"],
|
||||
"name": v["plugin_name"],
|
||||
"severity": v["severity"],
|
||||
"count": v["count"],
|
||||
"family": v.get("plugin_family"),
|
||||
}
|
||||
for v in sorted(vulns, key=lambda x: -x.get("severity", 0))[:50]
|
||||
],
|
||||
}
|
||||
|
||||
def create_scan(self, name, targets, policy_id=None, template="advanced"):
|
||||
templates = self._get("/editor/scan/templates")
|
||||
template_uuid = None
|
||||
for t in templates.get("templates", []):
|
||||
if t["name"] == template:
|
||||
template_uuid = t["uuid"]
|
||||
break
|
||||
if not template_uuid:
|
||||
template_uuid = templates["templates"][0]["uuid"]
|
||||
scan_config = {
|
||||
"uuid": template_uuid,
|
||||
"settings": {
|
||||
"name": name,
|
||||
"text_targets": targets,
|
||||
"launch_now": False,
|
||||
},
|
||||
}
|
||||
if policy_id:
|
||||
scan_config["settings"]["policy_id"] = policy_id
|
||||
return self._post("/scans", scan_config)
|
||||
|
||||
def launch_scan(self, scan_id):
|
||||
return self._post(f"/scans/{scan_id}/launch")
|
||||
|
||||
def get_scan_status(self, scan_id):
|
||||
data = self._get(f"/scans/{scan_id}")
|
||||
return data.get("info", {}).get("status", "unknown")
|
||||
|
||||
def wait_for_scan(self, scan_id, poll_interval=30, timeout=7200):
|
||||
elapsed = 0
|
||||
while elapsed < timeout:
|
||||
status = self.get_scan_status(scan_id)
|
||||
if status == "completed":
|
||||
return True
|
||||
if status in ("canceled", "aborted"):
|
||||
return False
|
||||
time.sleep(poll_interval)
|
||||
elapsed += poll_interval
|
||||
return False
|
||||
|
||||
def export_scan(self, scan_id, fmt="csv"):
|
||||
data = self._post(f"/scans/{scan_id}/export", {"format": fmt})
|
||||
file_id = data.get("file")
|
||||
if not file_id:
|
||||
return None
|
||||
while True:
|
||||
status = self._get(f"/scans/{scan_id}/export/{file_id}/status")
|
||||
if status.get("status") == "ready":
|
||||
break
|
||||
time.sleep(5)
|
||||
resp = self.session.get(f"{self.url}/scans/{scan_id}/export/{file_id}/download")
|
||||
return resp.content
|
||||
|
||||
def check_auth_status(self, scan_id):
|
||||
"""Check if authenticated scanning succeeded per host."""
|
||||
data = self._get(f"/scans/{scan_id}")
|
||||
auth_results = []
|
||||
for host in data.get("hosts", []):
|
||||
host_id = host["host_id"]
|
||||
host_detail = self._get(f"/scans/{scan_id}/hosts/{host_id}")
|
||||
auth_info = None
|
||||
for vuln in host_detail.get("vulnerabilities", []):
|
||||
if vuln["plugin_id"] == 19506:
|
||||
auth_info = vuln
|
||||
break
|
||||
auth_results.append({
|
||||
"hostname": host.get("hostname"),
|
||||
"host_id": host_id,
|
||||
"critical": host.get("critical", 0),
|
||||
"high": host.get("high", 0),
|
||||
"authenticated": auth_info is not None,
|
||||
})
|
||||
return auth_results
|
||||
|
||||
|
||||
def print_scan_report(details):
|
||||
print("Vulnerability Scan Report")
|
||||
print("=" * 50)
|
||||
print(f"Scan: {details['name']}")
|
||||
print(f"Status: {details['status']}")
|
||||
print(f"Hosts: {details['host_count']}")
|
||||
print(f"Targets: {details['targets']}")
|
||||
sev = details["severity_counts"]
|
||||
print(f"\nSeverity Summary:")
|
||||
print(f" Critical: {sev['critical']}")
|
||||
print(f" High: {sev['high']}")
|
||||
print(f" Medium: {sev['medium']}")
|
||||
print(f" Low: {sev['low']}")
|
||||
print(f" Info: {sev['info']}")
|
||||
print(f"\nTop Vulnerabilities:")
|
||||
for v in details["vulnerabilities"][:15]:
|
||||
sev_label = {4: "CRIT", 3: "HIGH", 2: "MED", 1: "LOW", 0: "INFO"}.get(v["severity"], "?")
|
||||
print(f" [{sev_label}] {v['name']} (plugin {v['plugin_id']}, count: {v['count']})")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
nessus_url = os.environ.get("NESSUS_URL", "https://localhost:8834")
|
||||
access_key = os.environ.get("NESSUS_ACCESS_KEY", "")
|
||||
secret_key = os.environ.get("NESSUS_SECRET_KEY", "")
|
||||
api = NessusAPI(nessus_url, access_key, secret_key)
|
||||
scans = api.list_scans()
|
||||
if scans:
|
||||
details = api.get_scan_details(scans[0]["id"])
|
||||
print_scan_report(details)
|
||||
else:
|
||||
print("No scans found. Create one with api.create_scan()")
|
||||
Reference in New Issue
Block a user