如何使用ESAPI修复HTTP响应拆分漏洞

问题描述 投票:4回答: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);

感谢任何帮助。

java servlets security httprequest esapi
4个回答
6
投票

如果有人感兴趣,这是我的最终解决方案。首先我规范化然后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-1);
        }
        else{
            //just cut off the part after the CR
            clean = clean.substring(0,idxR-1);
        }
    }

    //re-encode again
    return encoder.encodeForURL(clean);
}

从理论上讲,我可以稍后在ESAPI.properties中定义的'HTTPParameterValue'正则表达式中验证该值,但是它不喜欢http://中的冒号,因此我没有做进一步的研究。

测试后还有另外一句话:当今大多数现代浏览器(Firefox> 3.6,Chrome,IE10等)都检测到这种漏洞,并且不执行代码...


1
投票

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

encoder.encodeForURL(referrer);

-kevin


1
投票

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

编辑:

您正在使用的类org.owasp.esapi.reference.DefaultEncoder并未真正编码任何内容。查看方法encodeForHTMLAttribute(referrer) here at grepcode的源代码。典型的URL编码(对回车和换行进行编码)too wont help

因此,前进的道路将是使用一些验证逻辑来​​检查字符的有效集合。这是another insightful article


0
投票

如果字符串中有“ \ n \ r”,则接受的答案将无效。例:如果我有字符串:"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;
    }
© www.soinside.com 2019 - 2024. All rights reserved.