1. XSS漏洞
XSS(Cross Site Scripting,为了和层叠样式表(Cascading Style Sheet,CSS)有所区分,故称XSS)跨站脚本攻击是一种针对网站应用程序的安全漏洞攻击技术。它可以实现用户会话劫持、钓鱼攻击、恶意重定向、点击劫持、挂马、XSS蠕虫等。
XSS攻击类型可以分为:反射型、存储型、DOM型。
1.1 反射型XSS攻击
访问
http://localhost:8080/tomcat_demo_war_exploded/xssdemo?name=%3Cscript%3Ealert(1)%3C/script%3E
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>反射型XSS攻击-Demo</title>
</head>
<body>
<%=request.getParameter("name")%>
</body>
</html>
1.2 存储型XSS攻击
在留言框中输入XSS语句并提交。
刷新页面,出现弹框
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.*" %>
<%
String username = request.getParameter("username");
String content = request.getParameter("content");
String message = "GUEST_MESSAGE";
List<Map<String, String>> comments = new ArrayList<Map<String, String>>();
if (content != null && username != null) {
Object object = application.getAttribute(message);
if (object != null) {
comments = (List<Map<String, String>>) object;
}
Map<String, String> comment = new HashMap<String, String>();
comment.put("username", username);
comment.put("content", content);
comments.add(comment);
application.setAttribute(message, comments);
}
%>
<html>
<head>
<title>存储型XSS攻击-Demo</title>
</head>
<style>
* {
margin: 0;
padding: 0;
}
</style>
<body>
<div style="border: 1px solid rgba(198,198,198,0.93);">
<div style="text-align: center; height: 40px;">
<h1>在线留言板</h1>
</div>
<div>
<dl>
<%
Object object = application.getAttribute(message);
if (object instanceof List) {
comments = (List<Map<String, String>>) object;
for (Map<String, String> comment : comments) {
%>
<dd>
<div style="min-height: 50px; margin: 20px; border-bottom: 1px solid #9F9F9F;">
<p><B><%=comment.get("username")%>
</B>留言:</p>
<p style="margin: 20px 0 5px 0; font-size: 15px;">
<pre><%=comment.get("content")%></pre>
</p>
</div>
</dd>
<%
}
}
%>
</dl>
</div>
<div style="background-color: rgba(255,255,255,0.95); border: 1px solid rgba(198,198,198,0.93);">
<form action="#" method="POST" style="margin: 30px;">
昵称: <input type="text" name="username" style="width:300px; height: 28px;"/><br/><br/>
<textarea name="content" style="overflow: auto;width: 100%; height: 300px;"></textarea>
<input type="submit" value="提交留言" style="margin-top: 25px; width: 80px; height: 30px;"/>
</form>
</div>
</div>
</body>
</html>
1.3 Dom型XSS
请求访问
http://localhost:8080/tomcat_demo_war_exploded/dom.jsp?content=%22%3E%3Cscript%3Ealert(1)%3C/script%3E
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Dom型XSS攻击-Demo</title>
</head>
<body>
<%--http://localhost:8080/tomcat_demo_war_exploded/dom.jsp?content=%22%3E%3Cscript%3Ealert(1)%3C/script%3E--%>
Content: <span style="color: red;" ></span>
<input id="domXSS" type="hidden" value="<%=request.getParameter("content")%>" />
<script>
var date = document.getElementById("domXSS").value;
document.getElementsByTagName("span")[0].innerHTML = date;
</script>
</body>
</html>
2. XSS的防御
XSS漏洞攻击最常见的防御措施是特殊字符转义。
2.1 ESAPI
ESAPI是owasp提供的一套API级别的web应用解决方案。能够校验XSS、SQL、恶意文件后缀名等。
import org.owasp.esapi.ESAPI;
String content = request.getParameter("content");
content = ESAPI.encoder().encodeForHTML(content);
content = ESAPI.encoder().encoderForJavaScript(content); //防御dom xss使用jsencode
2.2 自定义特殊字符转义
对特殊字符进行替换转义。
import org.apache.commons.lang.StringUtils;
private String htmlEncode(String content) {
content = StringUtils.replace(content, "&", "&");
content = StringUtils.replace(content, "<", "<");
content = StringUtils.replace(content, ">", ">");
content = StringUtils.replace(content, "\"", """);
content = StringUtils.replace(content, "'", "'");
content = StringUtils.replace(content, "/", "/");
return content;
}
3.3 XSSFilter
全局过滤
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
public class XSSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
// 创建HttpServletRequestWrapper,包装原HttpServletRequest对象,示例程序只重写了getParameter方法,
// 应当考虑如何过滤:getParameter、getParameterValues、getParameterMap、getInputStream、getReader
HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) {
public String getParameter(String name) {
// 获取参数值
String value = super.getParameter(name);
// 简单转义参数值中的特殊字符
return value.replace("&", "&").replace("<", "<").replace("'", "'");
}
};
chain.doFilter(requestWrapper, resp);
}
@Override
public void destroy() {
}
}
web.xml配置添加XSSFilter过滤器
<!-- XSS过滤器 -->
<filter>
<filter-name>XSSFilter</filter-name>
<filter-class>XSSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XSSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>