npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
Overview
Authenticated (credentialed) vulnerability scanning uses valid system credentials to log into target hosts and perform deep inspection of installed software, patches, configurations, and security settings. Compared to unauthenticated scanning, credentialed scans detect 45-60% more vulnerabilities with significantly fewer false positives because they can directly query installed packages, registry keys, and file system contents.
When to Use
- When conducting security assessments that involve performing authenticated vulnerability scan
- When following incident response procedures for related security events
- When performing scheduled security testing or auditing activities
- When validating security controls through hands-on testing
Prerequisites
- Vulnerability scanner (Nessus, Qualys, OpenVAS, Rapid7 InsightVM)
- Service accounts with appropriate privileges on target systems
- Secure credential storage (vault integration preferred)
- Network access from scanner to target management ports
- Written authorization from system owners
Core Concepts
Why Authenticated Scanning
Unauthenticated scanning can only assess externally visible services and banners, often leading to:
- Missed vulnerabilities in locally installed software
- Inaccurate version detection from banner changes
- Inability to check patch levels, configurations, or local policies
- Higher false positive rates due to inference-based detection
Authenticated scanning resolves these by directly querying the target OS.
Credential Types by Platform
Linux/Unix Systems
- SSH Key Authentication: RSA/Ed25519 key pairs (recommended)
- SSH Username/Password: Fallback for systems without key-based auth
- Sudo/Su Elevation: Non-root user with sudo privileges
- Certificate-based SSH: X.509 certificates for enterprise environments
Windows Systems
- SMB (Windows): Domain or local admin credentials
- WMI: Windows Management Instrumentation queries
- WinRM: Windows Remote Management (HTTPS preferred)
- Kerberos: Domain authentication with service tickets
Network Devices
- SNMP v3: USM with authentication and privacy (AES-256)
- SSH: For Cisco IOS, Juniper JunOS, Palo Alto PAN-OS
- API Tokens: REST API for modern network platforms
Databases
- Oracle: SYS/SYSDBA credentials or TNS connection
- Microsoft SQL Server: Windows auth or SQL auth
- PostgreSQL: Role-based authentication
- MySQL: User/password with SELECT privileges
Workflow
Step 1: Create Dedicated Service Accounts
# Linux: Create scan service account
sudo useradd -m -s /bin/bash -c "Vulnerability Scanner Service Account" nessus_svc
sudo usermod -aG sudo nessus_svc
# Configure sudo for passwordless specific commands
echo 'nessus_svc ALL=(ALL) NOPASSWD: /usr/bin/dpkg -l, /usr/bin/rpm -qa, \
/bin/cat /etc/shadow, /usr/sbin/dmidecode, /usr/bin/find' | sudo tee /etc/sudoers.d/nessus_svc
# Generate SSH key pair
sudo -u nessus_svc ssh-keygen -t ed25519 -f /home/nessus_svc/.ssh/id_ed25519 -N ""
# Distribute public key to targets
for host in $(cat target_hosts.txt); do
ssh-copy-id -i /home/nessus_svc/.ssh/id_ed25519.pub nessus_svc@$host
done# Windows: Create scan service account via PowerShell
New-ADUser -Name "SVC_VulnScan" `
-SamAccountName "SVC_VulnScan" `
-UserPrincipalName "SVC_VulnScan@domain.local" `
-Description "Vulnerability Scanner Service Account" `
-PasswordNeverExpires $true `
-CannotChangePassword $true `
-Enabled $true `
-AccountPassword (Read-Host -AsSecureString "Enter Password")
# Add to local Administrators group on targets via GPO or:
Add-ADGroupMember -Identity "Domain Admins" -Members "SVC_VulnScan"
# For least privilege, use a dedicated GPO for local admin rights instead
# Enable WinRM on targets
Enable-PSRemoting -Force
Set-Item WSMan:\localhost\Service\AllowRemote -Value $true
winrm set winrm/config/service '@{AllowUnencrypted="false"}'Step 2: Configure Scanner Credentials
Nessus Configuration
{
"credentials": {
"add": {
"Host": {
"SSH": [{
"auth_method": "public key",
"username": "nessus_svc",
"private_key": "/path/to/id_ed25519",
"elevate_privileges_with": "sudo",
"escalation_account": "root"
}],
"Windows": [{
"auth_method": "Password",
"username": "DOMAIN\\SVC_VulnScan",
"password": "stored_in_vault",
"domain": "domain.local"
}],
"SNMPv3": [{
"username": "nessus_snmpv3",
"security_level": "authPriv",
"auth_algorithm": "SHA-256",
"auth_password": "stored_in_vault",
"priv_algorithm": "AES-256",
"priv_password": "stored_in_vault"
}]
}
}
}
}Step 3: Validate Credential Access
# Test SSH connectivity
ssh -i /path/to/key -o ConnectTimeout=10 nessus_svc@target_host "uname -a && sudo dpkg -l | head -5"
# Test WinRM connectivity
python3 -c "
import winrm
s = winrm.Session('target_host', auth=('DOMAIN\\\\SVC_VulnScan', 'password'), transport='ntlm')
r = s.run_cmd('systeminfo')
print(r.std_out.decode())
"
# Test SNMP v3 connectivity
snmpwalk -v3 -u nessus_snmpv3 -l authPriv -a SHA-256 -A authpass -x AES-256 -X privpass target_host sysDescr.0Step 4: Run Authenticated Scan
Configure and launch the scan using the Nessus API:
# Create scan with credentials
curl -k -X POST https://nessus:8834/scans \
-H "X-Cookie: token=$TOKEN" \
-H "Content-Type: application/json" \
-d '{
"uuid": "'$TEMPLATE_UUID'",
"settings": {
"name": "Authenticated Scan - Production",
"text_targets": "192.168.1.0/24",
"launch": "ON_DEMAND"
},
"credentials": {
"add": {
"Host": {
"SSH": [{"auth_method": "public key", "username": "nessus_svc", "private_key": "/keys/id_ed25519"}],
"Windows": [{"auth_method": "Password", "username": "DOMAIN\\SVC_VulnScan", "password": "vault_ref"}]
}
}
}
}'Step 5: Verify Credential Success
After scan completion, check credential verification results:
- Plugin 19506 (Nessus Scan Information): Shows credential status
- Plugin 21745 (OS Security Patch Assessment): Confirms local checks
- Plugin 117887 (Local Security Checks): Credential verification
- Plugin 110385 (Nessus Credentialed Check): Target-level auth status
Credential Security Best Practices
- Use a secrets vault (HashiCorp Vault, CyberArk, AWS Secrets Manager) for credential storage
- Rotate credentials every 90 days or after personnel changes
- Principle of least privilege - only grant minimum required access
- Audit credential usage - monitor service account login events
- Encrypt in transit - use SSH keys over passwords, WinRM over HTTPS
- Separate accounts per scanner - never share credentials across tools
- Disable interactive login for scan service accounts where possible
- Log all authentication events for scan accounts in SIEM
Common Pitfalls
- Using domain admin accounts instead of least-privilege service accounts
- Storing credentials in plaintext scan configurations
- Not testing credentials before scan launch (leads to wasted scan windows)
- Forgetting to configure sudo/elevation for Linux targets
- Windows UAC blocking remote credentialed checks
- Firewall rules blocking WMI/WinRM/SSH between scanner and targets
- Credential lockout from multiple failed authentication attempts
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 3
api-reference.md2.0 KB
Authenticated Vulnerability Scan — API Reference
Libraries
| Library | Install | Purpose |
|---|---|---|
| requests | pip install requests |
Nessus REST API client |
Nessus REST API Authentication
Header: X-ApiKeys: accessKey=<key>; secretKey=<key>Nessus API Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /scans |
List all scans |
| GET | /scans/{id} |
Scan details with results |
| GET | /scans/{id}/hosts/{host_id} |
Per-host vulnerability details |
| POST | /scans |
Create new scan |
| POST | /scans/{id}/launch |
Launch existing scan |
| POST | /scans/{id}/export |
Export results (nessus/csv/html) |
| GET | /policies |
List scan policies |
| GET | /credentials |
List stored credentials |
Severity Levels
| Index | Name | 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 | Informational |
Credential Types for Authenticated Scans
| Type | Protocol | Checks Enabled |
|---|---|---|
| SSH | Linux/macOS | Package versions, file permissions, configs |
| SMB | Windows | Patch levels, registry, installed software |
| ESXi | VMware | Hypervisor patches, VM configurations |
| SNMP | Network devices | Device firmware, community string audit |
| Database | SQL Server/Oracle | DB-level patches, user permissions |
Key Nessus Plugin Families
| Family | Description |
|---|---|
| Windows: Microsoft Bulletins | Microsoft security patches |
| Ubuntu Local Security Checks | Ubuntu package vulnerabilities |
| CGI abuses | Web application vulnerabilities |
| Misc. | Miscellaneous security checks |
| Service detection | Network service identification |
External References
standards.md2.2 KB
Standards and References - Authenticated Vulnerability Scanning
Industry Standards
- NIST SP 800-115: Technical Guide to Information Security Testing and Assessment
- NIST SP 800-53 RA-5: Vulnerability Scanning (requires credentialed scanning for compliance)
- CIS Controls v8 Control 7.5: Perform automated vulnerability scans of internal assets on a quarterly basis using authenticated scanning
- PCI DSS v4.0 Req 11.3.1: Internal vulnerability scans must use authenticated scanning
- DISA STIG: Requires credentialed scanning for compliance validation
Credential Management Standards
- NIST SP 800-63B: Digital Identity Guidelines - Authentication and Lifecycle Management
- CIS Controls v8 Control 5: Account Management
- OWASP Credential Storage Cheat Sheet: Secure credential handling best practices
Scanner Documentation
- Nessus Credentialed Checks: https://docs.tenable.com/nessus/Content/CredentialedChecks.htm
- Qualys Authenticated Scanning: https://www.qualys.com/docs/qualys-scanning-best-practices.pdf
- OpenVAS Credential Management: https://docs.greenbone.net/
- Rapid7 InsightVM Credentials: https://docs.rapid7.com/insightvm/managing-shared-credentials/
Verification Plugins (Nessus)
| Plugin ID | Name | Purpose |
|---|---|---|
| 19506 | Nessus Scan Information | Shows scan metadata and credential status |
| 21745 | OS Security Patch Assessment | Confirms local security checks enabled |
| 117887 | Local Security Checks Enabled | Per-host credential verification |
| 110385 | Nessus Credentialed Check | Detailed credential success/failure |
| 10394 | Microsoft Windows SMB Log In Possible | Windows SMB auth verification |
| 10180 | Ping the Remote Host | Host reachability confirmation |
Minimum Privileges Required
| Platform | Minimum Privilege | Notes |
|---|---|---|
| Linux | Root or sudo user | Sudo with NOPASSWD for specific commands |
| Windows | Local Administrator | Or domain account with local admin GPO |
| Cisco IOS | Privilege 15 | Enable mode access required |
| SNMP | Read-only (v3 authPriv) | SNMPv3 with encryption |
| Oracle DB | SELECT ANY DICTIONARY | Minimum for audit queries |
| PostgreSQL | pg_read_all_settings | Read-only role sufficient |
workflows.md3.3 KB
Workflows - Authenticated Vulnerability Scanning
Workflow 1: Credential Preparation and Validation
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Create Service │────>│ Configure Least │────>│ Test Credentials │
│ Accounts │ │ Privilege Access │ │ on Sample Hosts │
└──────────────────┘ └──────────────────┘ └──────────────────┘
│
┌────────────────────────────────────────────────┘
v
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Store in Secrets │────>│ Configure Scanner│────>│ Validate Auth │
│ Vault │ │ Credentials │ │ Success Rate │
└──────────────────┘ └──────────────────┘ └──────────────────┘Workflow 2: Authenticated Scan Execution
- Pre-scan: Verify credentials, check network connectivity, confirm scan window
- Discovery: Host enumeration to identify live targets
- Authentication: Scanner authenticates to each target host
- Local Enumeration: Query installed packages, patches, configurations
- Vulnerability Assessment: Match local data against vulnerability database
- Report Generation: Compile findings with credential success metrics
- Post-scan: Verify no service disruption, archive results
Workflow 3: Credential Success Monitoring
Scan Completion
│
├──> Check Plugin 117887 (Local Security Checks)
│ │
│ ├──> SUCCESS: Proceed to analyze findings
│ └──> FAILURE: Investigate cause
│ │
│ ├──> Network connectivity issue
│ ├──> Credential expired or changed
│ ├──> Firewall blocking management ports
│ ├──> Account locked out
│ └──> Insufficient privileges
│
└──> Calculate Credential Success Rate
│
├──> Target: >95% authenticated hosts
├──> Alert if <90% success rate
└──> Document exceptions for failed hostsWorkflow 4: Credential Lifecycle Management
| Phase | Action | Frequency |
|---|---|---|
| Provisioning | Create accounts with least privilege | One-time |
| Distribution | Deploy keys/passwords to scanner | One-time |
| Validation | Test connectivity before scans | Per scan |
| Rotation | Change passwords, rotate keys | 90 days |
| Monitoring | Audit login events in SIEM | Continuous |
| Deprovisioning | Remove accounts when scanner retired | As needed |
Scripts 2
agent.py6.8 KB
#!/usr/bin/env python3
"""Authenticated vulnerability scan orchestration agent using Nessus API."""
import json
import os
import sys
import argparse
from datetime import datetime
try:
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
except ImportError:
print("Install: pip install requests")
sys.exit(1)
class NessusClient:
"""Client for Tenable Nessus REST API."""
def __init__(self, url, access_key, secret_key):
self.base_url = url.rstrip("/")
self.headers = {
"X-ApiKeys": f"accessKey={access_key}; secretKey={secret_key}",
"Content-Type": "application/json",
}
def _get(self, path, params=None):
resp = requests.get(f"{self.base_url}{path}", headers=self.headers,
params=params,
verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=30) # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
resp.raise_for_status()
return resp.json()
def _post(self, path, data=None):
resp = requests.post(f"{self.base_url}{path}", headers=self.headers,
json=data,
verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=30) # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
resp.raise_for_status()
return resp.json()
def list_scans(self):
return self._get("/scans").get("scans", [])
def get_scan_details(self, scan_id):
return self._get(f"/scans/{scan_id}")
def list_policies(self):
return self._get("/policies").get("policies", [])
def list_credentials(self):
return self._get("/credentials").get("credentials", [])
def get_scan_results(self, scan_id):
details = self.get_scan_details(scan_id)
hosts = details.get("hosts", [])
vulns = details.get("vulnerabilities", [])
return {"hosts": hosts, "vulnerabilities": vulns, "info": details.get("info", {})}
def get_host_vulnerabilities(self, scan_id, host_id):
return self._get(f"/scans/{scan_id}/hosts/{host_id}")
def export_scan(self, scan_id, fmt="nessus"):
data = {"format": fmt}
resp = self._post(f"/scans/{scan_id}/export", data)
return resp.get("file", 0)
def analyze_scan_results(results):
"""Analyze scan results and categorize findings."""
vulns = results.get("vulnerabilities", [])
severity_map = {0: "Info", 1: "Low", 2: "Medium", 3: "High", 4: "Critical"}
severity_counts = {"Critical": 0, "High": 0, "Medium": 0, "Low": 0, "Info": 0}
categorized = []
for v in vulns:
sev = severity_map.get(v.get("severity", 0), "Info")
severity_counts[sev] += 1
categorized.append({
"plugin_id": v.get("plugin_id", 0),
"plugin_name": v.get("plugin_name", ""),
"severity": sev,
"severity_index": v.get("severity", 0),
"count": v.get("count", 0),
"family": v.get("plugin_family", ""),
})
categorized.sort(key=lambda x: x["severity_index"], reverse=True)
return {"severity_counts": severity_counts, "vulnerabilities": categorized}
def audit_credential_coverage(results):
"""Check if authenticated scan achieved credential coverage."""
findings = []
hosts = results.get("hosts", [])
for host in hosts:
host_info = host.get("info", {})
credentialed = host.get("credentialed_checks_running", "")
if not credentialed or credentialed == "no":
findings.append({
"host": host.get("hostname", host.get("host_id", "")),
"issue": "Credentialed checks not running — scan is unauthenticated",
"severity": "HIGH",
"detail": "Configure valid credentials for this host",
})
return findings
def compare_auth_vs_unauth(auth_results, unauth_results):
"""Compare authenticated vs unauthenticated scan finding counts."""
auth_vulns = len(auth_results.get("vulnerabilities", []))
unauth_vulns = len(unauth_results.get("vulnerabilities", []))
improvement = ((auth_vulns - unauth_vulns) / max(unauth_vulns, 1)) * 100
return {
"authenticated_findings": auth_vulns,
"unauthenticated_findings": unauth_vulns,
"improvement_pct": round(improvement, 1),
"additional_findings": auth_vulns - unauth_vulns,
}
def run_audit(args):
"""Execute authenticated vulnerability scan audit."""
print(f"\n{'='*60}")
print(f" AUTHENTICATED VULNERABILITY SCAN AUDIT")
print(f" Generated: {datetime.utcnow().isoformat()} UTC")
print(f"{'='*60}\n")
client = NessusClient(args.nessus_url, args.access_key, args.secret_key)
report = {}
scans = client.list_scans()
report["total_scans"] = len(scans) if scans else 0
print(f"--- AVAILABLE SCANS ({report['total_scans']}) ---")
for s in (scans or [])[:10]:
print(f" [{s.get('status','')}] {s.get('name','')}: {s.get('id','')}")
if args.scan_id:
results = client.get_scan_results(args.scan_id)
analysis = analyze_scan_results(results)
report["analysis"] = analysis
counts = analysis["severity_counts"]
print(f"\n--- SCAN RESULTS (ID: {args.scan_id}) ---")
print(f" Critical: {counts['Critical']} | High: {counts['High']} | "
f"Medium: {counts['Medium']} | Low: {counts['Low']}")
print(f"\n--- TOP VULNERABILITIES ---")
for v in analysis["vulnerabilities"][:15]:
print(f" [{v['severity']}] {v['plugin_name'][:70]} (x{v['count']})")
cred_check = audit_credential_coverage(results)
report["credential_coverage"] = cred_check
if cred_check:
print(f"\n--- CREDENTIAL COVERAGE ISSUES ({len(cred_check)}) ---")
for c in cred_check:
print(f" [{c['severity']}] {c['host']}: {c['issue']}")
else:
print(f"\n Credential coverage: All hosts authenticated")
return report
def main():
parser = argparse.ArgumentParser(description="Authenticated Vulnerability Scan Agent")
parser.add_argument("--nessus-url", required=True, help="Nessus server URL")
parser.add_argument("--access-key", required=True, help="Nessus API access key")
parser.add_argument("--secret-key", required=True, help="Nessus API secret key")
parser.add_argument("--scan-id", type=int, help="Scan ID to analyze results")
parser.add_argument("--output", help="Save report to JSON file")
args = parser.parse_args()
report = run_audit(args)
if args.output:
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"\n[+] Report saved to {args.output}")
if __name__ == "__main__":
main()
process.py14.2 KB
#!/usr/bin/env python3
"""
Authenticated Vulnerability Scan Credential Validator and Manager
Pre-validates scanner credentials against target hosts before launching
vulnerability scans to ensure maximum authenticated coverage.
Requirements:
pip install paramiko pywinrm pysnmp pandas
Usage:
python process.py validate --targets targets.txt --creds creds.json
python process.py report --nessus-file scan_results.nessus
"""
import argparse
import json
import socket
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime
from pathlib import Path
import pandas as pd
try:
import paramiko
except ImportError:
paramiko = None
try:
import winrm
except ImportError:
winrm = None
class CredentialValidator:
"""Validate scanner credentials against target hosts."""
def __init__(self, timeout: int = 10):
self.timeout = timeout
self.results = []
def check_port(self, host: str, port: int) -> bool:
"""Check if a TCP port is open on the target host."""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(self.timeout)
result = sock.connect_ex((host, port))
sock.close()
return result == 0
except (socket.error, OSError):
return False
def validate_ssh(self, host: str, username: str, password: str = None,
key_file: str = None, port: int = 22) -> dict:
"""Validate SSH credentials against a target host."""
result = {
"host": host, "protocol": "SSH", "port": port,
"username": username, "status": "UNKNOWN", "details": ""
}
if not paramiko:
result["status"] = "SKIP"
result["details"] = "paramiko not installed"
return result
if not self.check_port(host, port):
result["status"] = "FAIL"
result["details"] = f"Port {port} not reachable"
return result
try:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
connect_kwargs = {
"hostname": host, "port": port, "username": username,
"timeout": self.timeout, "allow_agent": False, "look_for_keys": False
}
if key_file:
connect_kwargs["key_filename"] = key_file
elif password:
connect_kwargs["password"] = password
else:
result["status"] = "FAIL"
result["details"] = "No password or key file provided"
return result
client.connect(**connect_kwargs)
# Test command execution
_, stdout, stderr = client.exec_command("id && uname -a", timeout=10)
output = stdout.read().decode().strip()
error = stderr.read().decode().strip()
# Test sudo access
_, stdout_sudo, stderr_sudo = client.exec_command(
"sudo -n id 2>&1", timeout=10
)
sudo_output = stdout_sudo.read().decode().strip()
has_sudo = "uid=0" in sudo_output
client.close()
result["status"] = "SUCCESS"
result["details"] = f"Auth OK. Sudo: {'Yes' if has_sudo else 'No'}. {output[:100]}"
result["has_sudo"] = has_sudo
except paramiko.AuthenticationException:
result["status"] = "FAIL"
result["details"] = "Authentication failed - invalid credentials"
except paramiko.SSHException as e:
result["status"] = "FAIL"
result["details"] = f"SSH error: {str(e)[:100]}"
except Exception as e:
result["status"] = "FAIL"
result["details"] = f"Connection error: {str(e)[:100]}"
return result
def validate_winrm(self, host: str, username: str, password: str,
port: int = 5985, use_ssl: bool = False) -> dict:
"""Validate WinRM credentials against a Windows target."""
result = {
"host": host, "protocol": "WinRM", "port": port,
"username": username, "status": "UNKNOWN", "details": ""
}
if not winrm:
result["status"] = "SKIP"
result["details"] = "pywinrm not installed"
return result
check_port = 5986 if use_ssl else port
if not self.check_port(host, check_port):
result["status"] = "FAIL"
result["details"] = f"Port {check_port} not reachable"
return result
try:
scheme = "https" if use_ssl else "http"
session = winrm.Session(
f"{scheme}://{host}:{check_port}/wsman",
auth=(username, password),
transport="ntlm",
server_cert_validation="ignore" if use_ssl else "validate"
)
r = session.run_cmd("whoami")
output = r.std_out.decode().strip()
# Check admin privileges
r_admin = session.run_cmd("net", ["localgroup", "Administrators"])
admin_output = r_admin.std_out.decode()
is_admin = username.split("\\")[-1].lower() in admin_output.lower()
result["status"] = "SUCCESS"
result["details"] = f"Auth OK as {output}. Admin: {'Yes' if is_admin else 'No'}"
result["is_admin"] = is_admin
except Exception as e:
result["status"] = "FAIL"
result["details"] = f"WinRM error: {str(e)[:150]}"
return result
def validate_smb(self, host: str, username: str, password: str,
domain: str = "", port: int = 445) -> dict:
"""Validate SMB credentials against a Windows target."""
result = {
"host": host, "protocol": "SMB", "port": port,
"username": username, "status": "UNKNOWN", "details": ""
}
if not self.check_port(host, port):
result["status"] = "FAIL"
result["details"] = f"Port {port} not reachable"
return result
try:
from impacket.smbconnection import SMBConnection
conn = SMBConnection(host, host, sess_port=port)
conn.login(username, password, domain)
shares = conn.listShares()
share_names = [s["shi1_netname"].rstrip("\x00") for s in shares]
conn.logoff()
result["status"] = "SUCCESS"
result["details"] = f"Auth OK. Shares: {', '.join(share_names[:5])}"
except ImportError:
result["status"] = "SKIP"
result["details"] = "impacket not installed"
except Exception as e:
result["status"] = "FAIL"
result["details"] = f"SMB error: {str(e)[:150]}"
return result
def validate_snmpv3(self, host: str, username: str, auth_password: str,
priv_password: str, port: int = 161) -> dict:
"""Validate SNMPv3 credentials against a target."""
result = {
"host": host, "protocol": "SNMPv3", "port": port,
"username": username, "status": "UNKNOWN", "details": ""
}
try:
from pysnmp.hlapi import (
SnmpEngine, UsmUserData, UdpTransportTarget,
ContextData, ObjectType, ObjectIdentity, getCmd,
usmHMACSHAAuthProtocol, usmAesCfb128Protocol
)
iterator = getCmd(
SnmpEngine(),
UsmUserData(username, auth_password, priv_password,
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usmAesCfb128Protocol),
UdpTransportTarget((host, port), timeout=self.timeout),
ContextData(),
ObjectType(ObjectIdentity("SNMPv2-MIB", "sysDescr", 0))
)
errorIndication, errorStatus, errorIndex, varBinds = next(iterator)
if errorIndication:
result["status"] = "FAIL"
result["details"] = f"SNMP error: {errorIndication}"
elif errorStatus:
result["status"] = "FAIL"
result["details"] = f"SNMP status: {errorStatus.prettyPrint()}"
else:
for varBind in varBinds:
result["status"] = "SUCCESS"
result["details"] = f"Auth OK. sysDescr: {str(varBind[1])[:100]}"
except ImportError:
result["status"] = "SKIP"
result["details"] = "pysnmp not installed"
except Exception as e:
result["status"] = "FAIL"
result["details"] = f"SNMP error: {str(e)[:150]}"
return result
def validate_all(self, targets: list, credentials: dict, max_workers: int = 20) -> list:
"""Validate credentials against all targets in parallel."""
self.results = []
tasks = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
for target in targets:
host = target.strip()
if not host:
continue
# SSH validation
if "ssh" in credentials:
cred = credentials["ssh"]
tasks.append(executor.submit(
self.validate_ssh, host, cred["username"],
cred.get("password"), cred.get("key_file"),
cred.get("port", 22)
))
# WinRM validation
if "winrm" in credentials:
cred = credentials["winrm"]
tasks.append(executor.submit(
self.validate_winrm, host, cred["username"],
cred["password"], cred.get("port", 5985),
cred.get("use_ssl", False)
))
# SMB validation
if "smb" in credentials:
cred = credentials["smb"]
tasks.append(executor.submit(
self.validate_smb, host, cred["username"],
cred["password"], cred.get("domain", ""),
cred.get("port", 445)
))
# SNMPv3 validation
if "snmpv3" in credentials:
cred = credentials["snmpv3"]
tasks.append(executor.submit(
self.validate_snmpv3, host, cred["username"],
cred["auth_password"], cred["priv_password"],
cred.get("port", 161)
))
for future in as_completed(tasks):
try:
result = future.result()
self.results.append(result)
status_icon = "[+]" if result["status"] == "SUCCESS" else "[-]"
print(f" {status_icon} {result['host']}:{result['port']} "
f"({result['protocol']}) - {result['status']}: {result['details'][:80]}")
except Exception as e:
print(f" [!] Validation error: {e}")
return self.results
def generate_report(self, output_path: str = None) -> pd.DataFrame:
"""Generate validation report."""
df = pd.DataFrame(self.results)
if df.empty:
print("[-] No validation results to report")
return df
print("\n" + "=" * 70)
print("CREDENTIAL VALIDATION SUMMARY")
print("=" * 70)
total = len(df)
success = len(df[df["status"] == "SUCCESS"])
fail = len(df[df["status"] == "FAIL"])
skip = len(df[df["status"] == "SKIP"])
print(f"Total Checks: {total}")
print(f" SUCCESS: {success} ({success/total*100:.1f}%)")
print(f" FAIL: {fail} ({fail/total*100:.1f}%)")
print(f" SKIPPED: {skip} ({skip/total*100:.1f}%)")
if success / max(total, 1) < 0.90:
print("\n[WARNING] Credential success rate below 90% - investigate failures before scanning")
# Protocol breakdown
print("\nBy Protocol:")
for proto in df["protocol"].unique():
proto_df = df[df["protocol"] == proto]
proto_success = len(proto_df[proto_df["status"] == "SUCCESS"])
print(f" {proto}: {proto_success}/{len(proto_df)} "
f"({proto_success/len(proto_df)*100:.1f}%)")
# Failed hosts
failures = df[df["status"] == "FAIL"]
if not failures.empty:
print(f"\nFailed Hosts ({len(failures)}):")
for _, row in failures.iterrows():
print(f" {row['host']}:{row['port']} ({row['protocol']}): {row['details'][:80]}")
if output_path:
df.to_csv(output_path, index=False)
print(f"\n[+] Report saved to: {output_path}")
return df
def main():
parser = argparse.ArgumentParser(description="Authenticated Scan Credential Validator")
subparsers = parser.add_subparsers(dest="command")
# Validate command
val_parser = subparsers.add_parser("validate", help="Validate credentials against targets")
val_parser.add_argument("--targets", required=True, help="File with target IPs (one per line)")
val_parser.add_argument("--creds", required=True, help="JSON file with credentials")
val_parser.add_argument("--output", default=None, help="Output CSV report path")
val_parser.add_argument("--workers", type=int, default=20, help="Max parallel workers")
val_parser.add_argument("--timeout", type=int, default=10, help="Connection timeout seconds")
args = parser.parse_args()
if args.command == "validate":
with open(args.targets) as f:
targets = [line.strip() for line in f if line.strip() and not line.startswith("#")]
with open(args.creds) as f:
credentials = json.load(f)
print(f"[*] Validating credentials against {len(targets)} targets")
print(f"[*] Protocols: {', '.join(credentials.keys())}")
validator = CredentialValidator(timeout=args.timeout)
validator.validate_all(targets, credentials, max_workers=args.workers)
output = args.output or f"cred_validation_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
validator.generate_report(output)
else:
parser.print_help()
if __name__ == "__main__":
main()