npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
Overview
Rapid7 InsightVM (formerly Nexpose) is an enterprise vulnerability management platform that combines on-premises scanning via Security Console and Scan Engines with cloud-based analytics through the Insight Platform. InsightVM leverages Rapid7's vulnerability research library, Metasploit exploit knowledge, global attacker behavior data, internet-wide scanning telemetry, and real-time reporting to provide comprehensive vulnerability visibility. This skill covers deploying the Security Console, configuring Scan Engines, setting up scan templates, credentialed scanning, and integrating with the Insight Agent for continuous assessment.
When to Use
- When deploying or configuring implementing rapid7 insightvm for scanning capabilities in your environment
- When establishing security controls aligned to compliance requirements
- When building or improving security architecture for this domain
- When conducting security assessments that require this implementation
Prerequisites
- Server meeting minimum requirements: 16 GB RAM, 4 CPU cores, 500 GB disk (Security Console)
- Scan Engine: 8 GB RAM, 4 CPU cores, 100 GB disk
- Network access to target subnets (ports vary by scan type)
- Administrative credentials for authenticated scanning (SSH, WMI, SNMP)
- Rapid7 InsightVM license and Insight Platform account
- PostgreSQL database (bundled with Security Console)
Core Concepts
InsightVM Architecture Components
Security Console
The central management server that:
- Hosts the web-based management interface (default port 3780)
- Stores scan results in an embedded PostgreSQL database
- Manages Scan Engine deployments and scan schedules
- Generates reports and dashboards
- Connects to Rapid7 Insight Platform for cloud analytics
Note: Security Console is NOT supported in containerized environments.
Scan Engines
Distributed scanning components that:
- Perform active network scanning against target assets
- Can be deployed across network segments for segmented environments
- Available as container images on Docker Hub for flexible deployment
- Report results back to the Security Console
Insight Agent
Lightweight endpoint agent providing:
- Continuous vulnerability assessment without network scans
- Assessment of remote/roaming endpoints
- Complement to engine-based scanning for comprehensive coverage
- Real-time asset inventory updates
Scan Template Types
| Template | Use Case | Depth |
|---|---|---|
| Discovery Scan | Asset inventory, host enumeration | Low |
| Full Audit without Web Spider | Standard vulnerability assessment | Medium |
| Full Audit Enhanced Logging | Deep assessment with verbose logging | High |
| HIPAA Compliance | Healthcare regulatory compliance | High |
| PCI ASV Audit | PCI DSS external scanning requirement | High |
| CIS Policy Compliance | Configuration benchmarking | Medium |
| Web Spider | Web application discovery and assessment | Medium |
Workflow
Step 1: Install Security Console
# Download InsightVM installer (Linux)
chmod +x Rapid7Setup-Linux64.bin
./Rapid7Setup-Linux64.bin -c
# Verify service is running
systemctl status nexposeconsole.service
# Access web interface
# https://<console-ip>:3780Initial configuration:
- Navigate to https://localhost:3780
- Complete the setup wizard with license key
- Configure database settings (embedded PostgreSQL recommended)
- Set administrator credentials
- Activate Insight Platform connection for cloud analytics
Step 2: Deploy Distributed Scan Engines
# Install Scan Engine on remote server
./Rapid7Setup-Linux64.bin -c
# During installation, select "Scan Engine only"
# Pair with Security Console using shared secret
# Docker-based Scan Engine deployment
docker pull rapid7/insightvm-scan-engine
docker run -d \
--name scan-engine \
-p 40814:40814 \
-e CONSOLE_HOST=<console-ip> \
-e CONSOLE_PORT=3780 \
-e ENGINE_NAME=DMZ-Scanner \
-e SHARED_SECRET=<pairing-secret> \
rapid7/insightvm-scan-enginePair engines in Security Console:
- Administration > Scan Engines > New Scan Engine
- Enter engine hostname/IP and port (default 40814)
- Use shared secret for authentication
- Verify connectivity status shows "Active"
Step 3: Configure Asset Discovery Sites
Site Configuration:
Name: Production-Network
Scan Engine: Primary-Engine-01
Scan Template: Full Audit without Web Spider
Included Assets:
- 10.0.0.0/8 (Internal network)
- 172.16.0.0/12 (DMZ network)
Excluded Assets:
- 10.0.0.1 (Core router - fragile)
- 10.0.100.0/24 (ICS/SCADA segment)
Schedule:
Frequency: Weekly
Day: Sunday
Time: 02:00 AM
Max Duration: 8 hoursStep 4: Configure Authenticated Scanning
Windows Credentials (WMI)
Credential Type: Microsoft Windows/Samba (SMB/CIFS)
Domain: CORP.EXAMPLE.COM
Username: svc_insightvm_scan
Password: <service-account-password>
Authentication: NTLM
Privilege Elevation:
Type: None (use domain admin or local admin)Linux/Unix Credentials (SSH)
Credential Type: Secure Shell (SSH)
Username: insightvm_scan
Authentication: SSH Key (preferred) or Password
SSH Private Key: /opt/rapid7/.ssh/scan_key
Port: 22
Privilege Elevation:
Type: sudo
sudo User: root
sudo Password: <sudo-password>Database Credentials
Credential Type: Microsoft SQL Server
Instance: MSSQLSERVER
Domain: CORP
Username: insightvm_db_scan
Authentication: Windows Authentication
Credential Type: Oracle
Port: 1521
SID: ORCL
Username: insightvm_scanStep 5: Configure Scan Templates
Custom scan template for balanced scanning:
Template Name: Enterprise-Standard-Scan
Service Discovery:
TCP Ports: Well-known (1-1024) + common services
UDP Ports: DNS(53), SNMP(161), NTP(123), TFTP(69)
Method: SYN scan (stealth)
Vulnerability Checks:
Safe checks only: Enabled
Skip potential: Disabled
Web spidering: Disabled (separate template)
Policy checks: Enabled (CIS benchmarks)
Performance:
Max parallel assets: 10
Max requests per second: 100
Timeout per asset: 30 minutes
Retries: 2Step 6: Set Up Insight Agent Deployment
# Windows Agent Installation (via GPO or SCCM)
msiexec /i agentInstaller-x86_64.msi /quiet /norestart `
CUSTOMTOKEN=<platform-token> `
CUSTOMCONFIG=<agent-config>
# Linux Agent Installation
chmod +x agent_installer.sh
./agent_installer.sh install_start \
--token <platform-token>
# Verify agent connectivity
# Check InsightVM console: Assets > Agent ManagementStep 7: Configure Remediation Workflows
Remediation Project:
Name: Q1-2025-Critical-Remediation
Scope:
Severity: Critical + High
CVSS Score: >= 7.0
Assets: Production-Network site
Assignment:
Team: Infrastructure-Ops
Due Date: 2025-03-31
Tracking:
Auto-verify: Enabled (re-scan on next scheduled scan)
Notification: Email on overdue items
Escalation: Manager notification at 75% SLAStep 8: API Integration for Automation
import requests
import json
class InsightVMClient:
"""Rapid7 InsightVM API v3 client for automation."""
def __init__(self, console_url, api_key):
self.base_url = f"{console_url}/api/3"
self.session = requests.Session()
self.session.headers.update({
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
})
self.session.verify = not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true" # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
def get_sites(self):
"""List all configured scan sites."""
response = self.session.get(f"{self.base_url}/sites")
response.raise_for_status()
return response.json().get("resources", [])
def start_scan(self, site_id, engine_id=None, template_id=None):
"""Trigger an ad-hoc scan for a site."""
payload = {}
if engine_id:
payload["engineId"] = engine_id
if template_id:
payload["templateId"] = template_id
response = self.session.post(
f"{self.base_url}/sites/{site_id}/scans",
json=payload
)
response.raise_for_status()
return response.json()
def get_asset_vulnerabilities(self, asset_id):
"""Retrieve vulnerabilities for a specific asset."""
response = self.session.get(
f"{self.base_url}/assets/{asset_id}/vulnerabilities"
)
response.raise_for_status()
return response.json().get("resources", [])
def get_scan_status(self, scan_id):
"""Check the status of a running scan."""
response = self.session.get(f"{self.base_url}/scans/{scan_id}")
response.raise_for_status()
return response.json()
def create_remediation_project(self, name, description, assets, vulns):
"""Create a remediation tracking project."""
payload = {
"name": name,
"description": description,
"assets": {"includedTargets": {"addresses": assets}},
"vulnerabilities": {"includedVulnerabilities": vulns}
}
response = self.session.post(
f"{self.base_url}/remediations",
json=payload
)
response.raise_for_status()
return response.json()
# Usage
client = InsightVMClient("https://insightvm-console:3780", "api-key-here")
sites = client.get_sites()
for site in sites:
print(f"Site: {site['name']} - Assets: {site.get('assets', 0)}")Best Practices
- Deploy Scan Engines close to target networks to minimize scan traffic traversing firewalls
- Use Insight Agents for roaming laptops and remote workers that are not always reachable by network scans
- Combine agent-based and engine-based scanning for the most accurate vulnerability view
- Configure scan blackout windows during business-critical hours to avoid operational impact
- Use credential testing before full scans to validate authentication works
- Enable safe checks to prevent accidental denial of service on production systems
- Separate scan sites by network segment, business unit, or compliance scope
- Leverage tag-based asset groups for dynamic reporting and remediation tracking
Common Pitfalls
- Running full scans during business hours causing network congestion or service degradation
- Using unauthenticated scans only, missing 60-80% of local vulnerabilities
- Not excluding fragile devices (printers, ICS/SCADA, medical devices) from aggressive scan templates
- Failing to distribute Scan Engines across network segments, causing firewall bottlenecks
- Ignoring scan engine resource utilization leading to incomplete scans
- Not configuring scan duration limits, allowing runaway scans to consume resources indefinitely
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 3
api-reference.md4.6 KB
API Reference: Rapid7 InsightVM Vulnerability Scanning
Libraries Used
| Library | Purpose |
|---|---|
requests |
HTTP client for InsightVM REST API v3 |
json |
Parse scan results and vulnerability data |
base64 |
Encode Basic Auth credentials |
os |
Read INSIGHTVM_URL, INSIGHTVM_USER, INSIGHTVM_PASS |
Installation
pip install requestsAuthentication
InsightVM API v3 uses HTTP Basic Authentication:
import requests
import os
from requests.auth import HTTPBasicAuth
INSIGHTVM_URL = os.environ.get("INSIGHTVM_URL", "https://insightvm.example.com:3780")
auth = HTTPBasicAuth(
os.environ["INSIGHTVM_USER"],
os.environ["INSIGHTVM_PASS"],
)REST API v3 Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/3/sites |
List all scan sites |
| GET | /api/3/sites/{id} |
Get site details |
| POST | /api/3/sites |
Create a new site |
| GET | /api/3/sites/{id}/assets |
List assets in a site |
| POST | /api/3/sites/{id}/scans |
Launch a scan on a site |
| GET | /api/3/scans |
List all scans |
| GET | /api/3/scans/{id} |
Get scan status and details |
| GET | /api/3/assets |
List all assets |
| GET | /api/3/assets/{id} |
Get asset details |
| GET | /api/3/assets/{id}/vulnerabilities |
Get vulnerabilities for asset |
| GET | /api/3/vulnerabilities |
List all known vulnerabilities |
| GET | /api/3/vulnerabilities/{id} |
Get vulnerability details |
| GET | /api/3/vulnerability_checks |
List vulnerability checks |
| GET | /api/3/scan_engines |
List scan engines |
| GET | /api/3/reports |
List generated reports |
| POST | /api/3/reports |
Create a report configuration |
| POST | /api/3/reports/{id}/generate |
Generate a report |
| GET | /api/3/tags |
List all tags |
| GET | /api/3/policies |
List compliance policies |
Core Operations
List Sites
resp = requests.get(
f"{INSIGHTVM_URL}/api/3/sites",
auth=auth,
params={"page": 0, "size": 100},
timeout=30,
verify=True,
)
for site in resp.json().get("resources", []):
print(f"Site: {site['name']} (ID: {site['id']}) — {site.get('description', '')}")Launch a Scan
resp = requests.post(
f"{INSIGHTVM_URL}/api/3/sites/{site_id}/scans",
auth=auth,
json={"engineId": engine_id},
timeout=30,
verify=True,
)
scan_id = resp.json()["id"]Poll Scan Status
import time
while True:
resp = requests.get(
f"{INSIGHTVM_URL}/api/3/scans/{scan_id}",
auth=auth,
timeout=30,
verify=True,
)
status = resp.json()["status"]
if status in ("finished", "stopped", "error"):
break
time.sleep(30)Get Asset Vulnerabilities
resp = requests.get(
f"{INSIGHTVM_URL}/api/3/assets/{asset_id}/vulnerabilities",
auth=auth,
params={"page": 0, "size": 500},
timeout=60,
verify=True,
)
vulns = resp.json().get("resources", [])
for v in vulns:
print(f" {v['id']} — CVSS: {v.get('cvssV3Score', 'N/A')} — {v.get('status')}")Get Vulnerability Details
resp = requests.get(
f"{INSIGHTVM_URL}/api/3/vulnerabilities/{vuln_id}",
auth=auth,
timeout=30,
verify=True,
)
vuln = resp.json()
# Fields: title, description, cvss, severity, publishedDate, references, exploitsGenerate a Report
report_config = {
"name": "Monthly Vuln Report",
"format": "pdf",
"scope": {"sites": [site_id]},
"template": "audit-report",
}
resp = requests.post(
f"{INSIGHTVM_URL}/api/3/reports",
auth=auth,
json=report_config,
timeout=30,
verify=True,
)
report_id = resp.json()["id"]
# Generate the report
requests.post(
f"{INSIGHTVM_URL}/api/3/reports/{report_id}/generate",
auth=auth,
timeout=30,
verify=True,
)Pagination
All list endpoints support cursor-based pagination:
def paginate(endpoint, auth, params=None):
params = params or {}
params.setdefault("size", 500)
page = 0
while True:
params["page"] = page
resp = requests.get(endpoint, auth=auth, params=params, timeout=60, verify=True)
data = resp.json()
yield from data.get("resources", [])
if page >= data.get("page", {}).get("totalPages", 1) - 1:
break
page += 1Output Format
{
"id": 12345,
"status": "finished",
"vulnerabilities": {
"critical": 3,
"severe": 12,
"moderate": 45,
"total": 60
},
"assets": 128,
"startTime": "2025-01-15T08:00:00Z",
"endTime": "2025-01-15T09:45:00Z",
"engineName": "Local Scan Engine"
}standards.md1.5 KB
Standards and References - Rapid7 InsightVM
Official Documentation
- InsightVM Product Page: https://www.rapid7.com/products/insightvm/
- InsightVM Quick Start Guide: https://docs.rapid7.com/insightvm/insightvm-quick-start-guide/
- InsightVM System Requirements: https://docs.rapid7.com/insightvm/system-requirements/
- InsightVM API v3 Documentation: https://help.rapid7.com/insightvm/en-us/api/index.html
- Insight Agent Documentation: https://docs.rapid7.com/insightvm/using-the-insight-agent-with-insightvm/
Scan Configuration References
- Scan Templates: https://docs.rapid7.com/insightvm/selecting-vulnerability-checks/
- Credential Configuration: https://docs.rapid7.com/insightvm/configuring-scan-credentials/
- Scan Scheduling: https://docs.rapid7.com/insightvm/configuring-scan-schedules/
Industry Standards
- NIST SP 800-115: Technical Guide to Information Security Testing and Assessment
- NIST SP 800-40 Rev 4: Guide to Enterprise Patch Management Planning
- PCI DSS v4.0 Req 11.3: External and internal vulnerability scanning
- CIS Controls v8.1 Control 7: Continuous Vulnerability Management
- ISO 27001:2022 A.8.8: Management of technical vulnerabilities
Compliance Scan Templates
| Standard | InsightVM Template | Frequency |
|---|---|---|
| PCI DSS | PCI ASV External Audit | Quarterly |
| HIPAA | HIPAA Compliance | Quarterly |
| CIS Benchmarks | CIS Policy Compliance | Monthly |
| DISA STIG | DISA STIG Compliance | Monthly |
| NIST 800-53 | Full Audit Enhanced | Quarterly |
workflows.md5.7 KB
Workflows - Rapid7 InsightVM Deployment
Workflow 1: InsightVM Deployment Pipeline
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Install Security │────>│ Deploy Scan │────>│ Pair Engines │
│ Console │ │ Engines │ │ with Console │
└──────────────────┘ └──────────────────┘ └──────────────────┘
│
┌────────────────────────────────────────────────┘
v
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Configure Scan │────>│ Set Up Credential│────>│ Create Sites & │
│ Templates │ │ Store │ │ Asset Groups │
└──────────────────┘ └──────────────────┘ └──────────────────┘
│
v
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Schedule Scans │────>│ Deploy Insight │────>│ Configure │
│ │ │ Agents │ │ Reports & Alerts │
└──────────────────┘ └──────────────────┘ └──────────────────┘Workflow 2: Scan Execution Cycle
For each scheduled scan:
1. Console dispatches scan job to assigned Scan Engine
2. Engine performs host discovery (ARP, ICMP, TCP SYN)
3. Engine fingerprints OS and services on discovered hosts
4. Engine selects vulnerability checks based on fingerprint
5. If credentials configured: authenticate and perform local checks
6. Engine reports findings back to Console database
7. Console correlates with previous scan data (new/fixed/unchanged)
8. Console updates risk scores and remediation projects
9. Notifications sent for new critical/high findings
10. Dashboard and reports refreshed automaticallyWorkflow 3: Hybrid Scanning Strategy
┌─────────────────────────────────────────────────────┐
│ Enterprise Network │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ Engine Scan ┌────────────────┐ │
│ │ Data Center │ <───────────── │ DC Scan Engine │ │
│ │ Servers │ └────────────────┘ │
│ └──────────────┘ │
│ │
│ ┌──────────────┐ Engine Scan ┌────────────────┐ │
│ │ DMZ Servers │ <───────────── │ DMZ Scan Engine│ │
│ └──────────────┘ └────────────────┘ │
│ │
│ ┌──────────────┐ Agent-Based ┌────────────────┐ │
│ │ Laptops / │ <───────────── │ Insight Agent │ │
│ │ Remote Users │ │ (on endpoint) │ │
│ └──────────────┘ └────────────────┘ │
│ │
│ ┌──────────────┐ Agent-Based ┌────────────────┐ │
│ │ Cloud VMs │ <───────────── │ Insight Agent │ │
│ │ (AWS/Azure) │ │ (on instance) │ │
│ └──────────────┘ └────────────────┘ │
│ │
│ All results ──> Security Console │
│ ──> Insight Platform (Cloud) │
└─────────────────────────────────────────────────────┘Workflow 4: Remediation Tracking
| Phase | Action | Owner | Timeline |
|---|---|---|---|
| Discovery | Scan identifies vulnerability | InsightVM | Automated |
| Triage | Severity confirmed, assigned to team | Security Ops | 24 hours |
| Remediation | Patch/config change applied | IT Operations | Per SLA |
| Validation | Re-scan confirms fix | InsightVM | Next scan cycle |
| Closure | Remediation project updated | Security Ops | Automated |
Scripts 2
agent.py9.1 KB
#!/usr/bin/env python3
"""Rapid7 InsightVM vulnerability scanning agent.
Interfaces with the InsightVM (Nexpose) REST API to manage scan
configurations, launch scans, retrieve vulnerability results, and
generate remediation reports. Supports site management, asset
discovery, and vulnerability prioritization.
"""
import argparse
import json
import os
import sys
import time
from datetime import datetime, timezone
try:
import requests
from requests.auth import HTTPBasicAuth
except ImportError:
print("[!] 'requests' required: pip install requests", file=sys.stderr)
sys.exit(1)
def get_insightvm_config():
"""Return InsightVM API connection config."""
host = os.environ.get("INSIGHTVM_HOST", "localhost")
port = os.environ.get("INSIGHTVM_PORT", "3780")
user = os.environ.get("INSIGHTVM_USER", "")
password = os.environ.get("INSIGHTVM_PASSWORD", "")
return f"https://{host}:{port}", user, password
def api_call(base_url, endpoint, user, password, method="GET",
data=None, params=None):
"""Make authenticated API call to InsightVM."""
url = f"{base_url}/api/3{endpoint}"
auth = HTTPBasicAuth(user, password)
headers = {"Content-Type": "application/json", "Accept": "application/json"}
if method == "POST":
resp = requests.post(url, auth=auth, headers=headers, json=data,
params=params,
verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=60) # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
elif method == "PUT":
resp = requests.put(url, auth=auth, headers=headers, json=data,
verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=60) # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
else:
resp = requests.get(url, auth=auth, headers=headers, params=params,
verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=60) # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
resp.raise_for_status()
return resp.json()
def list_sites(base_url, user, password):
"""List all scan sites."""
print("[*] Listing sites...")
data = api_call(base_url, "/sites", user, password, params={"size": 500})
sites = []
for site in data.get("resources", []):
sites.append({
"id": site.get("id"),
"name": site.get("name", ""),
"description": site.get("description", ""),
"type": site.get("type", ""),
"assets": site.get("assets", 0),
"last_scan_time": site.get("lastScanTime", ""),
"risk_score": site.get("riskScore", 0),
})
print(f"[+] Found {len(sites)} sites")
return sites
def get_site_vulnerabilities(base_url, user, password, site_id):
"""Get vulnerabilities for a specific site."""
print(f"[*] Fetching vulnerabilities for site {site_id}...")
vulns = []
page = 0
while True:
data = api_call(base_url, f"/sites/{site_id}/vulnerabilities",
user, password, params={"page": page, "size": 100})
resources = data.get("resources", [])
if not resources:
break
for v in resources:
vulns.append({
"id": v.get("id", ""),
"title": v.get("title", ""),
"severity": v.get("severity", ""),
"cvss_v3_score": v.get("cvss", {}).get("v3", {}).get("score", 0),
"risk_score": v.get("riskScore", 0),
"instances": v.get("instances", 0),
"status": v.get("status", ""),
})
page += 1
total_pages = data.get("page", {}).get("totalPages", 1)
if page >= total_pages:
break
print(f"[+] Retrieved {len(vulns)} vulnerabilities")
return vulns
def launch_scan(base_url, user, password, site_id, scan_name=None):
"""Launch a scan on a site."""
if not scan_name:
scan_name = f"agent-scan-{datetime.now(timezone.utc).strftime('%Y%m%d-%H%M%S')}"
print(f"[*] Launching scan '{scan_name}' on site {site_id}...")
data = api_call(base_url, f"/sites/{site_id}/scans", user, password,
method="POST", data={"name": scan_name})
scan_id = data.get("id")
print(f"[+] Scan started, ID: {scan_id}")
return scan_id
def poll_scan_status(base_url, user, password, scan_id, max_wait=1800):
"""Poll scan status until completion."""
print(f"[*] Waiting for scan {scan_id} to complete...")
elapsed = 0
interval = 30
while elapsed < max_wait:
data = api_call(base_url, f"/scans/{scan_id}", user, password)
status = data.get("status", "unknown")
if status in ("finished", "stopped", "error"):
print(f"[+] Scan {status}")
return status, data
print(f" Status: {status} ({elapsed}s)")
time.sleep(interval)
elapsed += interval
print("[!] Scan timed out")
return "timeout", {}
def get_scan_report(base_url, user, password, scan_id):
"""Get scan results summary."""
data = api_call(base_url, f"/scans/{scan_id}", user, password)
return {
"scan_id": scan_id,
"status": data.get("status", ""),
"start_time": data.get("startTime", ""),
"end_time": data.get("endTime", ""),
"duration": data.get("duration", ""),
"assets_discovered": data.get("assets", 0),
"vulnerabilities": data.get("vulnerabilities", {}),
}
def format_summary(sites, vulns=None, scan_report=None):
"""Print summary."""
print(f"\n{'='*60}")
print(f" Rapid7 InsightVM Report")
print(f"{'='*60}")
if sites:
print(f"\n Sites ({len(sites)}):")
for s in sites:
print(f" {s['name']:30s} | Assets: {s['assets']:5d} | "
f"Risk: {s['risk_score']:8.1f}")
if vulns:
severity_counts = {}
for v in vulns:
sev = v.get("severity", "unknown")
severity_counts[sev] = severity_counts.get(sev, 0) + 1
print(f"\n Vulnerabilities ({len(vulns)}):")
for sev in sorted(severity_counts.keys()):
print(f" {sev:15s}: {severity_counts[sev]}")
if scan_report:
print(f"\n Scan Report:")
print(f" Status : {scan_report.get('status', 'N/A')}")
print(f" Assets : {scan_report.get('assets_discovered', 0)}")
def main():
parser = argparse.ArgumentParser(description="Rapid7 InsightVM scanning agent")
sub = parser.add_subparsers(dest="command")
sub.add_parser("list-sites", help="List scan sites")
p_vulns = sub.add_parser("get-vulns", help="Get site vulnerabilities")
p_vulns.add_argument("--site-id", required=True, type=int)
p_scan = sub.add_parser("scan", help="Launch a scan")
p_scan.add_argument("--site-id", required=True, type=int)
p_scan.add_argument("--wait", action="store_true", help="Wait for completion")
p_scan.add_argument("--max-wait", type=int, default=1800)
parser.add_argument("--host", help="InsightVM host (or INSIGHTVM_HOST env)")
parser.add_argument("--user", help="Username (or INSIGHTVM_USER env)")
parser.add_argument("--password", help="Password (or INSIGHTVM_PASSWORD env)")
parser.add_argument("--output", "-o", help="Output JSON report")
parser.add_argument("--verbose", "-v", action="store_true")
args = parser.parse_args()
if not args.command:
parser.print_help()
sys.exit(1)
if args.host:
os.environ["INSIGHTVM_HOST"] = args.host
if args.user:
os.environ["INSIGHTVM_USER"] = args.user
if args.password:
os.environ["INSIGHTVM_PASSWORD"] = args.password
base_url, user, password = get_insightvm_config()
if not user or not password:
print("[!] Set INSIGHTVM_USER and INSIGHTVM_PASSWORD", file=sys.stderr)
sys.exit(1)
result = {}
if args.command == "list-sites":
sites = list_sites(base_url, user, password)
format_summary(sites)
result = {"sites": sites}
elif args.command == "get-vulns":
vulns = get_site_vulnerabilities(base_url, user, password, args.site_id)
format_summary([], vulns)
result = {"site_id": args.site_id, "vulnerabilities": vulns}
elif args.command == "scan":
scan_id = launch_scan(base_url, user, password, args.site_id)
if args.wait:
status, data = poll_scan_status(base_url, user, password, scan_id, args.max_wait)
scan_report = get_scan_report(base_url, user, password, scan_id)
format_summary([], scan_report=scan_report)
result = {"scan_id": scan_id, "report": scan_report}
else:
result = {"scan_id": scan_id, "status": "launched"}
report = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"tool": "Rapid7 InsightVM",
"command": args.command,
"result": result,
}
if args.output:
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
print(f"\n[+] Report saved to {args.output}")
elif args.verbose:
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()
process.py11.7 KB
#!/usr/bin/env python3
"""
Rapid7 InsightVM Scan Automation and Reporting Tool
Automates scan operations, asset queries, and vulnerability reporting
via the InsightVM API v3.
Requirements:
pip install requests pandas tabulate
Usage:
python process.py sites # List all sites
python process.py scan --site-id 1 # Start scan for site
python process.py status --scan-id 12345 # Check scan status
python process.py vulns --asset-id 42 # Get asset vulnerabilities
python process.py report --site-id 1 --output report.csv # Export report
"""
import argparse
import json
import os
import sys
import time
import urllib3
from datetime import datetime
import pandas as pd
import requests
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class InsightVMAPI:
"""Rapid7 InsightVM API v3 client."""
def __init__(self, console_url, username=None, password=None, api_key=None):
self.base_url = f"{console_url.rstrip('/')}/api/3"
self.session = requests.Session()
self.session.verify = not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true" # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
if api_key:
self.session.headers.update({
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
})
elif username and password:
self.session.auth = (username, password)
self.session.headers.update({"Content-Type": "application/json"})
else:
raise ValueError("Provide either api_key or username/password")
def _get_paginated(self, endpoint, params=None):
"""Fetch all pages from a paginated endpoint."""
all_resources = []
page = 0
while True:
p = params.copy() if params else {}
p["page"] = page
p["size"] = 100
response = self.session.get(
f"{self.base_url}/{endpoint}", params=p, timeout=60
)
response.raise_for_status()
data = response.json()
resources = data.get("resources", [])
all_resources.extend(resources)
total_pages = data.get("page", {}).get("totalPages", 1)
page += 1
if page >= total_pages:
break
return all_resources
def list_sites(self):
"""List all scan sites."""
return self._get_paginated("sites")
def get_site(self, site_id):
"""Get details for a specific site."""
response = self.session.get(
f"{self.base_url}/sites/{site_id}", timeout=30
)
response.raise_for_status()
return response.json()
def start_scan(self, site_id, engine_id=None, template_id=None, hosts=None):
"""Start a scan for a site."""
payload = {}
if engine_id:
payload["engineId"] = engine_id
if template_id:
payload["templateId"] = template_id
if hosts:
payload["hosts"] = hosts
response = self.session.post(
f"{self.base_url}/sites/{site_id}/scans",
json=payload, timeout=30
)
response.raise_for_status()
return response.json()
def get_scan_status(self, scan_id):
"""Get the status of a scan."""
response = self.session.get(
f"{self.base_url}/scans/{scan_id}", timeout=30
)
response.raise_for_status()
return response.json()
def wait_for_scan(self, scan_id, poll_interval=30, timeout=3600):
"""Wait for a scan to complete."""
start_time = time.time()
while time.time() - start_time < timeout:
status = self.get_scan_status(scan_id)
state = status.get("status", "unknown")
print(f" Scan {scan_id}: {state} "
f"({status.get('assets', 0)} assets, "
f"{status.get('vulnerabilities', {}).get('total', 0)} vulns)")
if state in ("finished", "stopped", "error", "aborted"):
return status
time.sleep(poll_interval)
print(f" [!] Scan timeout after {timeout}s")
return None
def get_site_assets(self, site_id):
"""Get all assets for a site."""
return self._get_paginated(f"sites/{site_id}/assets")
def get_asset_vulnerabilities(self, asset_id):
"""Get vulnerabilities for a specific asset."""
return self._get_paginated(f"assets/{asset_id}/vulnerabilities")
def get_vulnerability_details(self, vuln_id):
"""Get details for a specific vulnerability."""
response = self.session.get(
f"{self.base_url}/vulnerabilities/{vuln_id}", timeout=30
)
response.raise_for_status()
return response.json()
def list_scan_engines(self):
"""List all scan engines."""
return self._get_paginated("scan_engines")
def list_scan_templates(self):
"""List available scan templates."""
return self._get_paginated("scan_templates")
def cmd_list_sites(api):
"""List all configured sites."""
sites = api.list_sites()
if not sites:
print("No sites configured.")
return
print(f"\n{'ID':<6} {'Name':<35} {'Assets':<10} {'Last Scan':<20}")
print("-" * 75)
for site in sites:
last_scan = site.get("lastScanTime", "Never")
if last_scan != "Never":
last_scan = last_scan[:19]
print(f"{site['id']:<6} {site['name'][:34]:<35} "
f"{site.get('assets', 0):<10} {last_scan:<20}")
def cmd_start_scan(api, site_id, engine_id=None, template_id=None, wait=False):
"""Start a scan for a site."""
print(f"[*] Starting scan for site {site_id}...")
result = api.start_scan(site_id, engine_id, template_id)
scan_id = result.get("id")
print(f"[+] Scan started: ID={scan_id}")
if wait and scan_id:
print("[*] Waiting for scan to complete...")
final_status = api.wait_for_scan(scan_id)
if final_status:
print(f"\n[+] Scan completed: {final_status.get('status')}")
vulns = final_status.get("vulnerabilities", {})
print(f" Total vulnerabilities: {vulns.get('total', 0)}")
print(f" Critical: {vulns.get('critical', 0)}")
print(f" Severe: {vulns.get('severe', 0)}")
print(f" Moderate: {vulns.get('moderate', 0)}")
def cmd_scan_status(api, scan_id):
"""Check scan status."""
status = api.get_scan_status(scan_id)
print(f"\nScan ID: {status.get('id')}")
print(f"Status: {status.get('status')}")
print(f"Start Time: {status.get('startTime', 'N/A')}")
print(f"End Time: {status.get('endTime', 'N/A')}")
print(f"Assets: {status.get('assets', 0)}")
vulns = status.get("vulnerabilities", {})
print(f"Vulns Total: {vulns.get('total', 0)}")
print(f" Critical: {vulns.get('critical', 0)}")
print(f" Severe: {vulns.get('severe', 0)}")
print(f" Moderate: {vulns.get('moderate', 0)}")
def cmd_asset_vulns(api, asset_id):
"""List vulnerabilities for an asset."""
vulns = api.get_asset_vulnerabilities(asset_id)
if not vulns:
print(f"No vulnerabilities found for asset {asset_id}.")
return
print(f"\nVulnerabilities for asset {asset_id}: {len(vulns)} total\n")
print(f"{'Vuln ID':<40} {'Severity':<10} {'CVSS':<8} {'Status':<12}")
print("-" * 72)
for v in sorted(vulns, key=lambda x: x.get("severity", ""), reverse=True):
print(f"{v.get('id', 'N/A')[:39]:<40} "
f"{v.get('severity', 'N/A'):<10} "
f"{v.get('cvssV3Score', 'N/A'):<8} "
f"{v.get('status', 'N/A'):<12}")
def cmd_export_report(api, site_id, output_file):
"""Export vulnerability report for a site to CSV."""
print(f"[*] Fetching assets for site {site_id}...")
assets = api.get_site_assets(site_id)
print(f"[+] Found {len(assets)} assets")
all_findings = []
for asset in assets:
asset_id = asset.get("id")
hostname = asset.get("hostName", asset.get("ip", "unknown"))
ip = asset.get("ip", "N/A")
os_name = asset.get("os", {}).get("description", "Unknown")
vulns = api.get_asset_vulnerabilities(asset_id)
for v in vulns:
all_findings.append({
"asset_id": asset_id,
"hostname": hostname,
"ip_address": ip,
"os": os_name,
"vulnerability_id": v.get("id", ""),
"severity": v.get("severity", ""),
"cvss_v3_score": v.get("cvssV3Score", ""),
"status": v.get("status", ""),
"first_found": v.get("since", ""),
})
print(f" Processed {hostname}: {len(vulns)} vulnerabilities")
if all_findings:
df = pd.DataFrame(all_findings)
df = df.sort_values(["cvss_v3_score", "severity"], ascending=[False, False])
df.to_csv(output_file, index=False)
print(f"\n[+] Report exported to {output_file}")
print(f" Total findings: {len(all_findings)}")
print(f"\n Severity Distribution:")
print(df["severity"].value_counts().to_string())
else:
print("[!] No findings to export.")
def main():
parser = argparse.ArgumentParser(
description="Rapid7 InsightVM Scan Automation Tool"
)
parser.add_argument("--console", default="https://localhost:3780",
help="InsightVM console URL")
parser.add_argument("--username", help="Console username")
parser.add_argument("--password", help="Console password")
parser.add_argument("--api-key", help="API key (alternative to user/pass)")
subparsers = parser.add_subparsers(dest="command")
subparsers.add_parser("sites", help="List all scan sites")
scan_p = subparsers.add_parser("scan", help="Start a scan")
scan_p.add_argument("--site-id", type=int, required=True)
scan_p.add_argument("--engine-id", type=int)
scan_p.add_argument("--template-id", type=str)
scan_p.add_argument("--wait", action="store_true")
status_p = subparsers.add_parser("status", help="Check scan status")
status_p.add_argument("--scan-id", type=int, required=True)
vuln_p = subparsers.add_parser("vulns", help="List asset vulnerabilities")
vuln_p.add_argument("--asset-id", type=int, required=True)
report_p = subparsers.add_parser("report", help="Export vulnerability report")
report_p.add_argument("--site-id", type=int, required=True)
report_p.add_argument("--output", default="insightvm_report.csv")
subparsers.add_parser("engines", help="List scan engines")
subparsers.add_parser("templates", help="List scan templates")
args = parser.parse_args()
if not args.command:
parser.print_help()
sys.exit(1)
api = InsightVMAPI(
args.console,
username=args.username,
password=args.password,
api_key=args.api_key
)
if args.command == "sites":
cmd_list_sites(api)
elif args.command == "scan":
cmd_start_scan(api, args.site_id, args.engine_id,
args.template_id, args.wait)
elif args.command == "status":
cmd_scan_status(api, args.scan_id)
elif args.command == "vulns":
cmd_asset_vulns(api, args.asset_id)
elif args.command == "report":
cmd_export_report(api, args.site_id, args.output)
elif args.command == "engines":
engines = api.list_scan_engines()
for e in engines:
print(f" Engine {e['id']}: {e['name']} - {e.get('address', 'N/A')}")
elif args.command == "templates":
templates = api.list_scan_templates()
for t in templates:
print(f" {t['id']}: {t['name']}")
if __name__ == "__main__":
main()