You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PHP中移除URL协议部分及修复查询字符串重定向漏洞的方案咨询

Hey there! Let's break down your two PHP technical needs with robust, secure solutions:

1. Removing All Protocol Parts from URLs

To strip any protocol (like http://, https://, ftp://) from a URL, a targeted regular expression is perfect here. It matches the protocol prefix at the start of the string and replaces it with nothing:

function removeUrlProtocol($url) {
    // Matches any protocol (letters only) followed by :// at the start of the string
    return preg_replace('/^[a-zA-Z]+:\/\//', '', $url);
}

// Example usage:
$originalUrl = "https://test.dev/contact.php";
$cleanedUrl = removeUrlProtocol($originalUrl);
// Output: "test.dev/contact.php"

$anotherUrl = "ftp://file.example.com/docs";
$cleanedAnother = removeUrlProtocol($anotherUrl);
// Output: "file.example.com/docs"

This regex works because:

  • ^ anchors the match to the start of the string (so we don't accidentally replace protocol-like strings in the middle of a URL)
  • [a-zA-Z]+ matches any protocol name (HTTP, HTTPS, FTP, etc.)
  • :\/\/ matches the literal :// that follows protocols
2. Fixing the Open Redirect Vulnerability (Better Than Replacing Double Slashes)

Your current str_replace("//", "", $_GET['url']) approach has critical gaps—attackers can easily bypass it with tricks like http:/attack.hack (single slash) or pseudo-protocols like javascript:alert(1) (which could lead to XSS). Here are two far more reliable solutions:

Option 1: Force Internal/Relative Paths Only

This approach ensures the redirect target is always a valid internal path (either relative, like contact.php, or root-based, like /contact.php). Anything that looks like an external URL gets redirected to a safe default (e.g., your homepage):

$returnPage = $_GET['return_page'] ?? '/'; // Default to homepage if parameter is missing

// Block any URL that starts with a protocol (e.g., http://, javascript:) or contains double slashes
if (preg_match('/^[a-zA-Z]+:\/\//', $returnPage) || strpos($returnPage, '//') !== false) {
    $returnPage = '/';
}

// Optional: Add stricter validation to ensure it's a valid file/path format
if (!preg_match('/^(\/|\.\/|\.\.\/)?[a-zA-Z0-9_\-\/\.]+\.?[a-zA-Z]*$/', $returnPage)) {
    $returnPage = '/';
}

// Perform the safe redirect
header("Location: " . $returnPage);
exit;

Option 2: Validate the Target Domain

If you need to allow redirects to your own domain (including subdomains, if desired), use parse_url() to extract the target host and compare it to your site's host:

$currentHost = $_SERVER['HTTP_HOST']; // Gets your site's domain (e.g., test.dev)
$returnPage = $_GET['return_page'] ?? '/';

$parsedTarget = parse_url($returnPage);

// If the target has a host (i.e., it's an absolute URL), check if it matches your domain
if (isset($parsedTarget['host']) && $parsedTarget['host'] !== $currentHost) {
    $returnPage = '/'; // Redirect to safe default if domain doesn't match
}

// Safe redirect
header("Location: " . $returnPage);
exit;

Why These Are Better Than Your Original Approach

  • They block all external URL patterns, not just double slashes
  • They prevent pseudo-protocol attacks (like javascript: or data:) that could exploit your redirect
  • They enforce either internal paths or trusted domains, eliminating the open redirect risk entirely

内容的提问来源于stack exchange,提问作者rubo77

火山引擎 最新活动