Skip to content

Commit 7782e9d

Browse files
committed
feat(bypass): add path manipulation probes to header bypass
1 parent a7e93ef commit 7782e9d

10 files changed

Lines changed: 559 additions & 33 deletions

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
CHANGELOG
22
=======
33

4+
v5.14.2 (01.05.2026)
5+
---------------------------
6+
- (enhancement) extended `--header-bypass` with controlled path-manipulation probes after header-injection probes
7+
- (enhancement) added safe path-bypass variants: trailing slash, double leading slash, dot segment, semicolon suffix, case variation and URL-encoded segment
8+
- (enhancement) path-bypass probes are strict opt-in through the existing `--header-bypass` flow and do not change default scan behaviour
9+
- (enhancement) successful path-bypass candidates are stored in the existing `bypass` result bucket
10+
- (enhancement) added path-bypass report metadata: `bypass=path`, `bypass_variant`, `bypass_value`, `bypass_url`, `bypass_from_code` and `bypass_to_code`
11+
- (enhancement) JSON, HTML, CSV and SQLite reports preserve path-bypass evidence through detailed report items
12+
- (tests) added regression coverage for path-bypass generation, runtime reporting and debug output branches
13+
- (tests) full unittest suite passes after integration (`1221` tests)
14+
- (tests) coverage gate passes at `99%`
15+
416
v5.14.1 (01.05.2026)
517
---------------------------
618
- (enhancement) expanded target input parsing with IPv4 CIDR support for batch scans

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ It helps security researchers, penetration testers, bug bounty hunters, DevSecOp
6262
- smart auto-calibration for soft-404, wildcard, and catch-all responses;
6363
- technology fingerprint detection CMS, ecommerce platforms, frameworks;
6464
- passive WAF detection and WAF-safe scan mode;
65-
- controlled Header Injection Bypass probes for blocked `401` and `403` paths;
65+
- controlled header and path bypass probes for blocked `401` and `403` resources;
6666
- resumable scan sessions with checkpoint autosave;
6767
- CI/CD fail-on result bucket rules;
6868
- official Docker image distribution via GitHub Container Registry;
@@ -84,7 +84,7 @@ OpenDoor focuses on **context-aware discovery** instead of blind enumeration.
8484
|---|---|
8585
| **Fingerprint-first scanning** | OpenDoor can identify probable CMS platforms, frameworks, infrastructure providers, and WAF signals before deeper discovery. This helps you scan with context instead of blindly throwing a generic wordlist at the target. |
8686
| **WAF-aware behavior** | OpenDoor can detect probable WAF / anti-bot behavior and switch to a safer runtime profile with `--waf-safe-mode`, reducing noisy blocked scans and making defensive responses easier to understand. |
87-
| **Controlled header-bypass evidence** | OpenDoor can optionally probe blocked `401` and `403` paths with controlled per-request header-injection variants. It records exact evidence such as the header name, value, original status code, and resulting status code without mutating global scan headers. |
87+
| **Controlled bypass evidence** | OpenDoor can optionally probe blocked `401` and `403` resources with controlled header-injection and path-manipulation variants. It records exact evidence such as bypass type, header or path variant, probe value, original status code, and resulting status code without mutating global scan headers. |
8888
| **Multi-signal auto-calibration** | OpenDoor does not rely only on status code or response size. It compares multiple response signals such as body hashes, HTML structure, titles, redirects, stable headers, word count, line count, and normalized dynamic tokens to reduce soft-404 and wildcard false positives. |
8989
| **Transport-level workflows** | OpenDoor supports direct, proxy, OpenVPN, and WireGuard transport modes. It can also rotate transport profiles per target in authorized batch scans, which is not the same as manually starting a VPN before running a scanner. |
9090
| **Resumable long scans** | OpenDoor can save scan checkpoints and resume later. This matters when scans are interrupted by crashes, unstable networks, blocked routes, terminal disconnects, or long multi-target jobs. |
@@ -269,9 +269,9 @@ opendoor \
269269
--retries 5 \
270270
--delay 0.5
271271
```
272-
### Header Injection Bypass probes
272+
### Header and path bypass probes
273273

274-
Use this only on systems you are authorized to test. The feature is opt-in and probes blocked paths with temporary per-request headers.
274+
Use this only on systems you are authorized to test. The feature is opt-in and probes blocked resources with controlled temporary headers and safe path variants.
275275

276276
```bash
277277
opendoor \
@@ -282,6 +282,7 @@ opendoor \
282282
--header-bypass-limit 32 \
283283
--reports std,json,csv,sqlite
284284
```
285+
When --header-bypass is enabled, OpenDoor first tries configured header-injection variants and then safe path-manipulation variants such as trailing slash, dot segment, semicolon suffix, case variation, and URL-encoded segment.
285286
Customize trigger statuses, trusted IP values, and headers:
286287

287288
```bash
@@ -292,7 +293,7 @@ opendoor \
292293
--header-bypass-status 401,403 \
293294
--header-bypass-ips 127.0.0.1,10.0.0.1 \
294295
--header-bypass-headers X-Original-URL,X-Rewrite-URL,X-Forwarded-For,X-Real-IP \
295-
--reports json,html,sqlite
296+
--reports json,html,sqlite,csv
296297
```
297298

298299
### Proxy routing

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5.14.1
1+
5.14.2

docs/Usage.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,8 @@ Use this mode when scanning authorized targets protected by WAF, CDN, or anti-bo
464464

465465
Header Injection Bypass is an opt-in feature for authorized testing of blocked resources.
466466

467-
When enabled, OpenDoor probes configured blocked statuses with controlled, temporary per-request headers. If a probe changes a blocked response into a meaningful result, OpenDoor records it in the `bypass` result bucket with exact evidence.
467+
When enabled, OpenDoor probes configured blocked statuses with controlled, temporary per-request headers. `--header-bypass` flow also tries safe path-manipulation variants after header probes.
468+
If a probe changes a blocked response into a meaningful result, OpenDoor records it in the `bypass` result bucket with exact evidence.
468469

469470
### Enable header-bypass probes
470471

@@ -548,6 +549,23 @@ opendoor \
548549
--header-bypass-limit 0
549550
```
550551

552+
### Path-manipulation probes
553+
554+
Path-manipulation probes are enabled automatically when `--header-bypass` is enabled.
555+
556+
OpenDoor tries header-injection variants first, then safe path variants such as:
557+
558+
| Variant | Example |
559+
|---|---|
560+
| `trailing-slash` | `/admin``/admin/` |
561+
| `double-leading-slash` | `/admin``//admin` |
562+
| `dot-segment` | `/admin``/admin/.` |
563+
| `semicolon-suffix` | `/admin``/admin;/` |
564+
| `case-variation` | `/admin``/Admin` |
565+
| `url-encoded-segment` | `/admin panel``/admin%20panel` |
566+
567+
Path probes are controlled by the same `--header-bypass-limit` option.
568+
551569
### Reported evidence
552570

553571
Successful candidates are stored in the `bypass` bucket.
@@ -556,9 +574,11 @@ Detailed report items include:
556574

557575
| Field | Meaning |
558576
|---|---|
559-
| `bypass` | Bypass type, currently `header` |
560-
| `bypass_header` | Header that produced the candidate |
561-
| `bypass_value` | Header value used for the probe |
577+
| `bypass` | Bypass type: `header` or `path` |
578+
| `bypass_header` | Header that produced the candidate for header-based probes |
579+
| `bypass_variant` | Path-manipulation variant name for path-based probes |
580+
| `bypass_value` | Header value or path value used for the probe |
581+
| `bypass_url` | Full probe URL for path-based probes |
562582
| `bypass_from_code` | Original blocked status code |
563583
| `bypass_to_code` | Resulting status code |
564584

@@ -759,7 +779,7 @@ Available report formats:
759779
| `html` | Human-readable report |
760780
| `sqlite` | Structured local database for post-processing |
761781

762-
When `--header-bypass` is enabled and a candidate is found, report formats preserve bypass evidence:
782+
When `--header-bypass` is enabled and a header or path candidate is found, report formats preserve bypass evidence:
763783

764784
| Report | Header-bypass evidence |
765785
|---|---|

docs/examples/header-bypass-scans.md

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# 🧩 Header-bypass scans
1+
# 🧩 Header and path bypass scans
22

3-
This page contains practical Header Injection Bypass examples for authorized testing.
3+
This page contains practical bypass examples for authorized testing of blocked resources.
44

5-
Header Injection Bypass is opt-in and probes blocked resources with temporary per-request headers.
5+
Header-bypass mode is opt-in. It probes blocked resources with temporary per-request headers and safe path-manipulation variants.
66

77
---
88

@@ -19,6 +19,26 @@ By default, OpenDoor probes `401` and `403` responses.
1919

2020
---
2121

22+
## Header and path probe order
23+
24+
When `--header-bypass` is enabled, OpenDoor tries probes in a controlled order:
25+
26+
1. configured header-injection variants;
27+
2. safe path-manipulation variants.
28+
29+
Path variants include:
30+
31+
- trailing slash;
32+
- double leading slash;
33+
- dot segment;
34+
- semicolon suffix;
35+
- case variation;
36+
- URL-encoded segment.
37+
38+
All successful candidates are stored in the `bypass` bucket.
39+
40+
---
41+
2242
## WAF-aware header-bypass scan
2343

2444
```shell
@@ -98,10 +118,33 @@ Use:
98118

99119
---
100120

121+
## Report metadata
122+
123+
Header-based candidates may include:
124+
125+
- `bypass=header`;
126+
- `bypass_header`;
127+
- `bypass_value`;
128+
- `bypass_from_code`;
129+
- `bypass_to_code`.
130+
131+
Path-based candidates may include:
132+
133+
- `bypass=path`;
134+
- `bypass_variant`;
135+
- `bypass_value`;
136+
- `bypass_url`;
137+
- `bypass_from_code`;
138+
- `bypass_to_code`.
139+
140+
---
141+
101142
## Notes
102143

103144
- Header-bypass probes are disabled by default.
104-
- Probe headers are temporary per-request headers.
145+
- Header probes use temporary per-request headers.
146+
- Path probes use temporary probe URLs and do not mutate the original scan target.
105147
- Normal scan headers are not mutated.
106148
- Use `--header-bypass-limit` to keep probe volume controlled.
149+
- Method switching and large payload sets are intentionally deferred.
107150
- Use this only on systems you are authorized to test.

src/lib/browser/browser.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -811,15 +811,20 @@ def __probe_header_bypass(self, url, base_response_data):
811811
)
812812

813813
for variant in variants:
814-
headers = {variant.get('header'): variant.get('value')}
815-
response_object = self.__request_with_waf_safe_mode(url, extra_headers=headers)
814+
probe_url = variant.get('url') if variant.get('type') == 'path' else url
815+
extra_headers = None
816+
817+
if variant.get('type') != 'path':
818+
extra_headers = {variant.get('header'): variant.get('value')}
819+
820+
response_object = self.__request_with_waf_safe_mode(probe_url, extra_headers=extra_headers)
816821

817822
if response_object is None:
818823
continue
819824

820825
probe_response_data = self.__response.handle(
821826
response_object,
822-
request_url=url,
827+
request_url=probe_url,
823828
items_size=self.__pool.items_size,
824829
total_size=self.__pool.total_items_size,
825830
ignore_list=self.__reader.get_ignored_list()
@@ -832,7 +837,7 @@ def __probe_header_bypass(self, url, base_response_data):
832837
metadata = HeaderBypassProbe.metadata(variant, base_response_data, probe_response_data)
833838
tpl.debug(
834839
key='header_bypass_candidate',
835-
header=metadata.get('bypass_header'),
840+
header=metadata.get('bypass_header') or metadata.get('bypass_variant'),
836841
from_code=metadata.get('bypass_from_code') or '-',
837842
to_code=metadata.get('bypass_to_code') or '-'
838843
)
@@ -1186,6 +1191,10 @@ def __catch_report_data(self, status, url, size='0B', code='-', metadata=None):
11861191
item['bypass_header'] = metadata.get('bypass_header')
11871192
if metadata.get('bypass_value'):
11881193
item['bypass_value'] = metadata.get('bypass_value')
1194+
if metadata.get('bypass_variant'):
1195+
item['bypass_variant'] = metadata.get('bypass_variant')
1196+
if metadata.get('bypass_url'):
1197+
item['bypass_url'] = metadata.get('bypass_url')
11891198
if metadata.get('bypass_from_code') is not None:
11901199
item['bypass_from_code'] = str(metadata.get('bypass_from_code'))
11911200
if metadata.get('bypass_to_code') is not None:

0 commit comments

Comments
 (0)