Open HTTP Redirect 开放重定向漏洞:URL 跳转校验缺陷与绕过技术 📅 2026/7/18 12:06:07 Open HTTP Redirect 开放重定向漏洞URL 跳转校验缺陷与绕过技术前言1. Open HTTP Redirect 核心理论基础1.1 漏洞本质与定义1.2 漏洞成立的三大必要条件1.3 完整钓鱼攻击链路1.4 服务端跳转 vs 客户端跳转DOM 型1.5 常见攻击场景与业务危害1.6 漏洞在安全榜单中的定位2. DVWA Open HTTP RedirectLow2.1 页面黑盒探测2.2 黑盒漏洞利用实操2.2.1 直接构造恶意跳转 URL2.2.2 伪装可信域名钓鱼链接实战场景2.3 源码审计无校验直接跳转3. DVWA Open HTTP RedirectMedium3.1 黑盒探测3.1.1 基础功能测试3.1.2 验证协议过滤防护机制3.1.3 黑盒推导校验规则3.2 黑盒攻击实操3.2.1 协议相对 URL 绕过原理3.2.2 构造 //evil.com 恶意 Payload3.2.3 攻击复现步骤3.2.4 正则过滤存在的逻辑缺陷3.3 源码审计4. DVWA Open HTTP RedirectHigh4.1 黑盒探测4.1.1 抓包对比 Low/Medium 行为差异4.1.2 复用 Medium 的 Payload 测试完全失效4.1.3 黑盒推导校验规则4.2 黑盒攻击绕过实操4.2.1 子串匹配校验漏洞原理4.2.2 外部域名拼接 info.php 构造 Payload4.2.3 完整攻击复现4.3 High 级别源码审计5. DVWA Open HTTP RedirectImpossible5.1 源码审计5.2 四级对比总结Low/Medium/High/Impossible5.3 最终安全修复方案免责声明前言上一篇我们详细拆解了 CSRF 跨站请求伪造漏洞的攻防全流程相信大家对借助用户身份伪造请求的攻击思路已经有了清晰的认识。今天我们继续 Web 漏洞系列来聊一个经常被低估、但在真实钓鱼和社工攻击中极其好用的漏洞——Open HTTP Redirect开放重定向。很多开发者觉得不就是个跳转吗能有什么危害但恰恰是这种轻视让开放重定向成为了钓鱼攻击的绝佳跳板。一个存在漏洞的可信域名跳转能让钓鱼链接的可信度提升数个等级用户看到熟悉的域名后往往放松警惕最终被诱导至恶意站点窃取账号凭证。1. Open HTTP Redirect 核心理论基础1.1 漏洞本质与定义开放重定向漏洞Open Redirect又称 URL 跳转漏洞对应的标准漏洞编号为CWE-601: URL Redirection to Untrusted Site。漏洞的本质一句话就能说清Web 应用程序接收用户可控的参数来构造跳转目标 URL但没有对该 URL 进行严格的合法性校验导致攻击者可以构造恶意链接将用户重定向到任意外部站点。用最直白的话讲网站有个跳转功能本来是跳转到自己站内的页面但因为没校验攻击者可以改成跳转到钓鱼网站而且链接前面还是正经域名用户看不出来。典型的漏洞 URL 长这样https://trusted-site.com/login?redirecthttps://evil.com/phish用户看到域名是trusted-site.com可信站点放心点进去结果啪一下就跳到了攻击者控制的evil.com整个过程行云流水几乎没有感知。1.2 漏洞成立的三大必要条件不是所有带跳转的地方都有漏洞必须同时满足以下三个条件条件一跳转目标 URL 完全或部分由用户可控参数名常见的有redirect、url、next、go、to、return_url、redirect_uri、jump、target等等用户输入的内容能直接或间接影响最终的跳转地址条件二服务端未对跳转目标做严格的白名单校验完全没校验校验了但能被绕过用了黑名单、关键字匹配等不靠谱的校验方式条件三跳转是服务端 3xx 响应或客户端自动触发服务端通过Location响应头触发 302/301 跳转最常见前端通过window.location、meta refresh等方式跳转DOM 型用户不需要额外点击确认访问即跳转1.3 完整钓鱼攻击链路开放重定向最经典的用法就是钓鱼完整攻击链路分四步走第一步寻找可信站点的跳转漏洞攻击者在目标公司的官网、登录页、OAuth 授权页等地方寻找存在开放重定向漏洞的 URL 参数。第二步构造恶意跳转链接把正常的跳转目标替换成攻击者的钓鱼站点地址得到一个披着可信域名外衣的恶意链接https://银行官网.com/login?redirecthttps://钓鱼网站.com/fake-login第三步社工诱导用户点击通过邮件、短信、QQ/微信等渠道把链接发给受害者话术通常是您的账户异常请点击链接登录核实。第四步用户跳转至钓鱼站点被窃取信息用户看到链接是正经银行域名放下戒心点击 → 浏览器先访问银行官网 → 官网 302 跳转到钓鱼网站 → 钓鱼网站高仿银行登录页 → 用户输入账号密码 → 攻击者拿到凭证。整个过程中用户的注意力都在域名是不是官方的上很少有人会去注意 URL 后面?redirect那串参数。1.4 服务端跳转 vs 客户端跳转DOM 型开放重定向按触发位置分两大类攻击效果略有区别类型触发位置典型特征可利用性服务端重定向后端代码返回 302/301 状态码 Location 头高最常见钓鱼效果最好客户端重定向DOM型前端 JS 代码window.location url跳转中可能被浏览器策略限制额外提一句DOM 型开放重定向在某些场景下甚至可以升级为 XSS——如果跳转支持javascript:伪协议的话直接就能执行 JS 代码危害直接上一个档次。1.5 常见攻击场景与业务危害很多人觉得开放重定向就是个低危小漏洞其实它的危害被严重低估了。主要攻击场景钓鱼诈骗最主流这是开放重定向的本职工作。用可信域名当幌子把用户骗到高仿钓鱼页偷账号密码成功率比直接发陌生域名高得多。OAuth 授权令牌窃取如果 OAuth 的redirect_uri校验不严或者可信域内存在开放重定向攻击者可以把授权码/access_token 拐到自己的服务器直接接管用户账号。绕过 SSRF 防护有些 SSRF 防护只校验请求的域名是不是内网攻击者可以让服务端先请求一个带开放重定向的外网地址再由重定向跳到内网变相绕过防护。恶意软件分发把下载链接伪装成可信站点的跳转用户以为是官方下载实际下的是木马病毒。绕过邮件安全网关企业邮件网关通常会过滤恶意域名的链接但开放重定向的链接主域名是可信的很容易绕过检测进到用户收件箱。1.6 漏洞在安全榜单中的定位CWE 编号CWE-601— URL Redirection to Untrusted Site开放重定向的标准定义OWASP Top 10虽然没有单独列项但常被归类到A01:2021 - Broken Access Control访问控制失效或A03:2021 - Injection注入的范畴属于不起眼但到处都是的基础漏洞CTF 定位属于 Web 方向的基础考点经常和 SSRF、XSS、CSRF、OAuth 等知识点结合出题单独考的话一般是送分题但组合起来就是难题漏洞评级单独的开放重定向一般评低危到中危但如果能结合 OAuth 偷 token、配合 SSRF 打内网直接升级为高危甚至严重一句话总结开放重定向本身伤害不高但作为攻击链的粘合剂极其好用经常是组合拳里的关键一环。对接下来就是 Low 级别我们按黑盒探测 → 漏洞利用 → 源码审计的顺序来。2. DVWA Open HTTP RedirectLow2.1 页面黑盒探测先不看源码我们以渗透测试者的视角先摸清楚这个页面的功能。进入 DVWA 的 Open HTTP Redirect 模块首先看到页面上有三个链接分别指向info.php?id1、info.php?id2、info.php?id3看起来是跳转到不同的信息页面。随便点一个比如第一个抓包看一下黑盒初步结论GET /vulnerabilities/open_redirect/source/low.php?redirectinfo.php?id1 HTTP/1.1存在一个redirect参数用来控制跳转目标服务端返回 302 状态码通过Location头触发跳转目前传的是站内相对路径info.php?id1那问题来了如果我把redirect参数改成一个外部网址会发生什么这就是我们要验证的漏洞点。2.2 黑盒漏洞利用实操Low 级别顾名思义就是最菜的级别一般没有任何防护。我们直接来测。2.2.1 直接构造恶意跳转 URL测试思路把redirect参数的值直接换成一个外部域名看能不能跳过去。构造 Payloadvulnerabilities/open_redirect/source/low.php?redirecthttps://www.baidu.com把这个 URL 在抓到的包里面改一下。结果啪一下很快啊直接跳到百度首页了。说明 Low 级别完全没有任何校验你传什么 URL 它就跳什么连是站内还是站外都不检查。2.2.2 伪装可信域名钓鱼链接实战场景光跳个百度没什么意思我们来模拟真实的钓鱼场景。假设攻击者的钓鱼网站是https://evil.com/fake-login高仿 DVWA 登录页攻击者会构造这样的恶意链接http://你的DVWA地址/vulnerabilities/open_redirect/source/low.php?redirecthttps://evil.com/fake-login然后把这个链接发给受害者话术比如“系统升级请点击链接重新登录http://你的DVWA地址/…”受害者一看域名是正经的 DVWA 地址或者真实场景下是公司官网、银行官网放心点进去结果直接被重定向到钓鱼页面输入账号密码就中招了。为什么钓鱼成功率高链接主域名是可信的用户不会怀疑跳转过程是服务端 302速度极快用户几乎察觉不到钓鱼页面可以做得和官方一模一样普通用户根本分辨不出来2.3 源码审计无校验直接跳转Low 级别的源码非常简单一共就几行我们逐行来看?php// 第1步检查 redirect 参数是否存在且不为空if(array_key_exists(redirect,$_GET)$_GET[redirect]!){// 第2步直接把 redirect 参数的值拼到 Location 头里触发跳转header(location: .$_GET[redirect]);exit;}// 如果参数不存在或为空返回500错误http_response_code(500);?pMissing redirect target./p?phpexit;?代码逻辑拆解参数检查用array_key_exists判断 GET 请求里有没有redirect参数并且值不为空直接跳转拿到参数值后没有做任何校验直接拼到Location响应头里返回给浏览器错误处理参数缺失的话返回 500 状态码和提示文字漏洞点就在第 4 行header(location: .$_GET[redirect]);$_GET[redirect]是用户完全可控的输入开发者没有检查它是不是站内地址、是不是合法域名、是不是允许的协议直接就拿来跳转了。你传info.php?id1它跳站内页你传https://evil.com它就跳恶意网站照单全收。一句话总结 Low 级别完全没有任何安全防护属于开发者根本没想过跳转功能会被滥用的典型反面教材。3. DVWA Open HTTP RedirectMedium好接下来 Medium 级别。开发者觉得 Low 太菜了加了点防护但是——没加对照样能绕。3.1 黑盒探测还是老规矩先不看源码从黑盒视角一步步摸。3.1.1 基础功能测试先把 DVWA 难度切到 Medium进入 Open HTTP Redirect 模块。页面看起来和 Low 级别一模一样还是三个链接点一下试试vulnerabilities/open_redirect/source/medium.php?redirectinfo.php?id1正常跳转没问题基础功能和 Low 一样。3.1.2 验证协议过滤防护机制那我们直接上 Low 级别的 Payload 试试看还能不能用medium.php?redirecthttps://www.baidu.com结果页面报错了提示Absolute URLs not allowed.不允许使用绝对URL。说明 Medium 级别确实加了防护不让直接跳http://或https://开头的绝对地址。那我们再试几个变种看看防护到底有多严测试 Payload结果https://baidu.com❌ 被拦截http://baidu.com❌ 被拦截HTTP://baidu.com❓ 试试大写//baidu.com❓ 试试不带协议ftp://baidu.com❓ 试试其他协议3.1.3 黑盒推导校验规则经过一轮测试我们大概能摸出 Medium 的校验规则过滤了http://和https://开头的绝对 URL只要参数里包含http://或https://就直接拒绝大小写都试了HTTP://也被拦说明正则是不区分大小写的相对路径没问题info.php?id1这种站内相对路径正常跳转说明校验只针对绝对URL相对路径不受影响那//baidu.com这种不带协议的呢这就是我们的突破口——协议相对 URL3.2 黑盒攻击实操3.2.1 协议相对 URL 绕过原理先讲一个冷知识URL 可以省略协议部分只写//域名这种写法叫协议相对 URLProtocol-relative URL。比如//www.baidu.com浏览器会自动使用当前页面的协议http 或 https来补全这个 URL。举个例子你在https://dvwa.com/页面上访问//evil.com浏览器会自动补全为https://evil.com效果和写完整的https://evil.com一模一样为什么能绕过Medium 的正则只过滤http://和https://开头的字符串协议相对 URL 是//开头不带http字样正则匹配不到直接放行了但浏览器拿到//evil.com照样能跳转到外部站点完美绕过分检。3.2.2 构造//evil.com恶意 Payload知道原理就简单了构造 Payloadmedium.php?redirect//www.baidu.com注意前面没有http:或https:直接就是两个斜杠。3.2.3 攻击复现步骤第一步构造恶意链接http://你的DVWA地址/vulnerabilities/open_redirect/source/medium.php?redirect//evil.com/fake-login第二步发给受害者还是熟悉的社工话术链接看起来还是正经的 DVWA 域名。第三步受害者点击跳转用户点进去 → 服务端返回 302Location 是//evil.com/fake-login→ 浏览器自动补全协议为https://evil.com/fake-login→ 成功跳转到钓鱼站点。还有一种就是使用ftp://baidu.comftp://baidu.com协议替换绕过唤起系统 FTP 工具跳转外部站点传入该Payload后Medium正则仅匹配http://、https://不含ftp关键字校验直接放行。浏览器接收到Location: ftp://baidu.com响应头会触发系统弹窗询问是否打开对应应用你截图里的跳转唤起弹窗就是这个原理同样达成跳转到外部非信任站点的效果属于第二种绕过思路。3.2.4 正则过滤存在的逻辑缺陷为什么开发者加了防护还是被绕了核心问题出在两个地方缺陷一只过滤了协议头没考虑协议相对 URL开发者想的是只要不让写完整的 http/https URL 就安全了但忘了还有//这种写法。缺陷二黑名单思路本身就不靠谱用黑名单过滤危险字符/字符串永远是被动防御攻击者总能找到你没考虑到的变种。今天你过滤了http://明天还有//、\\、javascript:、各种编码绕过……一句话总结黑名单防御防不胜防白名单才是正道。3.3 源码审计Medium 级别的源码如下我们逐行拆解?php// 第1步检查 redirect 参数是否存在且不为空if(array_key_exists(redirect,$_GET)$_GET[redirect]!){// 第2步正则匹配检查参数里有没有 http:// 或 https://if(preg_match(/http:\/\/|https:\/\//i,$_GET[redirect])){// 匹配到了 → 拦截返回500错误http_response_code(500);?pAbsolute URLs not allowed./p?phpexit;}else{// 没匹配到 → 直接跳转header(location: .$_GET[redirect]);exit;}}// 参数缺失的情况http_response_code(500);?pMissing redirect target./p?phpexit;?代码逻辑拆解参数校验先判断redirect参数有没有传、是不是空正则过滤核心防护就在第 4 行的preg_match正则表达式/http:\/\/|https:\/\//i意思是匹配http://或者https://末尾的/i表示不区分大小写匹配到了就拦截没匹配到就放行跳转防护的缺陷这个正则只认http://和https://两种协议其他的一概不管。所以Payload正则是否匹配结果http://evil.com✅ 匹配到http://❌ 拦截https://evil.com✅ 匹配到https://❌ 拦截//evil.com❌ 没有 http 字样✅ 放行 → 协议相对URL绕过ftp://evil.com❌ 是 ftp 不是 http✅ 放行 → 协议替换绕过javascript:alert(1)❌ 没有 http✅ 放行 → 伪协议绕过DOM型可用一句话总结 Medium 级别用黑名单思路只封了 http/https 两个协议没考虑协议相对 URL 和其他协议属于防了但没完全防的典型反面教材。好接下来 High 级别。开发者觉得 Medium 的防护太菜了换了个思路——强制要求跳转地址里必须包含info.php以为这样就只能跳站内页了。但还是太年轻。4. DVWA Open HTTP RedirectHigh4.1 黑盒探测还是老规矩先不看源码从黑盒视角一步步摸。4.1.1 抓包对比 Low/Medium 行为差异把 DVWA 难度切到 High进入 Open HTTP Redirect 模块。页面看起来还是一样的三个链接点一下正常跳转high.php?redirectinfo.php?id1正常跳转没问题。4.1.2 复用 Medium 的 Payload 测试完全失效先试试 Low 和 Medium 的 Payload 还能不能用测试1直接外部URLLow 级别 Payloadhigh.php?redirecthttps://www.baidu.com结果报错提示You can only redirect to the info page.你只能跳转到 info 页面测试2协议相对URLMedium 级别 Payloadhigh.php?redirect//www.baidu.com结果还是报错同样的提示。测试3ftp协议绕过high.php?redirectftp://baidu.com结果依然报错。看来 Medium 级别的绕过手法在 High 这里完全失效了防护升级了。4.1.3 黑盒推导校验规则报错信息很关键You can only redirect to the info page.“只能跳转到 info 页面”——那它是怎么判断你跳的是不是 info 页面的呢我们来做几组测试摸清楚校验规则测试 Payload结果推测info.php?id1✅ 正常跳转正常情况info.php✅ 正常跳转不带参数也可以INFO.PHP❌ 报错区分大小写abcinfo.php✅ 正常跳转前面加东西也行info.php/../✅ 正常跳转后面加东西也可以https://evil.com❌ 报错没有 info.php 就不行https://evil.com/info.php❓ 试试这个关键测试high.php?redirecthttps://evil.com/info.php结果居然跳转了虽然跳的是https://evil.com/info.php一个不存在的页面但确实成功跳转到了外部域名evil.com。黑盒结论High 级别的校验规则是——只要 redirect 参数的值里包含info.php这个子串就放行不管这个info.php在 URL 的什么位置也不管整个 URL 是不是站内地址。这就好办了。4.2 黑盒攻击绕过实操4.2.1 子串匹配校验漏洞原理High 级别用的是子串匹配的校验思路只要 URL 里有info.php这几个字就认为你跳的是站内的 info 页面是安全的。但这个逻辑有个致命缺陷info.php可以出现在 URL 的任意位置包括域名后面、参数里、路径里……攻击者只要在恶意 URL 里随便找个地方塞上info.php这几个字就能骗过校验。4.2.2 外部域名拼接 info.php 构造 Payload知道原理就简单了我们有好几种构造方式方式一路径拼接最常用high.php?redirecthttps://evil.com/info.php把info.php当成恶意站点上的一个路径骗过校验。方式二参数拼接更隐蔽high.php?redirecthttps://evil.com/phish?xinfo.php把info.php藏在 URL 参数里不影响实际跳转目标。方式三锚点拼接high.php?redirecthttps://evil.com/phish#info.php把info.php放在锚点#后面完全不影响页面跳转。三种方式都能成功绕过实战推荐用参数拼接最隐蔽。4.2.3 完整攻击复现第一步构造恶意钓鱼链接http://你的DVWA地址/vulnerabilities/open_redirect/source/high.php?redirecthttps://evil.com/fake-login?fooinfo.php注意看redirect参数的值是https://evil.com/fake-login?fooinfo.php真实目标https://evil.com/fake-login钓鱼页面凑数用的?fooinfo.php只是为了骗过校验不影响实际跳转第二步发给受害者链接主域名还是正经的 DVWA 地址用户看不出问题。第三步受害者点击跳转用户点进去 → 服务端检查到 URL 里有info.php放行 → 302 跳转到https://evil.com/fake-login?fooinfo.php→ 钓鱼页面正常显示那个fooinfo.php参数对钓鱼页面毫无影响。完美绕过效果和 Low 级别一模一样。4.3 High 级别源码审计High 级别的源码如下我们逐行拆解?php// 第1步检查 redirect 参数是否存在且不为空if(array_key_exists(redirect,$_GET)$_GET[redirect]!){// 第2步用 strpos 检查参数里有没有 info.php 这个子串if(strpos($_GET[redirect],info.php)!false){// 找到了 info.php → 认为是合法的直接跳转header(location: .$_GET[redirect]);exit;}else{// 没找到 info.php → 拦截返回500错误http_response_code(500);?pYou can only redirect to the info page./p?phpexit;}}// 参数缺失的情况http_response_code(500);?pMissing redirect target./p?phpexit;?代码逻辑拆解参数校验先判断redirect参数有没有传、是不是空关键字匹配核心防护就在第 4 行的strpos函数strpos(字符串, 子串)作用查找子串在字符串中第一次出现的位置! false表示只要能找到info.php这几个字就行不管它在什么位置找到了就直接跳转没找到就拦截报错防护的致命缺陷strpos只检查有没有不检查在哪。只要 URL 里任意位置出现了info.php这 8 个字符就会被判定为合法。所以Payloadstrpos 是否找到 info.php结果info.php?id1✅ 开头就是✅ 正常跳转https://evil.com/info.php✅ 路径里有✅ 绕过 → 跳外部站点https://evil.com/?xinfo.php✅ 参数里有✅ 绕过 → 跳外部站点https://evil.com#info.php✅ 锚点里有✅ 绕过 → 跳外部站点开发者以为强制要求包含 info.php 只能跳站内 info 页面但实际上只要在恶意 URL 里随便找个地方塞上info.php这几个字就能轻松骗过校验。一句话总结 High 级别子串匹配校验思路太想当然只验证了有没有关键字没验证是不是真的站内地址属于典型的防了但防错了地方。5. DVWA Open HTTP RedirectImpossible5.1 源码审计完整源码逐行解析?php$target;// 双重校验参数存在 参数必须为纯数字if(array_key_exists(redirect,$_GET)is_numeric($_GET[redirect])){// 将参数转为整数通过switch硬编码白名单映射跳转地址switch(intval($_GET[redirect])){case1:$targetinfo.php?id1;break;case2:$targetinfo.php?id2;break;case99:$targethttps://digi.ninja;break;}// 存在匹配的预设地址才执行跳转if($target!){header(location: .$target);exit;}else{?Unknown redirect target.?phpexit;}}?Missing redirect target.三层闭环防御机制输入类型强过滤is_numeric($_GET[redirect])限制redirect只能传入数字彻底杜绝用户自定义URL字符串攻击者无法传入https://evil.com、//evil.com、ftp://xxx等任何恶意跳转Payload。硬编码白名单映射核心防御跳转目标$target不由用户输入直接赋值而是通过数字索引匹配后端预先写死的固定地址传1→ 固定跳转info.php?id1传2→ 固定跳转info.php?id2传99→ 固定跳转https://digi.ninja除此之外所有数字都不会赋值$target直接提示未知跳转目标。跳转数据源完全可控最终header(location: . $target)拼接的变量是后端写死的静态字符串全程无任何用户可控内容参与URL构造不存在篡改跳转地址的空间。漏洞结论Impossible 级别完全不存在开放重定向漏洞不存在任何绕过方式。即便内置了一条外部域名https://digi.ninja该地址也是后端固定写死攻击者无法修改、替换成任意恶意站点不会产生钓鱼风险。5.2 四级对比总结Low/Medium/High/Impossible难度防护逻辑核心缺陷是否可绕过Low无任何校验直接拼接用户输入跳转完全信任用户可控参数可任意外部URL直接跳转Medium黑名单正则过滤http:///https://仅拦截网页协议忽略协议相对URL、ftp等其他协议可//evil.com、ftp://evil.com绕过High子串匹配校验URL包含info.php仅检查关键字是否存在不校验关键字位置与站点归属可恶意URL拼接info.php绕过Impossible数字强限制硬编码白名单映射无缺陷用户无法控制跳转目标URL不可绕过彻底封堵漏洞5.3 最终安全修复方案禁止直接使用用户输入拼接跳转地址使用数字索引固定白名单映射由后端预设全部合法跳转地址若业务必须接收URL参数采用完整域名白名单校验而非黑名单/子串匹配外部域名跳转增加二次确认页面阻断钓鱼攻击链路。免责声明本文所有内容仅用于网络安全技术研究与教学演示所有测试均在本地授权搭建的 DVWA 靶场环境中进行旨在帮助读者理解漏洞原理与防御机制。请勿将本文涉及的技术与方法用于任何未经授权的真实系统测试。任何利用本文内容进行的非法攻击行为均与作者无关由使用者自行承担相应法律责任。网络安全学习请严格遵守《中华人民共和国网络安全法》及相关法律法规仅在获得明确书面授权的前提下开展安全测试。