漏洞介绍
假设在请求中提交了一个由标准的字母和数字字符组成的字符串,如 index.html,那么包含此 cookie 的 HTTP 响应可能表现为以下形式:
HTTP/1.1 200 OK
...
location: index.html
...
然而,因为该位置的值由未经验证的用户输入组成,所以仅当提交给 some_location 的值不包含任何 CR 和 LF 字符时,响应才会保留这种形式。
如果攻击者提交的是一个恶意字符串,比如 :
index.html\r\nHTTP/1.1 200 OK\r\n...
那么此 HTTP 响应就会被分割成以下形式的两个响应:
HTTP/1.1 200 OK
location: index.html
HTTP/1.1 200 OK
...
解决方案
在设置HTTP响应头的代码中,过滤回车换行(%0d%0a、%0D%0A)字符
原代码
String code = request.getParameter("code");
StringBuffer url = new StringBuffer();
if (StringUtils.isBlank(code)) {
url.append("http://19.1.1.1");
} else {
url.append("http://19.1.1.1").append("?code=").append(code);
}
logger.info("oauthCodeLogin url={}", url);
response.sendRedirect(url.toString());
修改后
String code = request.getParameter("code");
String url = getOauthCodeLoginJumpUrl(code);
response.sendRedirect(url);
/**
*修复Header Manipulation漏洞
*
* @param code
* @return
*/
private String getOauthCodeLoginJumpUrl(String code) {
StringBuffer url = new StringBuffer();
if (StringUtils.isBlank(code)) {
url.append("http://19.1.1.1");
} else {
String regex = "[`~!@#$%^&*()\\+\\=\\{}|:\"?><【】\\/r\\/n]";
Pattern pa = Pattern.compile(regex);
Matcher ma = pa.matcher(code);
if (ma.find()) {
code = ma.replaceAll("");
}
url.append("http://19.1.1.1").append("?code=").append(code);
}
return url.toString();
}
参考:
https://www.cnblogs.com/cyjaysun/p/4392867.html
https://blog.csdn.net/YSF2017_3/article/details/96862705