mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-19 05:59:40 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
---
|
||||
name: None
|
||||
description: Authenticated (credentialed) vulnerability scanning uses valid system credentials to log into target hosts and perform deep inspection of installed software, patches, configurations, and security sett
|
||||
domain: cybersecurity
|
||||
subdomain: vulnerability-management
|
||||
tags: [vulnerability-management, cve, authenticated-scanning, credentials, nessus, qualys, risk]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
# Performing Authenticated Vulnerability Scan
|
||||
|
||||
## 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.
|
||||
|
||||
## 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
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Step 1: Create Dedicated Service Accounts
|
||||
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
|
||||
```powershell
|
||||
# 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
|
||||
```json
|
||||
{
|
||||
"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
|
||||
|
||||
```bash
|
||||
# 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.0
|
||||
```
|
||||
|
||||
### Step 4: Run Authenticated Scan
|
||||
|
||||
Configure and launch the scan using the Nessus API:
|
||||
```bash
|
||||
# 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
|
||||
|
||||
1. **Use a secrets vault** (HashiCorp Vault, CyberArk, AWS Secrets Manager) for credential storage
|
||||
2. **Rotate credentials** every 90 days or after personnel changes
|
||||
3. **Principle of least privilege** - only grant minimum required access
|
||||
4. **Audit credential usage** - monitor service account login events
|
||||
5. **Encrypt in transit** - use SSH keys over passwords, WinRM over HTTPS
|
||||
6. **Separate accounts** per scanner - never share credentials across tools
|
||||
7. **Disable interactive login** for scan service accounts where possible
|
||||
8. **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
|
||||
|
||||
## Related Skills
|
||||
- scanning-infrastructure-with-nessus
|
||||
- performing-network-vulnerability-assessment
|
||||
- implementing-continuous-vulnerability-monitoring
|
||||
@@ -0,0 +1,38 @@
|
||||
# Authenticated Vulnerability Scan Report Template
|
||||
|
||||
## Scan Configuration
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Scan Date | [YYYY-MM-DD] |
|
||||
| Scanner | [Nessus/Qualys/OpenVAS] |
|
||||
| Scan Type | Authenticated (Credentialed) |
|
||||
| Targets | [TARGET_RANGE] |
|
||||
| Credential Types | SSH / WinRM / SMB / SNMPv3 |
|
||||
|
||||
## Credential Success Summary
|
||||
| Protocol | Targets | Success | Failed | Rate |
|
||||
|----------|---------|---------|--------|------|
|
||||
| SSH | [N] | [N] | [N] | [%] |
|
||||
| WinRM | [N] | [N] | [N] | [%] |
|
||||
| SMB | [N] | [N] | [N] | [%] |
|
||||
| SNMPv3 | [N] | [N] | [N] | [%] |
|
||||
| **Total** | **[N]** | **[N]** | **[N]** | **[%]** |
|
||||
|
||||
## Findings Summary (Authenticated vs Unauthenticated Comparison)
|
||||
| Severity | Auth Scan | Unauth Scan | Delta |
|
||||
|----------|-----------|-------------|-------|
|
||||
| Critical | [N] | [N] | [+N] |
|
||||
| High | [N] | [N] | [+N] |
|
||||
| Medium | [N] | [N] | [+N] |
|
||||
| Low | [N] | [N] | [+N] |
|
||||
|
||||
## Authentication Failures
|
||||
| Host | Protocol | Failure Reason | Remediation |
|
||||
|------|----------|---------------|-------------|
|
||||
| [IP] | [SSH/WinRM] | [reason] | [action] |
|
||||
|
||||
## Recommendations
|
||||
1. **Credential Coverage**: [Current %] - Target: >95%
|
||||
2. **Failed Hosts**: Investigate [N] authentication failures
|
||||
3. **Privilege Gaps**: [N] hosts missing sudo/admin elevation
|
||||
4. **Credential Rotation**: Next rotation due [DATE]
|
||||
@@ -0,0 +1,39 @@
|
||||
# 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 |
|
||||
@@ -0,0 +1,61 @@
|
||||
# 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
|
||||
|
||||
1. **Pre-scan**: Verify credentials, check network connectivity, confirm scan window
|
||||
2. **Discovery**: Host enumeration to identify live targets
|
||||
3. **Authentication**: Scanner authenticates to each target host
|
||||
4. **Local Enumeration**: Query installed packages, patches, configurations
|
||||
5. **Vulnerability Assessment**: Match local data against vulnerability database
|
||||
6. **Report Generation**: Compile findings with credential success metrics
|
||||
7. **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 hosts
|
||||
```
|
||||
|
||||
## Workflow 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 |
|
||||
@@ -0,0 +1,390 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user