Configuration and Authentication

Configuration and Authentication

The following files were used as context for generating this wiki page:

This page documents all configuration and authentication mechanisms in WSHawk. This includes authentication sequence configuration for stateful WebSocket testing, custom header injection, session-based authentication for specialized tests, and environment-based configuration options.

For information about using the Python API programmatically, see Python API Usage. For CI/CD-specific configuration examples, see CI/CD Integration.


Overview

WSHawk supports multiple configuration and authentication mechanisms to accommodate diverse WebSocket implementations:

| Configuration Type | Use Case | Primary Interface | |-------------------|----------|-------------------| | Authentication Sequences | Stateful WebSocket sessions requiring login flows | YAML files loaded via auth_sequence parameter | | Custom Headers | Bearer tokens, API keys, session cookies | headers dictionary parameter | | Session Test Auth | Session hijacking test customization | auth_config dictionary in SessionHijackingTester | | Environment Variables | Runtime behavior customization | PYTHONUNBUFFERED, TIMEOUT, etc. | | Docker Configuration | Containerized deployment settings | Volume mounts, environment variables, network modes |


Authentication Sequences (YAML)

Purpose and Loading Mechanism

Authentication sequences enable WSHawk to test WebSocket applications that require multi-step login flows before vulnerability testing can begin. The SessionStateMachine class manages these sequences.

Configuration Flow:

graph LR
    YAMLFile["YAML Configuration File<br/>auth_sequence.yaml"]
    WSHawkV2["WSHawkV2.__init__()<br/>scanner_v2.py:33-34"]
    StateMachine["SessionStateMachine<br/>state_machine.py"]
    LoadMethod["load_sequence_from_yaml()<br/>state_machine.py"]
    WSConnection["WebSocket Connection<br/>Learning Phase"]
    
    YAMLFile -->|"auth_sequence='/path/to/file.yaml'"| WSHawkV2
    WSHawkV2 -->|"self.state_machine"| StateMachine
    WSHawkV2 -->|"if auth_sequence"| LoadMethod
    LoadMethod -->|"Loads and validates"| StateMachine
    StateMachine -->|"Executes sequence"| WSConnection

Sources: wshawk/scanner_v2.py:33-63

YAML File Format

Authentication sequences are defined in YAML format with the following structure:

# Example authentication sequence
auth_sequence:
  - action: "connect"
    message:
      type: "handshake"
      client_version: "1.0"
    
  - action: "authenticate"
    message:
      action: "login"
      username: "testuser"
      password: "testpass"
    wait_for_response: true
    
  - action: "subscribe"
    message:
      action: "subscribe"
      channel: "main"

Each step in the sequence supports:

  • action: Descriptive name for the step (used in state tracking)
  • message: The WebSocket message payload (JSON object)
  • wait_for_response: Boolean flag indicating whether to wait for server response
  • timeout: Optional timeout in seconds for response waiting

Loading Authentication Sequences

Python API:

from wshawk.scanner_v2 import WSHawkV2

scanner = WSHawkV2(
    url="wss://app.example.com/ws",
    auth_sequence="/path/to/auth_config.yaml"
)

CLI Usage:

Currently, authentication sequences must be configured programmatically via the Python API. CLI support for external YAML files is planned for future releases.

Sources: wshawk/scanner_v2.py:60-62


Custom Headers Configuration

HTTP Header Injection

Custom headers are passed to the WebSocket connection during the initial HTTP handshake. This is essential for authentication mechanisms that use bearer tokens, API keys, or session cookies.

Header Configuration Flow:

graph TB
    UserHeaders["User-Provided Headers<br/>Dict[str, str]"]
    WSHawkInit["WSHawkV2.__init__()<br/>headers parameter<br/>scanner_v2.py:33-37"]
    ConnectMethod["connect() method<br/>scanner_v2.py:77-85"]
    WebSocketsConnect["websockets.connect()<br/>additional_headers parameter<br/>scanner_v2.py:80"]
    WSConnection["WebSocket Connection<br/>with custom headers"]
    
    UserHeaders --> WSHawkInit
    WSHawkInit -->|"self.headers"| ConnectMethod
    ConnectMethod -->|"additional_headers=self.headers"| WebSocketsConnect
    WebSocketsConnect --> WSConnection

Sources: wshawk/scanner_v2.py:33-85

Common Header Patterns

| Authentication Type | Header Format | Example | |--------------------|---------------|---------| | Bearer Token | Authorization: Bearer <token> | {"Authorization": "Bearer eyJhbG..."} | | API Key | X-API-Key: <key> | {"X-API-Key": "sk_live_12345"} | | Session Cookie | Cookie: session=<value> | {"Cookie": "session=abc123; Path=/"} | | Custom Auth | Custom header name | {"X-Custom-Auth": "value"} |

Configuration Examples

Python API with Bearer Token:

scanner = WSHawkV2(
    url="wss://api.example.com/ws",
    headers={
        "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
        "User-Agent": "WSHawk/2.0.5"
    }
)
await scanner.run_intelligent_scan()

Multiple Headers:

scanner = WSHawkV2(
    url="wss://secure.example.com/socket",
    headers={
        "Authorization": "Bearer token123",
        "X-API-Key": "sk_test_abcdef",
        "X-Client-ID": "client-001",
        "Origin": "https://app.example.com"
    }
)

Sources: wshawk/scanner_v2.py:33-37, wshawk/scanner_v2.py:77-85


Session Hijacking Test Authentication

SessionHijackingTester Authentication Configuration

The SessionHijackingTester class requires its own authentication configuration to test session security vulnerabilities. This configuration is separate from the main scanner's authentication.

Authentication Configuration Structure:

graph TB
    SessionTester["SessionHijackingTester<br/>session_hijacking_tester.py:48-91"]
    AuthConfig["auth_config parameter<br/>Dict with auth structure"]
    DefaultConfig["Default Configuration<br/>Lines 84-90"]
    CustomConfig["Custom Configuration<br/>User-provided"]
    GetAuthPayload["_get_auth_payload()<br/>Lines 92-114"]
    WSMessage["WebSocket Auth Message<br/>JSON payload"]
    
    SessionTester -->|"Optional"| AuthConfig
    AuthConfig --> DefaultConfig
    AuthConfig --> CustomConfig
    DefaultConfig --> GetAuthPayload
    CustomConfig --> GetAuthPayload
    GetAuthPayload -->|"json.dumps()"| WSMessage

Sources: wshawk/session_hijacking_tester.py:61-114

Default Authentication Configuration

The default configuration assumes a simple login-based authentication:

{
    'action': 'login',
    'username_field': 'username',
    'password_field': 'password',
    'username': 'user1',
    'password': 'pass1'
}

This generates the following WebSocket message:

{
    "action": "login",
    "username": "user1",
    "password": "pass1"
}

Sources: wshawk/session_hijacking_tester.py:84-90

Custom Authentication Configuration

Example 1: Custom Field Names

from wshawk.session_hijacking_tester import SessionHijackingTester

tester = SessionHijackingTester(
    target_url="ws://localhost:9999",
    auth_config={
        'action': 'authenticate',
        'username_field': 'email',
        'password_field': 'pass',
        'username': 'test@example.com',
        'password': 'secure123'
    }
)

This generates:

{
    "action": "authenticate",
    "email": "test@example.com",
    "pass": "secure123"
}

Example 2: Custom Payload Structure

For non-standard authentication flows:

tester = SessionHijackingTester(
    target_url="ws://localhost:9999",
    auth_config={
        'custom_payload': {
            "type": "AUTH",
            "credentials": {
                "user": "testuser",
                "token": "abc123"
            },
            "client_id": "wshawk-tester"
        }
    }
)

This sends the custom payload directly without field transformation.

Sources: wshawk/session_hijacking_tester.py:92-114

Authentication Payload Generation

The _get_auth_payload() method handles two configuration modes:

flowchart TD
    GetAuthPayload["_get_auth_payload(username, password)<br/>session_hijacking_tester.py:92"]
    CheckCustom{"'custom_payload'<br/>in auth_config?"}
    UseCustom["Return custom_payload<br/>Lines 94-95"]
    BuildPayload["Build from fields<br/>Lines 97-114"]
    CheckAction{"'action' field<br/>exists?"}
    ActionSeparate["action as separate field<br/>Lines 107-112"]
    ActionAsKey["action as boolean key<br/>Lines 100-104"]
    JSONDumps["json.dumps(payload)<br/>Line 114"]
    
    GetAuthPayload --> CheckCustom
    CheckCustom -->|"Yes"| UseCustom
    CheckCustom -->|"No"| BuildPayload
    BuildPayload --> CheckAction
    CheckAction -->|"Yes"| ActionSeparate
    CheckAction -->|"No"| ActionAsKey
    ActionSeparate --> JSONDumps
    ActionAsKey --> JSONDumps
    UseCustom --> JSONDumps

Sources: wshawk/session_hijacking_tester.py:92-114


Environment Variables

Supported Environment Variables

WSHawk respects standard Python and container environment variables:

| Variable | Purpose | Default | Example | |----------|---------|---------|---------| | PYTHONUNBUFFERED | Disable Python output buffering (useful for real-time logs) | 0 | PYTHONUNBUFFERED=1 | | TIMEOUT | Custom timeout for WebSocket operations | 3.0 | TIMEOUT=30 |

Usage in Docker

Environment variables can be set in multiple ways when using Docker:

Command Line:

docker run --rm -e PYTHONUNBUFFERED=1 -e TIMEOUT=30 rothackers/wshawk ws://target.com

Docker Compose:

services:
  wshawk:
    image: rothackers/wshawk:latest
    environment:
      - PYTHONUNBUFFERED=1
      - TIMEOUT=30

Sources: docker-compose.yml:17-18, docs/DOCKER.md:112-118


Docker-Specific Configuration

Volume Mounting for Configuration Files

To use YAML authentication sequences or save configuration files in Docker:

# Mount configuration directory
docker run --rm \
  -v $(pwd)/config:/app/config \
  -v $(pwd)/reports:/app/reports \
  rothackers/wshawk ws://target.com

Directory Structure:

./config/
  ├── auth_sequence.yaml
  └── custom_payloads.txt
./reports/
  └── wshawk_report_*.html

Sources: docs/DOCKER.md:56-63

Network Configuration

Host Network Mode (for local testing):

docker run --rm --network host rothackers/wshawk ws://localhost:8765

Custom Network:

docker network create wshawk-net
docker run --rm --network wshawk-net rothackers/wshawk ws://target.com

Docker Compose Network Configuration:

services:
  wshawk:
    network_mode: host  # Access localhost services
    # OR
    networks:
      - wshawk-network

networks:
  wshawk-network:
    driver: bridge

Sources: docs/DOCKER.md:66-70, docs/DOCKER.md:132-143, docker-compose.yml:8-35

User and Permission Configuration

The Docker image runs as non-root user wshawk:1000 by default. To avoid permission issues with volume mounts:

# Run as current user
docker run --rm --user $(id -u):$(id -g) \
  -v $(pwd)/reports:/app/reports \
  rothackers/wshawk ws://target.com

Sources: docs/DOCKER.md:169-174, docs/DOCKER.md:196-201


Configuration Precedence and Override

Configuration Loading Order

graph TB
    DefaultConfig["Default Configuration<br/>Hard-coded in classes"]
    EnvVars["Environment Variables<br/>OS-level settings"]
    ConstructorParams["Constructor Parameters<br/>Python API / CLI args"]
    YAMLFiles["YAML Configuration Files<br/>auth_sequence parameter"]
    RuntimeOverride["Runtime Overrides<br/>Method parameters"]
    
    DefaultConfig --> EnvVars
    EnvVars --> ConstructorParams
    ConstructorParams --> YAMLFiles
    YAMLFiles --> RuntimeOverride
    
    DefaultConfig -.->|"Lowest Priority"| P1[ ]
    RuntimeOverride -.->|"Highest Priority"| P2[ ]
    
    style P1 fill:none,stroke:none
    style P2 fill:none,stroke:none

Example: Header Configuration Override

# 1. Default headers (empty)
scanner = WSHawkV2(url="ws://target.com")
# headers = {}

# 2. Constructor override
scanner = WSHawkV2(
    url="ws://target.com",
    headers={"Authorization": "Bearer token1"}
)
# headers = {"Authorization": "Bearer token1"}

# 3. Runtime modification (not directly supported, requires reconnection)
scanner.headers["X-Custom"] = "value"
ws = await scanner.connect()  # Uses updated headers

Sources: wshawk/scanner_v2.py:33-85


Complete Configuration Example

Full Python API Configuration

import asyncio
from wshawk.scanner_v2 import WSHawkV2

async def main():
    scanner = WSHawkV2(
        # Target WebSocket URL
        url="wss://api.example.com/ws",
        
        # Custom HTTP headers for initial handshake
        headers={
            "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
            "X-API-Key": "sk_live_12345",
            "User-Agent": "WSHawk/2.0.5 Security Scanner",
            "Origin": "https://app.example.com"
        },
        
        # Authentication sequence (YAML file path)
        auth_sequence="./config/auth_sequence.yaml",
        
        # Rate limiting (requests per second)
        max_rps=10
    )
    
    # Configure optional features
    scanner.use_headless_browser = True  # Enable Playwright XSS verification
    scanner.use_oast = True              # Enable OAST for blind vulnerabilities
    
    # Run comprehensive scan
    results = await scanner.run_intelligent_scan()
    
    print(f"Found {len(results)} vulnerabilities")

if __name__ == "__main__":
    asyncio.run(main())

Session Hijacking Test Configuration

from wshawk.session_hijacking_tester import SessionHijackingTester

tester = SessionHijackingTester(
    target_url="ws://localhost:9999",
    auth_config={
        'action': 'login',
        'username_field': 'email',
        'password_field': 'password',
        'username': 'test@example.com',
        'password': 'secure123'
    }
)

results = await tester.run_all_tests()

Sources: wshawk/scanner_v2.py:28-76, wshawk/session_hijacking_tester.py:48-91


Configuration Best Practices

Security Considerations

| Practice | Rationale | Implementation | |----------|-----------|----------------| | Never hardcode credentials | Prevents credential leakage in version control | Use environment variables or external config files | | Use environment-specific configs | Different credentials for dev/staging/prod | Separate YAML files per environment | | Rotate authentication tokens | Limits exposure window | Update headers/configs before each scan | | Restrict file permissions | Prevents unauthorized config access | chmod 600 auth_sequence.yaml |

Configuration File Management

# Recommended directory structure
.
├── config/
│   ├── prod_auth.yaml      # Production authentication
│   ├── staging_auth.yaml   # Staging authentication
│   └── dev_auth.yaml       # Development authentication
├── reports/                 # Scan output
└── .gitignore              # Exclude config/ from version control

Example .gitignore:

config/
reports/
*.yaml

Sources: Project best practices, standard security guidelines


Troubleshooting

Common Configuration Issues

| Issue | Symptom | Solution | |-------|---------|----------| | Authentication sequence not loading | TypeError: load_sequence_from_yaml() | Ensure YAML file path is absolute or relative to execution directory | | Headers not applied | Authentication fails despite correct credentials | Verify headers are passed to WSHawkV2.__init__(), not connect() | | Docker volume permissions | Cannot write reports | Use --user $(id -u):$(id -g) or adjust host directory permissions | | Session test auth fails | Tests skip or error | Verify auth_config structure matches server expectations |

Debug Configuration Loading

To verify configuration is loaded correctly, enable verbose logging:

from wshawk.logger import setup_logging

logger = setup_logging(verbose=True, log_file="wshawk_debug.log")

scanner = WSHawkV2(
    url="ws://target.com",
    headers={"Authorization": "Bearer token"}
)
# Check logs for header application

Sources: wshawk/logger.py:37-70


Configuration Reference Tables

WSHawkV2 Constructor Parameters

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | url | str | Required | WebSocket URL (ws:// or wss://) | | headers | Optional[Dict] | None | Custom HTTP headers for handshake | | auth_sequence | Optional[str] | None | Path to YAML authentication sequence file | | max_rps | int | 10 | Maximum requests per second (rate limiting) |

Sources: wshawk/scanner_v2.py:33-35

SessionHijackingTester Auth Config Fields

| Field | Type | Required | Description | |-------|------|----------|-------------| | action | str | No | Action type for auth message | | username_field | str | No | Field name for username (default: "username") | | password_field | str | No | Field name for password (default: "password") | | username | str | No | Username value (default: "user1") | | password | str | No | Password value (default: "pass1") | | custom_payload | Dict | No | Complete custom authentication payload |

Sources: wshawk/session_hijacking_tester.py:84-114


Sources: wshawk/scanner_v2.py:1-681, wshawk/session_hijacking_tester.py:1-573, wshawk/logger.py:1-71, docker-compose.yml:1-36, docs/DOCKER.md:1-240