安全漏洞扫描之Sql注入解析

来源:互联网 发布:js调用手机相册插件 编辑:程序博客网 时间:2024/04/30 22:17

对于Web系统,要防范Sql注入|XSS(跨站脚本攻击)等其他攻击,一般处理方法是针对攻击的关键子进行过滤。这里针对Sql注入和XSS攻击防范方法提供使用的说明。

一、Sql注入防范

1、过滤Sql关键字

大家都知道Web服务器核心实现就是Servlet技术,servlet的过滤器可以对请求Header,请求内容等进行过滤和修改。Sql注入就是利用过滤器功能对请求参数的关键字进行过滤处理,从而降低Sql注入的成功率。

  1. 创建过滤器实现Filter接口,web.xml配置过滤器信息
    public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper{

@Override

publicvoid doFilter(ServletRequest request, ServletResponse response,FilterChainchain) throws IOException, ServletException {

 

HttpServletRequesthttpRequest = (HttpServletRequest) request; 

                       HttpServletResponse httpResponse = (HttpServletResponse) response;

       

                      XssHttpServletRequestWrapperxssReq = new XssHttpServletRequestWrapper(httpRequest);

                chain.doFilter(xssReq, response);

      

}

 

}

 

  1. 创建一个包装器类,继承HttpServletRequestWrapper类
    下面是这个类具体实现,这里运用了装饰模式,建议大家先了解下该模式具体内容,可以参考:《JAVA与模式》之装饰模式

这里最重要的是stripXSS()方法,利用正则表达式过滤特殊关键字,其他的方法都是套路,按照它的要求实现即可。如果对正则表达式不是很了解,可以参考:正则表达式30分钟入门教程。
 

publicclass XssHttpServletRequestWrapper extends HttpServletRequestWrapper{

 

 private Map params;

 

HttpServletRequestorgReq = null;

publicXssHttpServletRequestWrapper(HttpServletRequest request) {

super(request);

this.orgReq= request;

this.params= request.getParameterMap();

 

}

 @Override

  public Map getParameterMap() {

          return params ;

  }

 @Override

  public Enumeration getParameterNames() {

          Vector l = new Vector(params.keySet());

          return l.elements();

  }

 @Override

 public String[] getParameterValues(Stringname) {

         Object v = params.get(name);

        

          if (v == null ) {

                    return null ;

         } else if (v instanceof String[]) {

                   String[] value = (String[])v;

                    for (int i = 0; i <value.length; i++) {

                            value[i] =stripXSS(value[i]);

                   }

                    return (String[]) value;

         } else if (v instanceof String) {

                   String value = (String) v;

                   value = stripXSS(value);

                    return new String[] {(String) value };

         } else {

                    return new String[] {v.toString() };

         }

}

 

 

  @Override

  public String getParameter(String name) {

          Object v = params.get(name);

           if (v == null ) {

                     return null ;

          } else if (v instanceof String[]) {

                    String[] strArr =(String[]) v;

                     if (strArr.length > 0){

                             String value =strArr[0];

                            // value =stripXSS(value);

                              returnstripXSS(value);

                    } else {

                              return null ;

                    }

          } else if (v instanceof String) {

                    String value = (String) v;

                  //  value = stripXSS(value);

                     return stripXSS(value);

          } else {

                     return v.toString();

          }

 }

 

// 使用正则替换关键字

privateString stripXSS(String value) {

        if (value != null) {

            // NOTE: It's highly recommended touse 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 scripttags

            Pattern scriptPattern =Pattern.compile("<script>(.*?)</script>",Pattern.CASE_INSENSITIVE);

            value =scriptPattern.matcher(value).replaceAll("");

            // Avoid anything in asrc="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("(?:')|(?:--)(/\\*(?:.[\\n\\r])*?\\*/)'",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</script> tag

            scriptPattern =Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);

            value =scriptPattern.matcher(value).replaceAll("");

            // Remove any lonesome <script...> tag

            scriptPattern =Pattern.compile("<script(.*?)>", 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("");

            // (select .* from)

            //scriptPattern =Pattern.compile("(^(?!.*?select?.).*select|udpate|delete.*|(\n|\r)from)", Pattern.CASE_INSENSITIVE);

            scriptPattern =Pattern.compile("(insert|select|udpate|delete|\\s+or|\\s+and|\\s+drop)\\s+",Pattern.CASE_INSENSITIVE);

            value =scriptPattern.matcher(value).replaceAll("");

            // insert into

            scriptPattern =Pattern.compile("(insert.*into)", Pattern.CASE_INSENSITIVE);

            value =scriptPattern.matcher(value).replaceAll("");

            scriptPattern =Pattern.compile("(\b(and|trancate|ascii|declare|exec|count|master|drop|execute)\b)",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

            value =scriptPattern.matcher(value).replaceAll("");

        }

        return value;

    }

 

}
 

2、程序中使用PreparedStatement替代sql拼接
      一般公司对编码规范没有明确规定,很多人为了图方便,在编写sql时直接采用字符串拼接方式,这样倒是省事,但无疑留下了一个巨坑,容易导致sql注入攻击。

很多规范要求采用PreparedStatement对象的方法,对传入的参数采用占位符方式来避免sql注入攻击。

PreparedStatement有预编译的过程,已经绑定sql,之后无论执行多少遍,都不会再去进行编译,所以性能比Statement要好,而且可以有效的防止 SQL注入等问题



0 0
原创粉丝点击