如何正确转义Location:header值?

问题描述:

In my webapp I'm using HTTP Location: headers for redirect (e.g. POST/redirect/GET). But the target locations have to be dynamic (e.g. login.php?dest=pagexy.php). We all know that any user-modifiable input has to be properly escaped to prevent XSS, so

 header('Location: '.$_REQUEST['dest']);

looks wrong. Simple urlencode-ing can only be used for simple files, not paths (e.g. cross-domain URLs with Single-Sign-On).

I've also read about vulnerabilities like:

Location: javascript:...bad.stuff...  or
Location: data:text/html:base64,...

Having an explicit whitelist of destinations would probably the most secure solution, but is tedious and might even not be possible for all use-cases.

Solutions?

Edit:

  1. Is urlencoding enough/correct for simple files? Assume a recent PHP version (> 5.1.2, AFAIK) that forbids newlines in header().

  2. How can I safely handle cross-domain credential-checking without knowing each other-domain beforehand?

在我的webapp中,我使用HTTP Location: code>标题进行重定向(例如POST / 重定向/ GET)。 但目标位置必须是动态的(例如 login.php?dest = pagexy.php code>)。 我们都知道任何用户可修改的输入都必须正确转义以防止XSS,所以 p>

  header('Location:'。$ _ REQUEST ['dest']); \  n  code>  pre> 
 
 

看起来不对。 简单的 urlencode code> -ing只能用于简单文件,而不能用于路径(例如,具有单点登录的跨域URL)。 p>

我也是 阅读有关以下漏洞的信息: p>

 位置:javascript:... bad.stuff ...或
位置:data:text / html:base64,... 
   pre> 
 
 

明确的目的地白名单可能是最安全的解决方案,但是很乏味,甚至可能无法用于所有用例。 p>

解决方案? p>

编辑: strong> p>

  1. urlencoding足够/正确 简单文件? 假设最近的PHP版本(> 5.1.2,AFAIK)禁止在header()中使用换行符。 p> li>

  2. 如何安全地处理跨域 凭证检查而不事先知道其他域名? p> li> ol> div>

Simple: DON'T EVER DO THAT.

If you must redirect the user, don't ever let them tell you where they are going.

If you absolutely must do that, urlencode the the input, whitelist the domains, and strip parameters that you haven't whitelisted. Better yet, don't let them tell you what domain - produce that using some other backend switch.

If you don't seriously lock that down, you will be vulnerable to all kinds of things. Be especially careful that they can't put a linebreak in there.

More info:

There actually occurs three kinds of attacks:

  1. HTTP Response Splitting, but as mentioned is some the comments, header() filters CRLF symbols.
  2. Open Redirect, which I suppose cannot be mitigated in your case.
  3. XSS. urlencode() is useless, don't bother it. You should make sure URL is http:// (or https://) as long as it's possible to make redirect to javascript: (some browsers allow it, but not all) and data: URIs.

For more information on Open Redirect and its issues see presentation at OWASP AppSec 2010 by sirdarckcat and thornmaker