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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16439618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 06:56:15  来源:igfitidea点击:

How to fix the HTTP Response splitting vulnerability with ESAPI

javaservletssecurityhttprequestesapi

提问by Lonzak

after a recent findbugs (FB) run it complains about a: Security - HTTP Response splitting vulnerabilityThe following code triggers it:

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

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

Basically the 'referrer' http parameter contains an url, to which, when clicking on a back button in our application the browser returns to. It is appended to the url as a parameter. After a bit research i know that i need to sanitize the referrer url. After a bit more research i found the esapiproject which seem to offer this kind of functionality:

基本上,'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);

However I didn't figure out how to detect e.g. jscript code or other stuff which doesn't belong to a referrer url. So how can I achieve that with esapi?

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

I tried:

我试过:

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

however this doesn't work. What I need is a function which results in:

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

http://www.google.com(ok)

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

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

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

Or is it enough to call the following statement?

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

encoder.encodeForHTMLAttribute(referrer);

Any help appreciated.

任何帮助表示赞赏。

采纳答案by Lonzak

Here's my final solution if anyone is interested. First I canonicalize and then URL decode the string. If a CR or LF exists (\n \r) I just cut of the rest of that potential 'attack' string starting with \n or \r.

如果有人感兴趣,这是我的最终解决方案。首先我规范化然后 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);
}

Theoretically i could have later verified the value against 'HTTPParameterValue' regex which is defined in the ESAPI.properties however it didn't like colon in the http:// and I didn't investigated further.

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

And one more remark after testing it: Most modern browser nowadays (Firefox > 3.6, Chrome, IE10 etc.) detect this kind of vulnerability and do not execute the code...

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

回答by Santosh

I would suggest white-listing approach wherein you check the referrerstring only for permissible characters. Regex would be a good option.

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

EDIT:

编辑:

The class org.owasp.esapi.reference.DefaultEncoderbeing used by you is not really encoding anything. Look at the source code of the method encodeForHTMLAttribute(referrer)here at grepcode. A typical URL encoding (encoding carriage return and line feed) too wont help.

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

So the way forward would be device some validation logic which checks for valid set of characters. Here is another insightful article.

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

回答by Kevin W. Wall

I think you have the right idea, but are using an inappropriate encoder. The Referer [sic] header value is really a URL, not an HTML attribute, so you really want to use:

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

encoder.encodeForURL(referrer);

encoder.encodeForURL(referrer);

-kevin

-凯文

回答by Atul Verma

The accepted answer will not work if in case there is "\n\r" in the string. Example: If I have string: "This is str\n\rstr", it returns "This is str\nstr"

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

Rectified version of above accepted answer is:

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

 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;
    }