Offensive Testing
Offensive Testing
The following files were used as context for generating this wiki page:
- .github/workflows/ghcr-publish.yml
- README.md
- requirements.txt
- wshawk/advanced_cli.py
- wshawk/scanner_v2.py
Purpose and Scope
This document provides a comprehensive overview of WSHawk's offensive testing capabilities, which form the core "Red Team Execution Plane" of the scanner. Offensive testing encompasses all vulnerability detection, payload generation, injection techniques, and verification mechanisms used to identify exploitable security weaknesses in WebSocket applications.
The offensive testing system detects 11+ vulnerability types using a combination of static payloads (22,000+ vectors), dynamic mutation, context-aware generation, and multi-stage verification. For specific vulnerability types and detection methods, see the child sections: Vulnerability Detection Overview, Injection Vulnerabilities, XSS Detection, XXE and SSRF Detection, Path Traversal and SSTI, Payload Mutation and WAF Evasion, Playwright XSS Verification, OAST Blind Vulnerability Detection, and Session Hijacking Tests.
For defensive security validation (blue team testing), see Defensive Validation.
Sources: README.md:23-52, wshawk/scanner_v2.py:1-853
Architectural Overview
The offensive testing architecture consists of three primary layers: the Scanning Engine, the Payload Generation System, and the Verification Layer. These layers work in concert to detect, validate, and report vulnerabilities with high confidence.
graph TB
subgraph "Scanning Engine Layer"
WSHawkV2["WSHawkV2<br/>(scanner_v2.py:35)"]
TestMethods["Test Methods:<br/>test_sql_injection_v2()<br/>test_xss_v2()<br/>test_command_injection_v2()<br/>test_path_traversal_v2()<br/>test_xxe_v2()<br/>test_nosql_injection_v2()<br/>test_ssrf_v2()"]
end
subgraph "Payload Generation System"
WSPayloads["WSPayloads<br/>(__main__.py)<br/>Static 22k+ Vectors"]
ContextGen["ContextAwareGenerator<br/>(smart_payloads/context_generator.py)<br/>Dynamic Field Injection"]
Evolver["PayloadEvolver<br/>(smart_payloads/payload_evolver.py)<br/>Genetic Algorithm"]
Feedback["FeedbackLoop<br/>(smart_payloads/feedback_loop.py)<br/>Response Analysis"]
end
subgraph "Analysis & Intelligence"
MsgAnalyzer["MessageAnalyzer<br/>(message_intelligence.py)<br/>Format Detection<br/>Field Mapping"]
Fingerprinter["ServerFingerprinter<br/>(server_fingerprint.py)<br/>Stack Detection"]
end
subgraph "Verification Layer"
Verifier["VulnerabilityVerifier<br/>(vulnerability_verifier.py)<br/>Confidence Scoring"]
HeadlessXSS["HeadlessBrowserXSSVerifier<br/>(headless_xss_verifier.py)<br/>Playwright Browser"]
OAST["OASTProvider<br/>(oast_provider.py)<br/>interact.sh"]
SessionTester["SessionHijackingTester<br/>(session_hijacking_tester.py)<br/>6 Security Tests"]
end
subgraph "Supporting Infrastructure"
StateMachine["SessionStateMachine<br/>(state_machine.py)"]
RateLimiter["TokenBucketRateLimiter<br/>(rate_limiter.py)"]
end
WSHawkV2 --> TestMethods
TestMethods --> WSPayloads
TestMethods --> ContextGen
TestMethods --> Evolver
Evolver --> Feedback
ContextGen --> MsgAnalyzer
TestMethods --> MsgAnalyzer
TestMethods --> Fingerprinter
TestMethods --> Verifier
TestMethods --> HeadlessXSS
TestMethods --> OAST
WSHawkV2 --> SessionTester
TestMethods --> StateMachine
TestMethods --> RateLimiter
Feedback -.->|"Fitness Scores"| Evolver
Fingerprinter -.->|"Recommended Payloads"| TestMethods
The WSHawkV2 class wshawk/scanner_v2.py:35-852 serves as the orchestrator, coordinating payload generation, injection, response analysis, and verification. Each vulnerability type has a dedicated test method that follows the detection pipeline.
Sources: wshawk/scanner_v2.py:35-100, README.md:38-52
Vulnerability Detection Pipeline
The detection pipeline consists of five distinct phases executed for each vulnerability type. This pipeline ensures high-confidence detection through multiple validation layers.
graph LR
Phase1["Phase 1:<br/>Learning & Analysis<br/>learning_phase()<br/>MessageAnalyzer.learn_from_messages()<br/>ServerFingerprinter.fingerprint()"]
Phase2["Phase 2:<br/>Payload Selection<br/>WSPayloads.get_*()<br/>ServerFingerprinter.get_recommended_payloads()<br/>ContextAwareGenerator.generate_payloads()"]
Phase3["Phase 3:<br/>Injection & Execution<br/>MessageAnalyzer.inject_payload_into_message()<br/>websockets.send()<br/>websockets.recv()"]
Phase4["Phase 4:<br/>Primary Verification<br/>VulnerabilityVerifier.verify_*()<br/>Confidence Scoring:<br/>LOW/MEDIUM/HIGH/CRITICAL"]
Phase5["Phase 5:<br/>Advanced Verification<br/>HeadlessBrowserXSSVerifier.verify_xss_execution()<br/>OASTProvider.check_callbacks()<br/>SessionHijackingTester.run_all_tests()"]
Phase1 --> Phase2
Phase2 --> Phase3
Phase3 --> Phase4
Phase4 -->|"HIGH Confidence"| Phase5
Phase4 -->|"Store Result"| Results["vulnerabilities[]<br/>EnhancedHTMLReporter"]
Phase5 --> Results
Phase 1: Learning & Analysis (scanner_v2.py:112-175) - The scanner connects to the target and passively collects 5-10 seconds of sample messages. The MessageAnalyzer detects the message format (JSON, XML, protobuf, binary) and identifies injectable fields. The ServerFingerprinter identifies the backend technology stack (language, framework, database).
Phase 2: Payload Selection - Based on fingerprinting results, the scanner selects appropriate payloads. For example, if MySQL is detected, MySQL-specific SQL injection payloads are prioritized. If use_smart_payloads is enabled, the ContextAwareGenerator creates context-specific payloads based on the learned message structure.
Phase 3: Injection & Execution - Payloads are automatically injected into detected message fields using MessageAnalyzer.inject_payload_into_message(). The scanner respects rate limits via TokenBucketRateLimiter and handles errors through ResilientSession (documented in ResilientSession and Resilience Control).
Phase 4: Primary Verification - The VulnerabilityVerifier analyzes responses using pattern matching, timing analysis, and heuristic detection. It assigns a confidence level (LOW/MEDIUM/HIGH/CRITICAL) based on the strength of indicators.
Phase 5: Advanced Verification - For HIGH-confidence findings, additional verification occurs. XSS findings trigger real browser execution via Playwright. XXE/SSRF findings check for OAST callbacks. All findings undergo session security testing.
Sources: wshawk/scanner_v2.py:112-175, wshawk/scanner_v2.py:177-256, wshawk/scanner_v2.py:593-852
Core Scanner Components
The following table maps the key classes involved in offensive testing to their responsibilities and file locations:
| Class | File Location | Primary Responsibility | Key Methods |
|-------|--------------|------------------------|-------------|
| WSHawkV2 | scanner_v2.py:35-852 | Main orchestrator, coordinates all testing phases | run_heuristic_scan(), test_*_v2() |
| MessageAnalyzer | message_intelligence.py | Detects message formats and injectable fields | learn_from_messages(), inject_payload_into_message() |
| VulnerabilityVerifier | vulnerability_verifier.py | Validates vulnerabilities with confidence scoring | verify_sql_injection(), verify_xss(), verify_command_injection() |
| ServerFingerprinter | server_fingerprint.py | Identifies backend technology stack | fingerprint(), get_recommended_payloads() |
| WSPayloads | main.py | Manages static payload collections (22,000+ vectors) | get_sql_injection(), get_xss(), get_command_injection() |
| ContextAwareGenerator | smart_payloads/context_generator.py | Generates context-specific payloads based on message structure | learn_from_message(), generate_payloads() |
| PayloadEvolver | smart_payloads/payload_evolver.py | Evolves successful payloads using genetic algorithms | seed(), evolve(), update_fitness() |
| FeedbackLoop | smart_payloads/feedback_loop.py | Analyzes responses and guides payload evolution | analyze_response(), establish_baseline() |
| HeadlessBrowserXSSVerifier | headless_xss_verifier.py | Verifies XSS execution in real browser | verify_xss_execution() |
| OASTProvider | oast_provider.py | Out-of-band testing for blind vulnerabilities | generate_payload(), check_callbacks() |
| SessionHijackingTester | session_hijacking_tester.py | Tests session security controls | run_all_tests() |
Sources: wshawk/scanner_v2.py:35-100, README.md:40-48
Test Method Architecture
Each vulnerability type is detected by a dedicated test method following a consistent pattern. The following diagram illustrates the internal flow of a test method using SQL injection as an example:
graph TD
Entry["test_sql_injection_v2(ws)<br/>(scanner_v2.py:177)"]
LoadPayloads["Load Payloads:<br/>WSPayloads.get_sql_injection()[:100]"]
Fingerprint{{"ServerFingerprinter<br/>detected database?"}}
RecommendedPayloads["Get database-specific payloads:<br/>fingerprinter.get_recommended_payloads()"]
BaseMessage["Get base message from<br/>sample_messages[0]"]
PayloadLoop["For each payload in payloads"]
ContextInjection{{"learning_complete &<br/>MessageFormat.JSON?"}}
AutoInject["MessageAnalyzer.inject_payload_into_message()<br/>Injects into detected fields"]
RawPayload["Use raw payload string"]
SendReceive["ws.send(msg)<br/>messages_sent++<br/>ws.recv(timeout=2.0)<br/>messages_received++"]
Verify["VulnerabilityVerifier.verify_sql_injection()<br/>Returns: is_vuln, confidence, description"]
SmartFeedback{{"use_smart_payloads?"}}
FeedbackAnalysis["FeedbackLoop.analyze_response()<br/>Analyzes response signals"]
ConfidenceCheck{{"confidence !=<br/>ConfidenceLevel.LOW?"}}
SeedEvolver["PayloadEvolver.seed([payload])<br/>PayloadEvolver.update_fitness(payload, 1.0)"]
StoreVuln["Append to vulnerabilities[]:<br/>type, severity, confidence,<br/>description, payload,<br/>response_snippet, recommendation"]
RateLimit["await asyncio.sleep(0.05)<br/>Rate limiting"]
Entry --> LoadPayloads
LoadPayloads --> Fingerprint
Fingerprint -->|Yes| RecommendedPayloads
Fingerprint -->|No| BaseMessage
RecommendedPayloads --> BaseMessage
BaseMessage --> PayloadLoop
PayloadLoop --> ContextInjection
ContextInjection -->|Yes| AutoInject
ContextInjection -->|No| RawPayload
AutoInject --> SendReceive
RawPayload --> SendReceive
SendReceive --> Verify
Verify --> SmartFeedback
SmartFeedback -->|Yes| FeedbackAnalysis
SmartFeedback -->|No| ConfidenceCheck
FeedbackAnalysis --> ConfidenceCheck
ConfidenceCheck -->|Yes| SeedEvolver
ConfidenceCheck -->|No| RateLimit
SeedEvolver --> StoreVuln
StoreVuln --> RateLimit
RateLimit --> PayloadLoop
This pattern is replicated across all test methods: test_xss_v2() scanner_v2.py:258-341, test_command_injection_v2() scanner_v2.py:343-407, test_path_traversal_v2() scanner_v2.py:409-448, test_xxe_v2() scanner_v2.py:450-504, test_nosql_injection_v2() scanner_v2.py:506-544, and test_ssrf_v2() scanner_v2.py:546-591.
Sources: wshawk/scanner_v2.py:177-256, wshawk/scanner_v2.py:258-407
Payload Evolution System
When use_smart_payloads is enabled (via --smart-payloads flag or configuration), WSHawk employs an adaptive payload generation system that learns from successful attacks:
graph TB
subgraph "Initial Seeding"
SuccessfulPayload["Successful Payload<br/>from test_*_v2()"]
Seed["PayloadEvolver.seed([payload])<br/>PayloadEvolver.update_fitness(payload, 1.0)"]
end
subgraph "Evolution Phase (scanner_v2.py:638-703)"
Evolve["PayloadEvolver.evolve(count=30)<br/>Genetic crossover & mutation"]
ContextGen["ContextAwareGenerator.generate_payloads()<br/>Based on learned message structure"]
Priorities["FeedbackLoop.get_priority_categories()<br/>Identifies most promising attack vectors"]
end
subgraph "Feedback Loop"
TestEvolved["Inject evolved payloads"]
AnalyzeResponse["FeedbackLoop.analyze_response()<br/>Returns: signal, confidence"]
MultiVerify["Test against all verifiers:<br/>verify_sql_injection()<br/>verify_xss()<br/>verify_command_injection()"]
UpdateFitness["PayloadEvolver.update_fitness(payload, 1.0)<br/>Reinforces successful mutations"]
end
subgraph "Results"
StoreEvolved["Store with type: 'Vulnerability (Evolved)'<br/>Marked as novel discovery"]
end
SuccessfulPayload --> Seed
Seed --> Evolve
Priorities --> ContextGen
Evolve --> TestEvolved
ContextGen --> TestEvolved
TestEvolved --> AnalyzeResponse
AnalyzeResponse --> MultiVerify
MultiVerify -->|"High Confidence"| UpdateFitness
UpdateFitness --> StoreEvolved
StoreEvolved -.->|"Next Generation"| Evolve
The evolution phase scanner_v2.py:638-703 runs after all standard tests complete. It generates 30 evolved payloads through genetic operations (crossover, mutation) and combines them with context-aware payloads generated from the learned message structure. Each evolved payload is tested against all verification methods, and successful payloads are marked with the (Evolved) suffix in reports, indicating novel discoveries by the mutation engine.
Sources: wshawk/scanner_v2.py:638-703, README.md:28-35
Confidence Scoring and Verification
The VulnerabilityVerifier class assigns confidence levels using a multi-indicator approach:
| Confidence Level | Criteria | Example Indicators |
|-----------------|----------|-------------------|
| CRITICAL | Real execution confirmed by browser or OAST callback | Playwright confirms alert() execution, OAST receives DNS/HTTP callback |
| HIGH | Multiple strong indicators present | Error messages reveal internal details + data exfiltration patterns |
| MEDIUM | Single strong indicator or multiple weak indicators | SQL error message OR timing anomaly + suspicious response |
| LOW | Reflection detected but no execution indicators | Payload appears in response unchanged |
The verification process uses indicator patterns defined in each verify_*() method. For SQL injection scanner_v2.py:177-256, indicators include SQL error messages (syntax error, mysql_fetch, ORA-), database version strings, timing delays, and data extraction patterns. For XSS scanner_v2.py:258-341, indicators include unescaped script tags, event handlers, and JavaScript execution contexts.
Advanced Verification Triggers:
- HIGH-confidence XSS → Triggers
HeadlessBrowserXSSVerifier.verify_xss_execution()scanner_v2.py:294-314 - XXE/SSRF payloads → Triggers
OASTProvider.check_callbacks()scanner_v2.py:450-504 - All findings → Undergo
SessionHijackingTester.run_all_tests()scanner_v2.py:709-732
If browser verification confirms XSS execution, the confidence is upgraded to CRITICAL and marked as [BROWSER VERIFIED] in reports scanner_v2.py:304-314.
Sources: wshawk/scanner_v2.py:177-256, wshawk/scanner_v2.py:258-341, wshawk/scanner_v2.py:294-314
Scan Execution Flow
The complete scan is orchestrated by run_heuristic_scan() scanner_v2.py:593-852:
graph TD
Start["WSHawkV2.run_heuristic_scan()"]
Banner["Logger.banner()<br/>Display WSHawk banner"]
Connect["await connect()<br/>Establish WebSocket connection"]
Learning["await learning_phase(ws, duration=5)<br/>Collect sample messages<br/>MessageAnalyzer learns format<br/>ServerFingerprinter identifies stack"]
SQLi["await test_sql_injection_v2(ws)"]
XSS["await test_xss_v2(ws)"]
CMDi["await test_command_injection_v2(ws)"]
PathTrav["await test_path_traversal_v2(ws)"]
XXE["await test_xxe_v2(ws)"]
NoSQL["await test_nosql_injection_v2(ws)"]
SSRF["await test_ssrf_v2(ws)"]
SmartCheck{{"use_smart_payloads &<br/>population > 0?"}}
Evolution["Evolution Phase:<br/>PayloadEvolver.evolve(count=30)<br/>ContextAwareGenerator.generate_payloads()<br/>Test evolved payloads against all verifiers"]
CloseWS["await ws.close()"]
SessionTests["SessionHijackingTester.run_all_tests()<br/>6 session security tests"]
Cleanup["Cleanup:<br/>HeadlessBrowserXSSVerifier.stop()<br/>OASTProvider.stop()"]
Summary["Display Statistics:<br/>Duration, messages sent/received,<br/>vulnerabilities count by confidence"]
Report["EnhancedHTMLReporter.generate_report()<br/>Save to wshawk_report_YYYYMMDD_HHMMSS.html"]
Exports["ReportExporter.export()<br/>JSON/CSV/SARIF formats"]
Integrations["Automated Integrations:<br/>DefectDojoIntegration.push_findings()<br/>JiraIntegration.create_tickets()<br/>WebhookNotifier.notify()"]
Start --> Banner
Banner --> Connect
Connect --> Learning
Learning --> SQLi
SQLi --> XSS
XSS --> CMDi
CMDi --> PathTrav
PathTrav --> XXE
XXE --> NoSQL
NoSQL --> SSRF
SSRF --> SmartCheck
SmartCheck -->|Yes| Evolution
SmartCheck -->|No| CloseWS
Evolution --> CloseWS
CloseWS --> SessionTests
SessionTests --> Cleanup
Cleanup --> Summary
Summary --> Report
Report --> Exports
Exports --> Integrations
The scan is rate-limited throughout by TokenBucketRateLimiter.acquire() calls and manual delays (await asyncio.sleep(0.05)) to prevent overwhelming the target. The resilient session handling (documented in ResilientSession and Resilience Control) ensures the scan continues even if individual requests fail.
Sources: wshawk/scanner_v2.py:593-852
CLI Entry Points
WSHawk provides multiple CLI entry points for offensive testing, each with different feature sets:
| Command | Entry Point | Features | Use Case |
|---------|------------|----------|----------|
| wshawk | main.py | Basic scan, all vulnerability types | Quick automated scanning |
| wshawk-interactive | interactive_cli.py | Menu-driven interface | Learning and guided testing |
| wshawk-advanced | advanced_cli.py:12-283 | Full control: --smart-payloads, --playwright, --full, --rate | Advanced users, custom workflows |
The wshawk-advanced command supports the most offensive testing options:
# Basic scan with smart payloads
wshawk-advanced ws://target.com --smart-payloads
# Full offensive testing (all features)
wshawk-advanced ws://target.com --full
# Custom rate limit with browser verification
wshawk-advanced ws://target.com --playwright --rate 5
# Export to SARIF for CI/CD integration
wshawk-advanced ws://target.com --format sarif
# Automated integration with DefectDojo
wshawk-advanced ws://target.com --defectdojo https://dojo.example.com
The --full flag advanced_cli.py:174-178 enables all offensive features: use_headless_browser=True, use_oast=True, and use_smart_payloads=True.
Sources: wshawk/advanced_cli.py:12-283, README.md:82-109
Vulnerability Storage and Reporting
Detected vulnerabilities are stored in the vulnerabilities list as dictionaries with the following schema:
{
'type': str, # e.g., "SQL Injection", "XSS (Evolved)"
'severity': str, # CRITICAL/HIGH/MEDIUM/LOW
'confidence': str, # Matches severity for VulnerabilityVerifier
'description': str, # Human-readable explanation
'payload': str, # The attack payload that triggered detection
'response_snippet': str, # First 200 chars of response
'recommendation': str, # Remediation guidance
'browser_verified': bool, # (Optional) True if Playwright confirmed execution
'cvss_score': float # (Optional) For session security findings
}
This structure is defined across all test methods scanner_v2.py:236-244, scanner_v2.py:321-330, scanner_v2.py:387-396 and used by EnhancedHTMLReporter for report generation and by ReportExporter for JSON/CSV/SARIF export.
Sources: wshawk/scanner_v2.py:236-244, wshawk/scanner_v2.py:784-805
Integration with Analysis Modules
The offensive testing system relies heavily on the analysis modules documented in Analysis and Verification Modules:
MessageAnalyzer Integration scanner_v2.py:58 - Initialized during __init__() and called in the learning phase scanner_v2.py:146-154. During payload injection, inject_payload_into_message() is called for each test scanner_v2.py:200-203, scanner_v2.py:271-274 to automatically insert payloads into detected JSON/XML fields.
ServerFingerprinter Integration scanner_v2.py:60 - Called during learning phase scanner_v2.py:165-170. The fingerprint results guide payload selection via get_recommended_payloads() scanner_v2.py:188-192, scanner_v2.py:353-358, prioritizing database-specific SQL injection payloads or language-specific command injection payloads.
VulnerabilityVerifier Integration scanner_v2.py:59 - Called for every response in every test method to assign confidence levels. The verifier uses pattern matching, timing analysis, and heuristic detection to minimize false positives.
Sources: wshawk/scanner_v2.py:58-60, wshawk/scanner_v2.py:146-170, wshawk/scanner_v2.py:188-192
Python API Usage
Offensive testing can be invoked programmatically via the Python API:
import asyncio
from wshawk.scanner_v2 import WSHawkV2
# Initialize scanner
scanner = WSHawkV2("ws://target.com")
# Enable advanced features
scanner.use_headless_browser = True
scanner.use_oast = True
scanner.use_smart_payloads = True
# Run full scan
vulnerabilities = await asyncio.run(scanner.run_heuristic_scan())
# Access results
for vuln in vulnerabilities:
print(f"[{vuln['severity']}] {vuln['type']}: {vuln['description']}")
Individual test methods can also be called directly:
# Run only SQL injection tests
ws = await scanner.connect()
await scanner.learning_phase(ws, duration=5)
sql_results = await scanner.test_sql_injection_v2(ws)
await ws.close()
Configuration can be passed via the config parameter scanner_v2.py:40-53 to customize rate limits, output directories, and integration settings.
Sources: README.md:252-264, wshawk/scanner_v2.py:40-53
Performance Characteristics
The offensive testing system is designed for production use with the following performance characteristics:
- Rate Limiting: Default 10 requests/second via
TokenBucketRateLimiterscanner_v2.py:62-66 - Timeout Management: 2-second timeout for most operations scanner_v2.py:212, 3 seconds for SSRF scanner_v2.py:567
- Payload Subsets: Uses first 100 payloads for SQL/XSS/Command Injection scanner_v2.py:184, 50 for path traversal scanner_v2.py:414, 30 for XXE scanner_v2.py:455
- Adaptive Delays: 0.05 second delay between payloads scanner_v2.py:250, 0.1 seconds for SSRF scanner_v2.py:587
- Smart Payload Generation: Limited to 30 evolved payloads + 10 context payloads per category scanner_v2.py:640-646
For full payload coverage, use the legacy scanner documented in WSHawkV2 Scanner Engine or adjust payload counts in the source code.
Sources: wshawk/scanner_v2.py:62-66, wshawk/scanner_v2.py:184, wshawk/scanner_v2.py:640-646