diff --git a/src/pentesting-web/proxy-waf-protections-bypass.md b/src/pentesting-web/proxy-waf-protections-bypass.md index 6311dd93ee1..2a6493a801c 100644 --- a/src/pentesting-web/proxy-waf-protections-bypass.md +++ b/src/pentesting-web/proxy-waf-protections-bypass.md @@ -76,6 +76,54 @@ location ~* ^/admin { } ``` +## Raw-vs-normalized URI authorization bypass + +A reverse proxy can give one request **two security identities** when authorization evaluates the original URI while routing later uses a decoded, dot-segment-normalized URI. In nginx, policy built from `$request_uri` can therefore disagree with the location/upstream selected from the normalized `$uri`; this is more dangerous than a normal ACL bypass when the first path segment selects a tenant, application, or permission domain.[[15]](#references) + +For example, an authorization subrequest may extract the target service from the raw path:[[15]](#references) + +```nginx +map $request_uri $target_service { + default ""; + ~^/proxy/([a-z]+)/ $1; +} +``` + +A request such as `/proxy/allowed/..%2f..%2fproxy/forbidden/api` can be authorized for `allowed`, then decoded and normalized to `/proxy/forbidden/api` for upstream routing. Establish a denied baseline against the protected path first, then compare it with the traversal form; a stable `403` to `200` change is strong evidence that the policy and routing layers interpreted different destinations.[[15]](#references) + +### Prefix exemptions become routing keys + +Authentication allowlists based on lexical prefix checks are especially exploitable across this boundary. If the gate exempts every raw path satisfying `startsWith("/api/auth/public/")`, traversal appended after that prefix can retain the exemption while normalization selects an unrelated protected handler:[[15]](#references) + +```text +raw: /api/auth/public/../../../proxy/internal/admin +policy: startsWith("/api/auth/public/") -> exempt +normalized: /proxy/internal/admin -> protected upstream +``` + +Preserve the path bytes during testing because HTTP clients may remove dot segments before sending the request:[[15]](#references) + +```bash +curl -sk --path-as-is \ + 'https://target/api/auth/public/../../../proxy/internal/admin' +``` + +Also audit the service-extraction grammar itself. A regex such as `[a-z]+` does not recognize legitimate identifiers containing hyphens, so the authorization backend may receive an empty/default service while routing still reaches the hyphenated application.[[15]](#references) + +### Trusted-host metadata as a second bypass + +After reaching an internal-only upstream, inspect how it determines the caller. A loopback service always sees the reverse proxy as its TCP peer; if it then treats client-influenced `Host` or `X-Forwarded-Host` as proof of local origin, an external request with `Host: 127.0.0.1` may satisfy the trusted-host check. This applies when the proxy rebuilds the forwarded header from the incoming Host value rather than a fixed, authenticated service identity.[[15]](#references) + +```bash +curl -sk --path-as-is \ + 'https://target/api/auth/public/../../../proxy/internal/admin' \ + -H 'Host: 127.0.0.1' +``` + +A compact review workflow is to log and compare the original URI, normalized URI, extracted authorization target, selected upstream, socket peer, and every forwarded identity header for the same request; test direct and traversal variants with no-permission and unauthenticated sessions. Fixes should canonicalize once before both authorization and routing, use exact route/method allowlist entries, validate the complete service-name grammar, and authenticate proxy-to-service identity instead of trusting client-derived host metadata.[[15]](#references) + +When this bypass exposes a dangerous internal handler, assess the reached primitive rather than repeating it here: [SQL injection](sql-injection/README.md), [command injection](command-injection.md), [JWT secret compromise](hacking-jwt-json-web-tokens.md), or [sudo command abuse](../linux-hardening/main-system-information/sudo-command-abuse.md).[[15]](#references) + ## Bypass Mod Security Rules ### Path Confusion @@ -323,5 +371,6 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri - [12] [cheatsheetseries.owasp.org - OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html) - [13] [PortSwigger Bypass Bot Detection extension](https://github.com/PortSwigger/bypass-bot-detection) - [14] [When a Web App Detects Burp Suite via TLS Fingerprinting](https://kecman.co/blog/burp-suite-tls-fingerprint-bot-detection-bypass.html) +- [15] [Pre-Auth RCE in UniFi OS — One Request to Root Behind Seven Products](https://catchify.sa/post/pre-auth-rce-unifi-os-one-request-to-root) {{#include ../banners/hacktricks-training.md}}