XSS攻击全称跨站脚本攻击(Cross-site scripting),为和CSS区别,改为XSS。XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意的web用户将代码植入到提供给其它用户使用的页面中。比如这些代码包括HTML代码和客户端脚本。
XSS攻击的产生原因是对外部输入的参数没有做严格过滤,导致输入参数直接参与页面源代码,相当于页面源代码可以被外部修改,因此可能被改变页面结构、植入恶意脚本,可被用于钓鱼、盗取数据、篡改页面等。解决的方法是加强页面输出过滤或转义,如ESAPI的Encoder转义、自定义转义,或者采用不存在XSS风险的页面标签进行输出。
攻击分类
反射型XSS攻击
又称为非持久性跨站点脚本攻击。漏洞产生的原因是攻击者注入的数据反映在响应中。一个典型的非持久性XSS包含一个带XSS攻击向量的链接(即每次攻击需要用户的点击)。
例子
http://www.test.com/message.php?send=Hello,World
接收者将会接收信息显示Hello,World
http://www.test.com/message.php?send=<script>alert(‘foolish!’)</script>
接收者接收消息显示的时候将会弹出警告窗口显示foolish!
存储型XSS攻击
又称为持久型跨站点脚本,它一般发生在XSS攻击向量(一般指XSS攻击代码)存储在网站数据库,当一个页面被用户打开的时候执行。每当用户打开浏览器,脚本执行。持久的XSS相比非持久性XSS攻击危害性更大,因为每当用户打开页面,查看内容时脚本将自动执行。
例子
一个正常的表单,正常操作是用户提交相应留言信息;将数据存储到数据库;其他用户访问,应用查询数据并显示。
<input type=“text” name=“content” value=“这里是用户填写的数据”>
攻击者在value填写
<script>alert(‘foolish!’)</script>
或者其他攻击代码。将代码存储到数据库中;其他用户取出数据显示的时候,将会执行这些攻击性代码。
攻击入口
可以通过HTML节点、HTML属性、JavaScript代码、富文本等只要有用户输入信息的地方都可能是被攻击的注入点。
防范方法
需要将一些特殊字符进行转义处理。
-
通过前端对用户输入内容进行处理:
var escapeHtml = function(str) { str = str.replace(/</g,\'<\'); str = str.replace(/</g,\'>\'); return str; }
-
通过后台对用户输入内容进行处理:
private String cleanXSS(String value) { //You\'ll need to remove the spaces from the html entities below value = value.replaceAll("<", "<").replaceAll(">", ">"); value = value.replaceAll("\\\\(", "(").replaceAll("\\\\)", ")"); value = value.replaceAll("\'", "'"); value = value.replaceAll("eval\\\\((.*)\\\\)", ""); value = value.replaceAll("[\\\\\\"\\\\\\\'][\\\\s]*javascript:(.*)[\\\\\\"\\\\\\\']", "\\"\\""); value = value.replaceAll("script", ""); return value; }
-
后台使用第三方方法处理:添加commons-lang-2.5.jar 包,然后使用方法或者使用Spring框架中的HtmlUtils方法:
StringEscapeUtils.escapeHtml(string); StringEscapeUtils.escapeJavaScript(string); StringEscapeUtils.escapeSql(string);
在父Controller里面进行处理:
@InitBinder
protected void initBinder(WebDataBinder binder) {
// String类型转换,将所有传递进来的String进行HTML编码,防止XSS攻击
binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
@Override
public void setAsText(String text) {
setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
}
@Override
public String getAsText() {
Object value = getValue();
return value != null ? value.toString() : "";
}
});
}