整理一下最近修复的漏洞
==== =环境:Java、tomcat、Linux====
1、目标URL存在http host头攻击漏洞
解决方案:
(1)将tomcat升级到7及以上版本
(2)修改tomcat中/conf/Server.xml配置文件
将host 节点里面 name名称改为域名,appBase:应用的目录
(3)Linux上增加hostname
Vi /etc/hosts
修改好确保有成功
ping hostname
(4)用burpsuite验证漏洞是否通过,具体过程可以百度一下。当时没截图
ps:这个方案是针对绿盟扫漏访问静态资源url后面不加斜杠导致的Host头攻击。坑死人- - 正常在系统设置白名单、添加host过滤器就行了。
2、目标主机可能存在缓慢的HTTP拒绝服务攻击
解决方案:
方法一:修改tomcat中 \conf\server.xml 配置文件 connectionTimeout="20000"
*connectionTimeout:网络连接超时。
20000改为5000 (询问了扫漏人员的攻击速度)
\conf\web.xml 中<session-timeout>30</session-timeout>
后添加
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
链接: 参考博客地址.
Ps:如果还是被查出漏洞,说明漏洞攻击速度比改的还要快,根据实际情况去选择时间是否还要再改小一点
方法二:
Linux用命令行在apache(不是tomcat)加载两个新模块mod_reqtimeout和mod_qos(如果有就不用重新加载),具体过程可以参考博客地址
链接: 参考博客地址.
3、XSS扫描跨站式漏洞、SQL注入漏洞
解决方案:
在项目中增加过滤器过滤请求的特殊字符
public class XSSFilter
implements Filter {
private static Logger log = Logger.getLogger(XSSFilter.class);
public void init(FilterConfig filterConfig)
throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String requestHost = ((HttpServletRequest) servletRequest).getHeader("host");
HttpServletRequest request = (HttpServletRequest) servletRequest;
request.setCharacterEncoding("UTF-8");
Map parameters = servletRequest.getParameterMap();
if ((parameters != null) && (parameters.size() > 0)) {
for (Iterator iter = parameters.keySet().iterator(); iter.hasNext(); ) {
String key = (String) iter.next();
String[] values = (String[]) parameters.get(key);
for (int i = 0; i < values.length; i++) {
//过滤请求特殊字符,扫描跨站式漏洞
if (("bingo".equals(guolv(values[i])))) {
System.out.println("requestStr: ======================== " + values[i]);
System.out.println("完整的地址是====" + request.getRequestURL().toString());
System.out.println("提交的方式是========" + request.getMethod());
System.out.println("======访问地址发现非法字符,已拦截======");
return;
}
}
}
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(
(HttpServletRequest) request);
HttpServletResponse resp = (HttpServletResponse) response;
resp.addHeader("x-frame-options", "SAMEORIGIN");
resp.addHeader("Set-Cookie", "Path=/; Secure; HttpOnly");
chain.doFilter(xssRequest, response);
}
public void destroy() {
}
public static String guolv(String a) {
return a;
}
public String guolv(String a) {
if ((StringUtils.isNotEmpty(a)) && (
(a.contains("%22")) || (a.contains("%3E")) || (a.contains("%3e")) || (a.contains("%3C")) || (a.contains("%3c")) || (a.contains("%2Fr%2Fn")) || (a.contains("%2fr%2fn")) || (a.contains("%2Fr")) || (a.contains("%2fr")) || (a.contains("%2Fn")) || (a.contains("%2fn")) || (a.contains("%28")) || (a.contains("%29")) || (a.contains("%20")) || (a.contains("<")) || (a.contains(">")) || (a.contains("\"")) || (a.contains("'")) || (a.contains("/r/n")) || (a.contains("/r")) || (a.contains("\\(")) || (a.contains("\\)")) || (a.contains("/n")) || (a.contains("+")) || (a.contains(" and ")) || (a.contains(" or ")) || (a.contains("1=1")))) {
return "bingo";
}
return a;
}
web.xml
<filter>
<filter-name>xssFilter</filter-name>
<filter-class>com.xxx.xxx.XSSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>xssFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4、跨站请求伪造(CSRF)漏洞
解决方案:
方案一:
网上很多都是关于解决用户登录后请求产生的漏洞
(1)用户登录时在session上添加token
(2)请求时再去判断这个token是否和请求的token一致
方案二:
针对扫漏访问公共页面,用户无需登录就能访问产生的csrf漏洞(= =再次吐槽什么玩意)
我的做法是
(1)在过滤器里先去判断是否有session。当session为空时添加session;否则判断session是否一致
(2)请求时在jsp页面上将session进行hash算法加密(网上看到说一般扫漏看到hash加密就不愿意去测了也不知道真假,蛮加密一下)
(3)项目中被扫漏的是a标签的url,所以用js去添加token;有用Ajax请求的则添加到header里
$(function(){
updateTags();
});
// javascript的String到int(32位)的hash算法
function hash(str) {
var hash = 0;
if (str.length == 0) return hash;
for (i = 0; i < str.length; i++) {
char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash; // Convert to 32bit integer
}
return hash;
}
function updateTags() {
var token = "<%=session.getAttribute("token") %>";
var all = document.getElementsByTagName('a');
var len = all.length;
// 遍历所有 a 元素
for (var i = 0; i < len; i++) {
var e = all[i];
updateTag(e, 'href', hash(token));
}
}
function updateTag(element, attr, token) {
var location = element.getAttribute(attr);
if (location != null && location != '') {
var fragmentIndex = location.indexOf('#');
var fragment = null;
if (fragmentIndex != -1) {
//url 中含有只相当页的锚标记
fragment = location.substring(fragmentIndex);
location = location.substring(0, fragmentIndex);
}
var index = location.indexOf('?');
if (index != -1) {
//url 中已含有其他参数
location = location + '&token=' + token;
} else {
//url 中没有其他参数
location = location + '?token=' + token;
}
if (fragment != null) {
location += fragment;
}
element.setAttribute(attr, location);
}
}
Ajax添加header
beforeSend: function (XMLHttpRequest){
XMLHttpRequest.setRequestHeader("token", $("#token").val());
},
后台代码判断:
Map parameters = servletRequest.getParameterMap();
if ((parameters != null) && (parameters.size() > 0)) {
HttpServletRequest req = (HttpServletRequest)request;
HttpSession s = req.getSession();
if (request.getServletPath().toString().contains("/sys/TestAction")) {
// 从 session 中得到 token 属性
String sToken = (String) s.getAttribute("token");
if (sToken == null) {
// 产生新的 token 放入 session 中
sToken = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";
s.setAttribute("token", sToken);
} else {
// 从 HTTP 头中取得 token
String xhrToken = req.getHeader("token");
// 从请求参数中取得 csrftoken
String pToken = req.getParameter("token");
Integer hasha=sToken.hashCode();
if (sToken != null && xhrToken != null && sToken.hashCode()==Integer.parseInt(xhrToken)) {
} else if (sToken != null && pToken != null && ((sToken.hashCode())==Integer.parseInt(pToken))) {
} else {
request.getRequestDispatcher("error.jsp").forward(request, response);
}
}
}
}
验证是否通过漏洞教程: 参考博客地址.
5、站点存在javascript框架库漏洞
解决方案:
替换jquery版本,根据系统兼容性升级到最高版本
6、HTTP头信息泄露(低危)
解决方案:
修改tomcat中 \conf\server.xml 配置文件中,为connector元素添加server=" ",是空格,在response header中server的信息就变为空了
<Connector server=" " port="8443" URIEncoding="UTF-8"/>
7、点击劫持、缺少HttpOnly属性(低危)
解决方案:
过滤器中添加
HttpServletResponse resp = (HttpServletResponse) response;
resp.addHeader("x-frame-options", "SAMEORIGIN");
resp.addHeader("Set-Cookie", "Path=/; Secure; HttpOnly");
8、长时间拒绝服务密码
解决方案:
前后端校验密码长度
9、内容安全策略 (CSP) 、HTTP X-XSS-Protection缺失
解决方案:
过滤器中添加
HttpServletResponse resp = (HttpServletResponse) response;
resp.addHeader("Content-Security-Policy", "default-src https: http: 'unsafe-inline' 'unsafe-eval';connect-src https: http:");//针对safi和chrome
resp.addHeader("X-XSS-Protection", "1; mode=block");
10、应用程序错误信息泄露
解决方案:
统一错误页面,删除敏感信息
11、JQuery版本过低引起的XSS漏洞——CVE-2020-11022/CVE-2020-11023
漏洞复现:
1、扫描网站所使用到的所有js
这里使用Retire.js插件,具体安装如下:
(1)火狐浏览器设置-扩展和主题-拓展
(2)在搜索栏搜索Retire.js
(3)安装插件(这里我已经安装过了)
(4)如果右上方菜单栏中没有显示插件,要在扩展里面找到安装好的插件,点击进去,将 在隐私窗口中运行 点击允许
ps:可能因为火狐浏览器开的是隐私还是其他原因,一开始插件没有在菜单栏中显示出来 坑- -
(5)成功效果
2、以CSDN为例将漏洞复现
(1)通过插件找出网站所用到的js,将jquery 1.12.4 Found in https://g.csdnimg.cn/??lib/jquery/1.12.4/jquery.min.js,user-tooltip/2.7/user-tooltip.js,lib/qrcode/1.0.0/qrcode.min.js复制下来
(2)图中 https://g.csdnimg.cn/??lib/jquery/1.12.4/jquery.min.js,user-tooltip/2.7/user-tooltip.js,lib/qrcode/1.0.0/qrcode.min.js 就是我们在上一步中复制的jquery引用路径。
将图中代码保存为html文件到本地,这里命名为 jQuery-xss-poc.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery XSS Examples (CVE-2020-11022/CVE-2020-11023)</title>
<script src="https://g.csdnimg.cn/??lib/jquery/1.12.4/jquery.min.js,user-tooltip/2.7/user-tooltip.js,lib/qrcode/1.0.0/qrcode.min.js"></script>
</head>
<body>
<script>
function test(n,jq){
sanitizedHTML = document.getElementById('poc'+n).innerHTML;
if(jq){
$('#div').html(sanitizedHTML);
}else{
div.innerHTML=sanitizedHTML;
}
}
</script>
<h1>jQuery XSS Examples (CVE-2020-11022/CVE-2020-11023)</h1>
<p>PoCs of XSS bugs fixed in <a href="//blog.jquery.com/2020/04/10/jquery-3-5-0-released/">jQuery 3.5.0</a>. You can find the details in my blog post: <a href="//mksben.l0.cm/2020/05/jquery3.5.0-xss.html">English</a> / <a href="//masatokinugawa.l0.cm/2020/05/jquery3.5.0-xss.html">日本語</a></p>
<h2>PoC 1</h2>
<button onclick="test(1)">Assign to innerHTML</button> <button onclick="test(1,true)">Append via .html()</button>
<xmp id="poc1">
<style><style /><img src=x οnerrοr=alert(2)>
</xmp>
<h2>PoC 2 (Only jQuery 3.x affected)</h2>
<button οnclick="test(2)">Assign to innerHTML</button> <button οnclick="test(2,true)">Append via .html()</button>
<xmp id="poc2">
<img alt="<x" title="/><img src=x οnerrοr=alert("1st")>">
</xmp>
<h2>PoC 3</h2>
<button οnclick="test(3)">Assign to innerHTML</button> <button οnclick="test(3,true)">Append via .html()</button>
<xmp id="poc3">
<option><style></option></select><img src=x οnerrοr=alert("1st")></style>
</xmp>
<div id="div"></div>
</body>
</html>
(3)右键该文件,用浏览器打开
至此,CVE-2020-11022/CVE-2020-11023漏洞就被我们复现出来了
解决方案:
网上是提出两种方案
(1)更新 jQuery 到 3.5.0 或更高版本:
https://code.jquery.com/jquery-3.5.0.js
(2)使用XSS清理工具清理用户输入的HTML,官方推荐:
https://github.com/cure53/DOMPurify
如果升级jquery版本毫无压力的话,建议还是升级版本吧,比方案二简单。
方案二对简单系统来说,只要引入相应js,按照demo将原来的html重新初始化一下就可以了,但是对于页面多且不统一的系统来说 工作量太大了!
附上官方demo
<!doctype html>
<html>
<head>
<script src="../dist/purify.js"></script>
</head>
<body>
<!-- Our DIV to receive content -->
<div id="sanitized"></div>
<!-- Now let's sanitize that content -->
<script>
/* jshint globalstrict:true */
/* global DOMPurify */
'use strict';
// Specify dirty HTML
var dirty = '<p>HELLO<iframe/\/src=JavScript:alert(1)></ifrAMe><br>goodbye</p>';
// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty);
document.getElementById('sanitized').innerHTML = clean;
</script>
</body>
</html>
ps:= =公司项目升级版本会有问题。之前为了不升级版本,领导命令将jquery版本去掉,现在直接针对jquery进行代码审查,漏洞自然逃不过
最后采用方案二,只针对登录页面
导入js(官方demo中有提供)
<script src="../dist/purify.js"></script>
在提交操作前 将登录框的html进行数据清洗,再塞回div中
var dirty = $("#sanitized").html();
//清洗数据
var clean = DOMPurify.sanitize(dirty);
$('#sanitized').html(clean);
也不懂有没有效果(项目中的登录信息是加密的),反正咱就是做了