「URL 的开头明明是真域名,点进去却被转到完全不同的站点」——这就是开放重定向。下面讲解其原理和可靠的防御方法(不会写攻击步骤)。
为什么危险
危险的本质在于「对域名的信任被滥用」这一点。
| 被滥用的方式 | 会发生什么 |
|---|---|
| phishing 的跳板 | 链接开头是真域名→用户和过滤器都信任→被诱导到假站点 |
| 认证流程被劫持 | 篡改 OAuth 等的重定向目标,盯上 token/code 的传递 |
| 放大其他漏洞 | 与 SSRF 或 XSS 组合,扩大危害 |
为什么会成立(原理)
在「登录后回到原来的页面」之类的功能里,如果原样信任并转发返回地址 URL,就会发生。用户看到的 URL 的「开头」是真域名,所以很难一直怀疑到最后,这正是麻烦之处。
防御:不接收外部 URL
跳转目标只允许相对路径(最重要)
返回地址只接受 /dashboard 这样的相对路径,拒绝完整 URL(以 http://、// 开头的)。不给用户留下任何能指定跳转目标域名的余地。
对照允许列表校验
如果需要动态的跳转目标,就只对已知跳转目标的固定集合(映射表)放行。不匹配就回到默认页面。
不要依赖字符串判断
//evil、反斜杠、@、多重编码等绕过手法很多。改变接收方式的设计(相对路径+允许列表)比一条条往过滤器里追加规则更可靠。
实在要跳到外部就明确告知
如果跳到外部是规格需要,就插入一个确认页面,向用户显示「即将跳转到外部站点」。不要悄无声息地跳走。
本站的视角:单独看是「低」,但和 phishing 组合就很有杀伤力
开放重定向单独看时往往被认为严重度低,但因为它会把真域名的信任借出去,所以一旦和 phishing 或认证劫持组合起来,就会一下子变得很有杀伤力。正因如此,用「相对路径+允许列表」这种设计层面的一招从根上斩断才高效。它和 SSRF(让服务器去访问任意目标)的思路相似,二者共同的防御原则都是「不让用户来决定跳转目标・连接目标」。
接下来读
FAQ
Q开放重定向到底有什么问题?
因为 URL 的「最前面的域名」是可信的真站点(例如登录页),所以用户和邮件过滤器都会放心地点击。可是网站会把用户转发到任意外部站点,于是它会被滥用:把真域名当成「跳板」来做 phishing,或作为认证流程中窃取 token 的起点。
Q最有效的防御是什么?
就是「跳转目标不接收外部 URL」。登录后的返回地址等,不要用完整 URL,只允许相对路径(如 /dashboard),并对照允许列表(已知跳转目标的固定集合)进行校验。如果实在要跳到外部,就插入一个确认页面明确告知用户。
Q只检查是不是 http 就够了吗?
不够。还有许多绕过手法,比如以 // 开头的省略形式(//evil.example)、反斜杠、编码、用 @ 构造的迷惑性 URL 等。与其判断字符串,不如从设计上根本就不接收外部 URL(相对路径+允许列表)来得可靠。