4

在最近的 findbugs (FB) 运行后,它抱怨:安全性 - HTTP 响应拆分漏洞以下代码触发它:

String referrer = req.getParameter("referrer");
 if (referrer != null) {
  launchURL += "&referrer="+(referrer);
 }
resp.sendRedirect(launchURL);

基本上,“referrer”http 参数包含一个 url,当单击我们应用程序中的后退按钮时,浏览器会返回到该 URL。它作为参数附加到 url。经过一番研究,我知道我需要清理引荐来源网址。经过更多研究后,我发现esapi项目似乎提供了这种功能:

//1st canonicalize
import org.owasp.esapi.Encoder;
import org.owasp.esapi.Validator;
import org.owasp.esapi.reference.DefaultEncoder;
import org.owasp.esapi.reference.DefaultValidator;
[...]
Encoder encoder = new DefaultEncoder(new ArrayList<String>());
String cReferrer = encoder.canonicalize(referrer);

但是,我不知道如何检测不属于引荐来源网址的例如 jscript 代码或其他内容。那么我怎样才能用 esapi 实现呢?

我试过了:

Validator validator = new DefaultValidator(encoder);
validator.isValidInput("Redirect URL",referrer,"HTTPParameterValue",512,false);

但是这不起作用。我需要的是一个导致:

http://www.google.com (好的)

http://www.google.com/login?dest=http://google.com/%0D%0ALocation : javascript:%0D%0A%0D%0Aalert(document.cookie) (不行)

或者调用以下语句就足够了?

encoder.encodeForHTMLAttribute(referrer);

任何帮助表示赞赏。

4

4 回答 4

7

如果有人感兴趣,这是我的最终解决方案。首先我规范化然后对字符串进行 URL 解码。如果存在 CR 或 LF (\n \r),我只需删除以 \n 或 \r 开头的潜在“攻击”字符串的其余部分。

String sanitize(String url) throws EncodingException{
    
    Encoder encoder = new DefaultEncoder(new ArrayList<String>());
    //first canonicalize
    String clean = encoder.canonicalize(url).trim();
    //then url decode 
    clean = encoder.decodeFromURL(clean);
    
    //detect and remove any existent \r\n == %0D%0A == CRLF to prevent HTTP Response Splitting
    int idxR = clean.indexOf('\r');
    int idxN = clean.indexOf('\n');
    
    if(idxN >= 0 || idxR>=0){
        if(idxN<idxR){
            //just cut off the part after the LF
            clean = clean.substring(0,idxN);
        }
        else{
            //just cut off the part after the CR
            clean = clean.substring(0,idxR);
        }
    }
    
    //re-encode again
    return encoder.encodeForURL(clean);
}

从理论上讲,我稍后可以根据 ESAPI.properties 中定义的“HTTPParameterValue”正则表达式验证该值,但是它不喜欢 http:// 中的冒号,我没有进一步调查。

测试后又说一句:现在大多数现代浏览器(Firefox > 3.6、Chrome、IE10等)检测到这种漏洞并且不执行代码......

于 2013-05-16T07:15:57.803 回答
1

我建议使用白名单方法,其中您referrer只检查字符串中允许的字符。正则表达式将是一个不错的选择。

编辑:

org.owasp.esapi.reference.DefaultEncoder您正在使用的类并没有真正编码任何东西。encodeForHTMLAttribute(referrer) 在 grepcode中查看该方法的源代码。典型的 URL 编码(编码回车和换行)也无济于事

因此,前进的道路将是设备一些验证逻辑来​​检查有效的字符集。这是另一篇有见地的文章

于 2013-05-08T12:22:26.377 回答
1

我认为您的想法是正确的,但是使用了不合适的编码器。Referer [sic] 标头值实际上是一个 URL,而不是 HTML 属性,所以你真的想使用:

encoder.encodeForURL(referrer);

-凯文

于 2013-05-09T03:42:13.517 回答
-1

如果字符串中有“\n\r”,则接受的答案将不起作用。示例:如果我有 string: "This is str\n\rstr",它会返回"This is str\nstr"

上述接受的答案的修正版本是:

 String sanitizeCarriageReturns(String value) {
        int idxR = value.indexOf('\r');
        int idxN = value.indexOf('\n');

        if (idxN >= 0 || idxR >= 0) {
            if ((idxN > idxR && idxR<0) || (idxR > idxN && idxR>=0)) {
                    value = value.substring(0, idxN);
                } else if (idxN < idxR){
                    value = value.substring(0, idxR);
                } 

        }
        return value;
    }
于 2019-10-09T08:29:03.240 回答