未经验证的URL重定向

Web表单在成功提交数据后重定向到不同页面是很常见的。这通常通过HTTP请求中的nextreturn参数完成。任何HTTP参数都可由用户控制,并可能被攻击者滥用以将用户重定向到恶意网站。

这通常用于网络钓鱼攻击,例如攻击者可以将用户从合法的登录表单重定向到虚假的、由攻击者控制的登录表单。如果页面看起来足够像目标网站,并诱骗用户相信他们输错了密码,攻击者就可以说服用户重新输入他们的凭据并将其发送给攻击者。

这是一个恶意重定向URL的示例

https://good.com/login.php?next=http://bad.com/phonylogin.php

为了对抗这种类型的攻击,所有URL在用于重定向用户之前都必须经过验证。这应确保重定向会将用户带到您网站内的页面。

错误

此示例仅处理“next”参数,没有进行任何验证

import os
from flask import Flask,redirect, request

app = Flask(__name__)

@app.route('/')
def example_redirect():
    return redirect(request.args.get('next'))

正确

以下是使用Flask web框架的示例。它检查用户将被重定向到的URL是否源自与提供内容的服务器相同的主机。

from flask import request, g, redirect
from urlparse import urlparse, urljoin


def is_safe_redirect_url(target):
  host_url = urlparse(request.host_url)
  redirect_url = urlparse(urljoin(request.host_url, target))
  return redirect_url.scheme in ('http', 'https') and \
    host_url.netloc == redirect_url.netloc


def get_safe_redirect():
  url =  request.args.get('next')
  if url and is_safe_redirect_url(url):
    return url

  url = request.referrer
  if url and is_safe_redirect_url(url):
    return url

  return '/'

Django框架包含一个django.utils.http.is_safe_url函数,可用于验证重定向,而无需实现自定义版本。

后果

  • 未经验证的重定向可能使您的网站成为网络钓鱼攻击的目标,从而导致用户凭据被盗。

  • OSSA-2012-012

参考