在最近的一个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/login?dest=http://google.com/%0D%0ALocation:javascript:%0D%0A%0D%0Aalert(document.cookie)(不行)
或者打电话给以下声明是否足够?
encoder.encodeForHTMLAttribute(referrer);
任何帮助表示感谢。
答案 0 :(得分: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&gt; 3.6,Chrome,IE10等)检测到这种漏洞并且不执行代码......
答案 1 :(得分:1)
我建议使用白名单方法,其中只检查referrer
字符串是否允许使用字符。正则表达式是一个不错的选择。
修改强>
您使用的类org.owasp.esapi.reference.DefaultEncoder
实际上并不是编码任何东西。查看方法encodeForHTMLAttribute(referrer)
here at grepcode的源代码。典型的URL编码(编码回车符和换行符)too wont help。
所以前进的方向是设备一些验证逻辑,它检查有效的字符集。这是another insightful article。
答案 2 :(得分:1)
我认为你有正确的想法,但使用的是不合适的编码器。 Referer [sic]标头值实际上是一个URL,而不是HTML属性,所以你真的想要使用:
encoder.encodeForURL(referrer);
-kevin
答案 3 :(得分: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;
}