Skip to main content
Offensive360
Home / Knowledge Base / Open Redirect
Medium CWE-601 A01:2021 Broken Access Control

Open Redirect

Open redirect vulnerabilities allow attackers to redirect users from a trusted site to a malicious URL, enabling phishing and credential harvesting. Learn detection and prevention.

Affects: C#JavaJavaScriptPHPPythonRubyGo

What is Open Redirect?

An open redirect vulnerability occurs when a web application accepts a user-controlled URL parameter and redirects the browser to that URL without validation. Attackers exploit this to craft legitimate-looking links that silently forward victims to malicious sites.

Because the initial URL belongs to a trusted domain (e.g., https://your-bank.com/login?next=https://evil.com), users and security tools are less likely to flag the link as suspicious. It is commonly used as a phishing vector to steal credentials or OAuth tokens, and as a stepping stone in more complex attack chains such as SSRF bypasses.

How exploitation works

An application has a post-login redirect:

GET /login?returnUrl=https://attacker.com/fake-login HTTP/1.1
Host: trusted-site.com

The server redirects to returnUrl after authentication. The victim sees a trusted-site.com URL in their email, logs in, and is silently forwarded to a cloned login page controlled by the attacker.

OAuth flows are particularly risky: open redirects can be used to steal authorization codes by redirecting the OAuth callback to an attacker-controlled host.

Vulnerable code examples

C# / ASP.NET Core

// VULNERABLE: Redirects to any URL from query string
[HttpGet("login")]
public IActionResult Login(string returnUrl)
{
    // ... authenticate user ...
    return Redirect(returnUrl); // No validation — attacker controls destination
}

PHP

// VULNERABLE
$redirect = $_GET['next'];
header("Location: " . $redirect);
exit;

Secure code examples

C# / ASP.NET Core — local URL validation

// SECURE: Only redirect to relative (local) URLs
[HttpGet("login")]
public IActionResult Login(string returnUrl)
{
    // ... authenticate user ...
    if (Url.IsLocalUrl(returnUrl))
        return Redirect(returnUrl);

    return RedirectToAction("Index", "Home");
}

Python / Django — allow-list validation

from urllib.parse import urlparse
from django.conf import settings

def safe_redirect(request):
    next_url = request.GET.get('next', '/')
    parsed = urlparse(next_url)
    # SECURE: Reject any URL with a scheme or netloc (i.e. absolute URLs)
    if parsed.scheme or parsed.netloc:
        next_url = '/'
    return redirect(next_url)

What Offensive360 detects

  • Unvalidated redirect sinksResponse.Redirect(), header('Location:'), res.redirect(), and similar functions receiving user-controlled input
  • Partial validation bypasses — Allow-list checks that can be bypassed with //evil.com, \evil.com, or protocol-relative URLs
  • OAuth redirect_uri abuse — Redirect URIs that accept wildcard or insufficiently validated parameters
  • Meta refresh injection — User input reflected inside <meta http-equiv="refresh" content="0;url=..."> tags

Remediation guidance

  1. Avoid redirecting to user-supplied URLs — The safest approach is to redirect only to known, hard-coded destinations (e.g., map a page parameter to a fixed URL list).

  2. Use Url.IsLocalUrl() or equivalent — Framework-provided helpers correctly identify relative-only URLs and reject external destinations.

  3. Maintain an allow-list of approved redirect domains — If external redirects are required, check that the destination matches an explicit list of trusted domains.

  4. Reject protocol-relative URLs — URLs starting with // are treated as absolute by browsers; validate that the redirect target starts with / and does not contain ://.

  5. Encode returnUrl in tokens — Sign redirect targets with an HMAC so they cannot be tampered with in transit.

References

By Offensive360 Security Research Reviewed: March 2026

Detect Open Redirect automatically

Run Offensive360 SAST on your codebase to find this and 100+ other vulnerabilities.