Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

HTTP/1 Sequencer

The HTTP/1 Sequencer (mrpf_http1_sequencer) executes ordered HTTP/1 requests using raw packet I/O. Each step targets its own endpoint, enabling multi-host sequences. It supports variable extraction between steps and simultaneous request delivery using the first-sequence-sync technique for race condition testing.

Unlike the HTTP/1.1 Scanner which fires requests at scale across many targets, the sequencer executes steps sequentially — extracting data from responses to feed into subsequent requests. This makes it suitable for multi-step attack chains, cross-host authentication flows, and race condition exploitation.

Architecture

The sequencer uses two long-lived threads that persist for the entire sequence. A single datalink channel is opened once and reused across all steps. Before each step, the executor sends a SetTarget control message to the RX thread so it filters packets for the current step’s target.

graph TB
    subgraph Executor Thread
        E1[Render templates with current variables]
        E2[Create connections + send SYN packets]
        E3[Forward RX packets via TX]
        E4[Wait for RaceReady signals]
        E5[Fire trigger packets in tight loop]
        E6[Collect step results]
        E7[Run extractors + update variables]
        E8[Send SequenceStepResult to progress]
    end

    subgraph RX Thread
        R1[Filter incoming ethernet frames]
        R2[Drive TCP handshake]
        R3[Drive TLS state machine]
        R4[Send outgoing packets to executor]
        R5[Race: send future byte + signal RaceReady]
        R6[Emit completed request/response pairs]
    end

    subgraph Progress Thread
        P1[Collect SequenceStepResults]
    end

    E1 --> E2 --> E3
    E3 --> E4 --> E5 --> E6 --> E7 --> E8
    E8 -->|next step| E1

    R1 --> R2 --> R3 --> R4
    R3 --> R5
    R3 --> R6

    R4 -->|SendPacket| E3
    R5 -->|RaceReady + trigger packet| E4
    R6 -->|StepResult| E6
    E8 -->|SequenceStepResult| P1

Thread Communication

The RX thread communicates with the executor via RxMessage:

MessageDirectionPurpose
SendPacket(Vec<u8>)RX -> ExecutorOutgoing TCP/TLS packet to send via TX
RaceReady { syn_cookie, trigger_packet }RX -> ExecutorConnection ready for race trigger
StepResult { syn_cookie, request, response }RX -> ExecutorCompleted request/response pair
Error { syn_cookie, error }RX -> ExecutorConnection-level error

The executor controls the RX thread via RxControl:

MessageDirectionPurpose
SetTarget { ip, port }Executor -> RXUpdate packet filter for the next step’s target
StopExecutor -> RXShut down the RX thread gracefully

Execution Flow

For each step in the sequence:

  1. Set target — send RxControl::SetTarget to the RX thread with this step’s IP and port
  2. Render templates with current variables (two-pass rendering using the step’s target)
  3. Create SequencerConnection(s) with rendered payloads
  4. Send SYN packet(s) via the datalink TX
  5. Event loop: forward packets from RX, collect results
  6. Extract values from responses (single steps only), merge into variable map
  7. Report SequenceStepResult to progress thread
sequenceDiagram
    participant E as Executor
    participant RX as RX Thread
    participant T as Target

    Note over E: Step N begins
    E->>T: SYN packet(s)
    T->>RX: SYN-ACK
    RX->>E: SendPacket (ACK)
    E->>T: ACK

    Note over RX: TLS handshake (if HTTPS)
    RX->>E: SendPacket (ClientHello)
    E->>T: ClientHello
    T->>RX: ServerHello + Cert + Done
    RX->>E: SendPacket (Key Exchange + Finished)
    E->>T: Key Exchange + Finished

    Note over RX: Encrypt & send HTTP request
    RX->>E: SendPacket (encrypted request data)
    E->>T: Request data

    T->>RX: Response data
    RX->>E: StepResult (request, response)

    Note over E: Run extractors, update variables
    Note over E: Step N+1 begins...

First-Sequence-Sync (Race Conditions)

The key innovation of the sequencer is first-sequence-sync for race condition testing. When a step uses SequenceStepType::Race, all requests are delivered to the server simultaneously with sub-microsecond precision.

Why Raw Packets?

Standard sockets with Barrier synchronization have 1-5ms of jitter between threads. Raw packets through a single datalink TX in a tight loop achieve microsecond-level jitter. Combined with first-sequence-sync, the server’s TCP stack delivers data to ALL connections simultaneously.

How It Works

For N concurrent race requests:

  1. All N connections complete TCP + TLS handshakes normally
  2. The full HTTP request is encrypted (TLS) or staged (plain TCP)
  3. All data is sent except the last 2 bytes per connection
  4. A “future byte” (the last byte) is sent at TCP sequence number S+1 — the server’s TCP stack buffers it because there’s a 1-byte gap at sequence S
  5. When all N connections signal “race ready”, N trigger packets (1 byte each at sequence S) are sent in a single tight TX loop
  6. Each trigger fills the gap, causing TCP reassembly and simultaneous data delivery to the application layer
sequenceDiagram
    participant E as Executor
    participant T as Target Server
    Note over E,T: N connections established + TLS complete

    rect rgb(70, 70, 120)
    Note over E,T: Hold-back Phase (per connection)
    E->>T: Request data (all except last 2 bytes)
    E->>T: Future byte at seq S+1 (out-of-order)
    Note over T: TCP buffers future byte (gap at seq S)
    end

    Note over E: All N connections "race ready"

    rect rgb(120, 70, 70)
    Note over E,T: Trigger Phase (tight loop)
    E->>T: Conn 1: trigger byte at seq S
    E->>T: Conn 2: trigger byte at seq S
    E->>T: Conn N: trigger byte at seq S
    end

    Note over T: TCP reassembly completes for ALL connections
    Note over T: Application receives N requests simultaneously

For TLS connections, withholding even 1 byte of a TLS record prevents the server from decrypting ANY of the HTTP request until the trigger arrives. This makes the synchronization even tighter than plain TCP.

Template System

Templates use a two-pass rendering system:

Pass 1 — User variables via mrpf_templates::Engine:

  • ${VAR} syntax with skip_missing=true
  • Single value replacement only (no cartesian product)
  • Variables from config + extracted from previous steps

Pass 2 — Host variables via byte-level Aho-Corasick replacement:

  • ${IPV4} — target IP address
  • ${PORT} — target port
  • ${SNI} — TLS Server Name Indication
  • ${CONTENT_LENGTH} — computed from body after \r\n\r\n

Extractors

Extractors pull values from HTTP responses and store them as template variables for subsequent steps. They are only available on Single steps (not Race steps).

SourceDescriptionExample
Header(name)HTTP header value (case-insensitive)Set-Cookie
JsonPath(path)Dot-notation JSON pathdata.token, items[0].id
Regex { pattern, group }Regex capture groupcsrf_token=([^;]+), group 1
StatusCodeHTTP status code as string200, 302
BodyEntire response bodyFull text content

Connection Types

SequencerConnection supports both plain TCP and TLS, implementing the mrpf_engine::Connection trait:

  • Plain TCP: Stages raw HTTP bytes, emits in MSS-sized chunks
  • TLS: Uses rustls::UnbufferedClientConnection for raw packet TLS, encrypts HTTP payload into appdata staging
  • Race mode: Both types support hold-back of last 2 bytes for first-sequence-sync

File Structure

scanners/mrpf_http1_sequencer/src/
├── lib.rs           # Public API: Http1Sequencer
├── config.rs        # Http1Sequence, SequenceStep, SequenceStepType, Extractor, SequenceTarget
├── connection.rs    # SequencerConnection: Connection impl, TLS+plain, race mode
├── error.rs         # Error/Result types
├── executor.rs      # Step orchestration, TX forwarding, trigger sending
├── extractor.rs     # Response data extraction (header, JSON, regex, etc.)
├── progress.rs      # SequencerMessage, SequenceStepResult, ProgressHandler
├── receive.rs       # RX thread: packet processing, TLS driving, race signaling
└── template.rs      # Two-pass template rendering