java 防止 XSS 攻击的常用方法总结.

java web应用程序防止 csrf 攻击的方法,参考这里 java网页程序采用 spring 防止 csrf 攻击. ,但这只是攻击的一种方式,还有其他方式,比如今天要记录的 XSS 攻击, XSS 攻击的专业解释,可以在网上搜索一下,参考百度百科的解释 http://baike.baidu.com/view/2161269.htm, 但在实际的应用中如何去防止这种攻击呢,下面给出几种办法.
1. 自己写 filter 拦截来实现,但要注意的时,在WEB.XML 中配置 filter 的时候,请将这个 filter 放在第一位.
2. 采用开源的实现 ESAPI library ,参考网址:https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API

3. 可以采用spring 里面提供的工具类来实现.

一, 第一种方法。
配置过滤器

publicclassXSSFilterimplementsFilter{
    @Override
    publicvoid init(FilterConfig filterConfig)throwsServletException{
    }
    @Override
    publicvoid destroy(){
    }
    @Override
    publicvoid doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
        throwsIOException,ServletException{
        chain.doFilter(newXSSRequestWrapper((HttpServletRequest) request), response);
    }}



再实现 ServletRequest 的包装类

import java.util.regex.Pattern;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;publicclassXSSRequestWrapperextendsHttpServletRequestWrapper{
    publicXSSRequestWrapper(HttpServletRequest servletRequest){
        super(servletRequest);
    }
    @Override
    publicString[] getParameterValues(String parameter){
        String[] values =super.getParameterValues(parameter);
        if(values ==null){
            returnnull;
        }
        int count = values.length;
        String[] encodedValues =newString[count];
        for(int i =0; i < count; i++){
            encodedValues[i]= stripXSS(values[i]);
        }
        return encodedValues;
    }
    @Override
    publicString getParameter(String parameter){
        String value =super.getParameter(parameter);
        return stripXSS(value);
    }
    @Override
    publicString getHeader(String name){
        String value =super.getHeader(name);
        return stripXSS(value);
    }
    privateString stripXSS(String value){
        if(value !=null){
            // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
            // avoid encoded attacks.
            // value = ESAPI.encoder().canonicalize(value);
            // Avoid null characters
            value = value.replaceAll("","");
            // Avoid anything between script tags
            Pattern scriptPattern =Pattern.compile("(.*?)",Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid anything in a src="http://www.yihaomen.com/article/java/..." type of e­xpression
            scriptPattern =Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            scriptPattern =Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome  tag
            scriptPattern =Pattern.compile("",Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome  tag
            scriptPattern =Pattern.compile("",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid eval(...) e­xpressions
            scriptPattern =Pattern.compile("eval\\((.*?)\\)",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid e­xpression(...) e­xpressions
            scriptPattern =Pattern.compile("e­xpression\\((.*?)\\)",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid javascript:... e­xpressions
            scriptPattern =Pattern.compile("javascript:",Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid vbscript:... e­xpressions
            scriptPattern =Pattern.compile("vbscript:",Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid onload= e­xpressions
            scriptPattern =Pattern.compile("onload(.*?)=",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
        }
        return value;
    }}



例子中注释的部分,就是采用 ESAPI library 来防止XSS攻击的,推荐使用.

当然,我还看到这样一种办法,将所有的编程全角字符的解决方式,但个人觉得并没有上面这种用正则表达式替换的好

privatestaticString xssEncode(String s){
        if(s ==null|| s.equals("")){
            return s;
        }
        StringBuilder sb =newStringBuilder(s.length()+16);
        for(int i =0; i < s.length(); i++){
            char c = s.charAt(i);
            switch(c){
            case'>':
                sb.append('>');// 全角大于号
                break;
            case'<':
                sb.append('<');// 全角小于号
                break;
            case'\'':
                sb.append('\\');
                sb.append('\'');
                sb.append('\\');
                sb.append('\'');
                break;
            case'\"':
                sb.append('\\');
                sb.append('\"');// 全角双引号
                break;
            case'&':
                sb.append('&');// 全角
                break;
            case'\\':
                sb.append('\');// 全角斜线
                break;
            case'#':
                sb.append('#');// 全角井号
                break;
            case':':
                sb.append(':');// 全角冒号
                break;
            case'%':
                sb.append("\\\\%");
                break;
            default:
                sb.append(c);
                break;
            }
        }
        return sb.toString();
    }



当然,还有如下更简单的方式:

privateString cleanXSS(String value){
                //You'll need to remove the spaces from the html entities below
        value = value.replaceAll("<","& lt;").replaceAll(">","& gt;");
        value = value.replaceAll("\\(","& #40;").replaceAll("\\)","& #41;");
        value = value.replaceAll("'","& #39;");
        value = value.replaceAll("eval\\((.*)\\)","");
        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']","\"\"");
        value = value.replaceAll("script","");
        return value;
    }



在后台或者用spring 如何实现呢:
首先添加一个jar包:commons-lang-2.5.jar ,然后在后台调用这些函数:

StringEscapeUtils.escapeHtml(string);StringEscapeUtils.escapeJavaScript(string);StringEscapeUtils.escapeSql(string);



当然,我记得在spring 里面好像有一个 HtmlUtils.htmlEscape , 同样可以做到 过滤 XSS 攻击。从上面的介绍可以看出,防止 XSS 攻击并不难,就是要小心。

===============================================================

在apache commons-lang(2.3以上版本)中为我们提供了一个方便做转义的工具类,主要是为了防止sql注入,xss注入攻击的功能。总共提供了以下几个方法:

1.escapeSql 提供sql转移功能,防止sql注入攻击,例如典型的万能密码攻击' ' or 1=1 ' '

StringBuffer sql = new StringBuffer("select key_sn,remark,create_date from tb_selogon_key where 1=1 ");  

        if(!CommUtil.isEmpty(keyWord)){  

            sql.append(" and like '%" + StringEscapeUtils.escapeSql(keyWord) + "%'");  

        }  
StringBuffer sql = new StringBuffer("select key_sn,remark,create_date from tb_selogon_key where 1=1 ");
		if(!CommUtil.isEmpty(keyWord)){
			sql.append(" and like '%" + StringEscapeUtils.escapeSql(keyWord) + "%'");
		}

2.escapeHtml /unescapeHtml  转义/反转义html脚本

System.out.println(StringEscapeUtils.escapeHtml("<a>dddd</a>"));     

输出结果为:&lt;a&gt;dddd&lt;/a&gt;  
System.out.println(StringEscapeUtils.escapeHtml("<a>dddd</a>"));   
输出结果为:&lt;a&gt;dddd&lt;/a&gt;
System.out.println(StringEscapeUtils.unescapeHtml("&lt;a&gt;dddd&lt;/a&gt;"));     

输出为:<a>ddd</a>  
System.out.println(StringEscapeUtils.unescapeHtml("&lt;a&gt;dddd&lt;/a&gt;"));   
输出为:<a>ddd</a>

3.escapeJavascript/unescapeJavascript 转义/反转义js脚本

System.out.println(StringEscapeUtils.escapeJavaScript("<script>alert('1111')</script>"));     

输出为:&lt;script&gt;alert('111')&lt;/script&gt;  
System.out.println(StringEscapeUtils.escapeJavaScript("<script>alert('1111')</script>"));   
输出为:&lt;script&gt;alert('111')&lt;/script&gt;

4.escapeJava/unescapeJava 把字符串转为unicode编码

System.out.println(StringEscapeUtils.escapeJava("中国"));     

输出为:用escapeJava方法转义之后的字符串为:/u4E2D/u56FD/u5171/u4EA7/u515A  

==============================================

  apache工具包common-lang中有一个很有用的处理字符串的工具类,其中之一就是StringEscapeUtils,这个工具类是在2.3版本以上加上的去的,利用它能很方便的进行html,xml,java等的转义与反转义,而且还能对关键字符串进行处理预防SQL注入,不过好像common-lang3.0以后我看着好像没这个处理SQL语句的方法了,想用的话前提时引入对应的jar包,以下为它的部分方法:java 防止 XSS 攻击的常用方法总结.

它的方法,全是静态,直接用类调用即可,下边来根据代码看看它们几个的用法和效果,一看一目了然:

package stringescapeutils;  
  
import org.apache.commons.lang.StringEscapeUtils;  
  
public class StringEscapeUtilsTest {  
  
    public static void main(String args[]){  
          
        String sql="1' or '1'='1";  
        System.out.println("防SQL注入:"+StringEscapeUtils.escapeSql(sql)); //防SQL注入  
          
        System.out.println("转义HTML,注意汉字:"+StringEscapeUtils.escapeHtml("<font>chen磊  xing</font>"));    //转义HTML,注意汉字  
        System.out.println("反转义HTML:"+StringEscapeUtils.unescapeHtml("<font>chen磊  xing</font>"));  //反转义HTML  
          
        System.out.println("转成Unicode编码:"+StringEscapeUtils.escapeJava("陈磊兴"));     //转义成Unicode编码  
          
        System.out.println("转义XML:"+StringEscapeUtils.escapeXml("<name>陈磊兴</name>"));   //转义xml  
        System.out.println("反转义XML:"+StringEscapeUtils.unescapeXml("<name>陈磊兴</name>"));    //转义xml  
          
    }  
}  

输入结果:

防SQL注入:1'' or ''1''=''1  
转义HTML,注意汉字:<font>chen磊  xing</font>  
反转义HTML:<font>chen磊  xing</font>  
转成Unicode编码:\u9648\u78CA\u5174  
转义XML:<name>陈磊兴</name>  
反转义XML:<name>陈磊兴</name>  

http://blog.csdn.net/chenleixing/article/details/43456987

http://www.cnblogs.com/thinkpad/p/4837841.html

http://blog.csdn.net/joeyon1985/article/details/43527987

相关推荐