Traversal Wordlist — Path Traversal & LFI Detection
This is the clearest demonstration of why normalised-field matching beats raw-byte matching. One http.uri rule replaces an unbounded set of encoding-specific signatures, and it also catches the encoding the attacker invents tomorrow.
Open in Red Team Toolkit — traversalTraversal Wordlist — Path Traversal & LFI Detection
This is the clearest demonstration of why normalised-field matching beats raw-byte matching. One http.uri rule replaces an unbounded set of encoding-specific signatures, and it also catches the encoding the attacker invents tomorrow.
Telemetry generated
| Log source | Field / identifier | What it shows |
|---|---|---|
| Web Access Log | status / sc-bytes | A 200 response with a plausible file size is the success signal. A traversal attempt that returns 200 and hundreds or thousands of bytes almost certainly retrieved a real file. A 400 or 403 with near-zero bytes is a blocked attempt. Track response size alongside status for every request containing traversal sequences. |
| Application Error Log | file_open_error / path | File-open errors referencing paths outside the intended web root indicate the application attempted to open the traversed path before rejecting it. These appear as exceptions in the application log and confirm the traversal reached the file-open call. |
| EDR / auditd | process_file_access | The definitive host-side proof. EDR or Linux auditd records the web server process opening files outside the web root. A file-open syscall from the web process targeting /etc/passwd, /etc/shadow, or any path outside the document root is unambiguous evidence of successful traversal. |
| WAF Log | matched_rule / raw_value | WAF rule matches tell you WHICH encoding variant was used, which reveals whether your normalisation pipeline is working. If the WAF fires on %252e%252e%252f but your SIEM rule only matches ../, your SIEM has a gap. Use WAF match data to audit your detection coverage. |
Detection rules
title: Path Traversal Patterns in Web Request URI
id: f6a7b8c9-d0e1-2345-fabc-456789012345
status: experimental
description: >
Matches normalised web request URI fields against path traversal keyword
groups covering plain sequences, single-encoded, double-encoded variants,
and sensitive file targets. Normalised-field matching means one rule covers
all encoding variants.
logsource:
category: webserver
detection:
plain:
- '../'
- '..'
- '..../'
- '....'
single_encoded:
- '%2e%2e%2f'
- '%2e%2e/'
- '..%2f'
- '%2e%2e%5c'
double_encoded:
- '%252e%252e%252f'
- '%252e%252e%255c'
- '%%32%65'
target_files:
- 'etc/passwd'
- 'etc/shadow'
- 'etc/hosts'
- 'proc/self/environ'
- 'windows/win.ini'
- 'boot.ini'
- 'web.config'
- '.env'
- '.git/config'
condition: plain or single_encoded or double_encoded or target_files
falsepositives:
- Authorised penetration testing
- Static site generators that include relative path strings in URLs
level: high
tags:
- attack.discovery
- attack.t1083
- attack.initial_access
- attack.t1190Evasion & counters
Single and double percent-encoding (%2e%2e%2f, %252e%252e%252f) to hide traversal sequences from signature matching.
Normalised-field matching — this is the whole lesson of this profile. Suricata's http.uri sticky buffer URL-decodes automatically. In SPL, apply urldecode() twice. One rule then catches every encoding variant including ones not yet invented.
Overlong UTF-8 sequences and alternate Unicode path separators (U+2215 ∕, U+FF0F /) to bypass normalisation.
Ensure the WAF and the application use the same canonicalisation library and reject paths that change under repeated normalisation passes. A path that normalises differently on the second pass than the first is malformed and should be rejected.
Null-byte truncation (%00) appended after the target filename to terminate the string in C-based runtimes.
Alert on %00 in any path parameter unconditionally — there is no legitimate reason for a null byte in a URL path. This is a one-line rule addition to any of the detections above.
Absolute paths (/etc/passwd directly) instead of traversal sequences, bypassing ../ detection entirely.
The sensitive-file-target Suricata rule and Sigma target_files group catch absolute path references independently of whether a ../ sequence is present. Both rules are needed together.
Rule tuning
Preventive control
Canonicalise the requested path and verify it resolves inside the intended directory before opening any file — this is the only reliable fix. Prefer an allowlist of permitted filenames over a denylist of traversal sequences: an allowlist of known-good filenames rejects everything else by default, including encoding variants not yet invented. Run the web process under a least-privileged account that has read access only to the web root, so a successful traversal cannot reach /etc/shadow or other sensitive system files.
