Smart Payload Engine

Article 1: The Architecture of the Smart Payload Engine (SPE)

Source File: wshawk/smart_payloads/payload_evolver.py
Relevant Class: PayloadEvolver

1.1 The Limitations of Static Fuzzing

Standard security scanners rely on static wordlists (such as SecLists). When testing web applications, scanners iterate through these lists, blasting thousands of static strings at the target. Modern Web Application Firewalls (WAFs), such as Cloudflare or AWS WAF, easily fingerprint this behavior. They utilize regex signatures or rate-limiters to detect the malicious patterns and subsequently drop the TCP connection.

In HTTP testing, a dropped connection is a minor inconvenience; the scanner simply initiates a new TCP handshake for the next request. In WebSocket testing, losing the persistent TCP connection halts the entire testing sequence, forcing the scanner to re-authenticate and re-establish the socket state before resuming. This makes brute-force fuzzing highly inefficient.

1.2 Genetic Payload Evolution as a Solution

To bypass this limitation, WSHawk implements the Smart Payload Engine (SPE). The SPE models payload discovery as a genetic optimization problem.

Instead of testing 10,000 static strings, the PayloadEvolver maintains a small “population” of payloads (default: 50). It treats fuzzing as an iterative learning process. When a payload bypasses a WAF but fails to trigger an exploit (e.g., returning a 200 OK or a valid JSON structure but no SQL error), the engine assigns it a moderate fitness score and uses it as a “parent” for the next generation.

1.3 Mutation and Crossover Algorithms

In payload_evolver.py, the engine applies specific genetic operators to evolve the population.

1.3.1 Mutations: The engine randomly applies techniques to alter the string structure without destroying its exploit capability.

  • null_insert: Injects URL-encoded or raw null bytes (%00, \x00).
  • case_change: Swaps capitalization to break case-sensitive regex (e.g., sElEcT).
  • duplicate_segment: Duplicates chunks of the payload to confuse buffer-based filters.
  • char_replace: Randomly replaces non-critical characters with harmless alternatives to evade entropy checks.

1.3.2 Crossover Recombination: The engine selects two successful parent payloads (e.g., one that bypassed a WAF, and one that triggered a database error) and recombines them to breed a novel child payload.

  • interleave: Slices both parents into chunks and alternates them.
  • split: Takes the first half of Parent A and the second half of Parent B.
  • wrap: Nests one payload entirely inside the other.

Example Code Implementation:

def _crossover(self, parent1: str, parent2: str) -> str:
    strategy = random.choice(['split', 'interleave', 'wrap', 'inject'])
    
    if strategy == 'split':
        mid1 = len(parent1) // 2
        mid2 = len(parent2) // 2
        if random.random() < 0.5:
            return parent1[:mid1] + parent2[mid2:]
        else:
            return parent2[:mid2] + parent1[mid1:]