Azure / Azure/static-web-apps

[Security] Encoded backslash bypass in post_logout_redirect_uri can cause open redirect

Open
#1,811 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
No language data
Stars
346
Forks
67
PR merge metrics
No merged PRs in 30d

Description

## Summary
Azure Static Web Apps managed authentication appears to accept an encoded backslash in `post_logout_redirect_uri`, then reflect the decoded value from `/.auth/logout/complete`. In browsers, the resulting URL can be normalized as a scheme-relative external redirect.

This appears to be an open redirect in the platform-managed `/.auth/*` authentication flow.

## Affected flow
1. `GET /.auth/logout?post_logout_redirect_uri=/%5Cattacker.example`
2. The request is accepted and establishes the managed-auth logout context.
3. `GET /.auth/logout/complete` with the resulting cookie.
4. The response may be a redirect such as:

`Location: /\\attacker.example`

5. Browser URL normalization can interpret `/\\attacker.example` as an off-origin scheme-relative URL.

## Expected behavior
`post_logout_redirect_uri` should be accepted only when it is a safe same-origin path, for example `/dashboard`. Inputs containing backslashes, encoded backslashes, control characters, or any form that can normalize to an authority should be rejected or replaced with a fixed local destination.

## Observed behavior
Obvious absolute and scheme-relative external URLs are rejected, but the encoded-backslash form is accepted and reflected by the logout completion endpoint. This suggests validation and browser URL parsing use different normalization rules.

## Security impact
An attacker can create a link that appears to target a legitimate Static Web App, but after logout the browser may be redirected to an attacker-controlled origin. This can support phishing and credential-harvesting flows.

## Reproduction
Use a test Static Web App domain and a cookie jar:

```bash
HOST=https://

curl -s -D - -o /dev/null -c cookies.txt \
$HOST/.auth/logout?post_logout_redirect_uri=/%5Cattacker.example

curl -s -D - -o /dev/null -b cookies.txt \
$HOST/.auth/logout/complete
```

Please verify the `Location` header without following redirects. A vulnerable response is one that reflects a value equivalent to `/\\attacker.example`, which browsers may normalize to an external scheme-relative URL.

## Notes
- This concerns the Azure Static Web Apps managed-auth endpoints, not application route configuration.
- A `staticwebapp.config.json` route rule for `/.auth/logout` does not appear to intercept the reserved managed-auth endpoint before the platform handler processes it.
- Please treat this as a security report and advise whether Microsoft prefers private disclosure through the MSRC process.

## Suggested fix
Normalize and validate the redirect target using browser-compatible URL parsing. Reject backslashes and encoded backslashes before validation, reject any target whose normalized authority differs from the current host, and use a fixed same-origin fallback when validation fails.

## Attack flow

```text
OPEN REDIRECT via SWA managed-auth
affected flow: `/.auth/logout` -> `/.auth/logout/complete`
================================================================================

ATTACKER VICTIM BROWSER AZURE STATIC WEB APPS
(platform managed-auth
layer, `/.auth/*`)
| | |
| phishing link | |
|------------------------->| |
| | |
| STEP 1: seed the redirect target into the cookie |
| | |
| | GET `/.auth/logout` |
| | ?post_logout_redirect_uri=/%5Cattacker.example
| |---------------------------------->|
| | | validate(uri)
| | | `/\` passes
| | 302 Found |
| | Location: `https://identity.5.azurestaticapps.net/`
| | `.redirect/logout?hostName=...`
| | Set-Cookie: `StaticWebAppsAuthContextCookie=`
| | Secure; HttpOnly; SameSite=None <-- sent cross-site
|<-------------------------| |
| | [target is stored in the managed-auth context]
| | |
| STEP 2: trigger the completion handler |
| | |
| | GET `/.auth/logout/complete` |
| | Cookie: `StaticWebAppsAuthContextCookie=`
| |---------------------------------->|
| | | reflect(cookie.uri)
| | 302 Found |
| | Location: `/\attacker.example` <== TAINTED
|<-------------------------| |
| | |
| | browser normalizes `/\` -> `//`
| | => scheme-relative URL
| v |
| `https://attacker.example` (off-origin)
| |
|<-------------------------+ attacker-controlled page
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reproducing the two-step /.auth/logout and /.auth/logout/complete flow with the provided curl commands, preserving the cookie and inspecting Location without following redirects. The report names no repository files and identifies the behavior as platform-managed. Done means unsafe encoded-backslash targets are rejected or replaced with a fixed same-origin destination.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure
Domain
authentication, cloud, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.