什么是XSS攻击?
XSS攻击使用Javascript脚本注入进行攻击
XSS攻击常出现在提交表单中,如博客的评论区等,用户可以通过提交评论:,那么只要访问该页面的用户都会弹窗,当然,这可能是为了娱乐娱乐,不要小看XSS攻击,有些人利用XSS攻击窃取用户名密码,调用黑客的工程,将用户名和密码发送过去,也可以伪装成钓鱼网站。
例如在表单中注入: 那么页面会跳转到xxx.com
还可以根据js获取本地浏览器的cookie信息,根据cookie信息完全可以模拟用户。
那么该如何防止XSS攻击呢?
实现思路:
使用转义解决。将<转义为< >转义为>
①使用过滤器,拦截所有请求,重写request
②重写获取值的方法,将特殊代码转换成html
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import com.jeecms.core.web.util.URLHelper;
public class XssFilter implements Filter {
/**
* 排除链接
*/
public List<String> excludes = new ArrayList<String>();
private String filterChar;
private String replaceChar;
private String splitChar;
private String excludeUrls;
FilterConfig filterConfig = null;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterChar=filterConfig.getInitParameter("FilterChar");
this.replaceChar=filterConfig.getInitParameter("ReplaceChar");
this.splitChar=filterConfig.getInitParameter("SplitChar");
this.excludeUrls=filterConfig.getInitParameter("excludeUrls");
this.filterConfig = filterConfig;
}
@Override
public void destroy() {
this.filterConfig = null;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (handleExcludeURL(req, resp))
{
chain.doFilter(request, response);
return;
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request,filterChar,replaceChar,splitChar);
chain.doFilter(xssRequest, response);
}
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
{
if (excludes == null || excludes.isEmpty())
{
return false;
}
String url = request.getServletPath();
for (String pattern : excludes)
{
Pattern p = Pattern.compile("^" + pattern);
Matcher m = p.matcher(url);
if (m.find())
{
return true;
}
}
return false;
}
private boolean isExcludeUrl(ServletRequest request){
boolean exclude=false;
if(StringUtils.isNotBlank(excludeUrls)){
String[]excludeUrl=excludeUrls.split(splitChar);
if(excludeUrl!=null&&excludeUrl.length>0){
for(String url:excludeUrl){
if(URLHelper.getURI((HttpServletRequest)request).startsWith(url)){
exclude=true;
}
}
}
}
return exclude;
}
}
import static com.jeecms.common.web.Constants.UTF8;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* @author Tom
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
private String[]filterChars;
private String[]replaceChars;
public XssHttpServletRequestWrapper(HttpServletRequest request,String filterChar,String replaceChar,String splitChar) {
super(request);
if(filterChar!=null&&filterChar.length()>0){
filterChars=filterChar.split(splitChar);
}
if(replaceChar!=null&&replaceChar.length()>0){
replaceChars=replaceChar.split(splitChar);
}
}
@Override
public String getQueryString() {
String value = super.getQueryString();
if (value != null) {
value = xssEncode(value);
}
return value;
}
/**
* 覆盖getParameter方法,将参数名和参数值都做xss过滤。<br/>
* 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/>
* getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
*/
@Override
public String getParameter(String name) {
String value = super.getParameter(xssEncode(name));
if (value != null) {
value = xssEncode(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[]parameters=super.getParameterValues(name);
if (parameters==null||parameters.length == 0) {
return null;
}
for (int i = 0; i < parameters.length; i++) {
parameters[i] = xssEncode(parameters[i]);
}
return parameters;
}
/**
* 覆盖getHeader方法,将参数名和参数值都做xss过滤。<br/>
* 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/> getHeaderNames 也可能需要覆盖
*/
@Override
public String getHeader(String name) {
String value = super.getHeader(xssEncode(name));
if (value != null) {
value = xssEncode(value);
}
return value;
}
/**
* 将容易引起xss漏洞的半角字符直接替换成全角字符
* 请求的参数过滤一些关键字
* @return
*/
private String xssEncode(String s) {
if (s != null) {
// 避免 null 字符
s = s.replaceAll("", "");
s = s.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
s = s.replaceAll("<", "& lt;").replaceAll(">", "& gt;");// 全角大于号 全角小于号
s = s.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");// \\( \\)
s = s.replaceAll("'", "& #39;");
s = s.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
s = s.replaceAll("alert", "");
s = s.replaceAll("script", "");
s = s.replaceAll("#", "#");
s = s.replaceAll("%", "%");
}
if (s == null || s.equals("")) {
return s;
}
try {
s = URLDecoder.decode(s, UTF8);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 0; i < filterChars.length; i++) {
if(s.contains(filterChars[i])){
s=s.replace(filterChars[i], replaceChars[i]);
}
}
return s;
}
}
web.xml配置过滤器
<!-- 防止XSS攻击 -->
<filter>
<filter-name>FilterXSS</filter-name>
<filter-class>cn.itcats.FilterXSS</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterXSS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>