天天看點

WEB程式防SQL注入攻擊程式

場景: WEB程式容易被SQL注入攻擊,攻擊原理是在請求參數中傳入非法字元,造成SQL語句出現出現異常情況,已達到攻擊者想要的結果。

分析: 一般的攻擊者都是在傳入的請求參數上做文章,是以我們重點檢查的是request的參數,判斷request請求參數是否有非法字元,及資料庫關鍵字,如果有即判定為SQL注入,否則通過。一般在WEB應用中都采用FILTER技術來處理此類問題,以下類适用于ORACLE,其他資料庫請修改SqlInjectFilter類中的static{ }内的關鍵字。

新增功能: 驗證POST攻擊,精簡驗證清單,優化驗證架構

解決:

1. 配置FILTER,配置位置為 /WEB-INF/web.xml

 <filter>

       <filter-name>SqlInjectFilter</filter-name>

      <filter-class>SqlInjectFilter</filter-class>

      <init-param>

          <param-name>enabled</param-name>

           <param-value>true</param-value>

       </init-param>

       <init-param>

          <param-name>failthPath</param-name>

           <param-value>/failth.jsp</param-value>

       </init-param>

    </filter>

    <filter-mapping>

       <filter-name>SqlInjectFilter</filter-name>

       <url-pattern>*.jsp</url-pattern>

    </filter-mapping>

    <filter-mapping>

       <filter-name>SqlInjectFilter</filter-name>

       <url-pattern>*.do</url-pattern>

    </filter-mapping>

說明:

    1. <filter-class>SqlInjectFilter</filter-class> 為類全路徑,可以根據具體情況修改

    2.  這裡判定是否啟用,預設是啟用,否則将  <param-value>true</param-value> 修改為  <param-value>false</param-value>

      <init-param>

          <param-name>enabled</param-name>

           <param-value>true</param-value>

       </init-param>

    3. 這是判定SQL注入後跳轉的頁面,根據實際情況修改 <param-value>/failth.jsp</param-value> 中的 /failth.jsp

       <init-param>

          <param-name>failthPath</param-name>

           <param-value>/failth.jsp</param-value>

       </init-param>

2. 建立FILTER類: SqlInjectFilter ; 2. 配置FILTER

import java.io.ByteArrayInputStream;

import java.io.File;

import java.io.IOException;

import java.util.Vector;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletInputStream;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

public class SqlInjectFilter implements Filter {

 protected Log log = LogFactory.getLog(getClass());

 protected static Vector list = new Vector();

 protected String enabled = "true";

 protected String failthPath = "/TaxWeb/failth.jsp";

 public void destroy() {

  // TODO Auto-generated method stub

 }

 public void doFilter(ServletRequest arg0, ServletResponse arg1,

   FilterChain arg2) throws IOException, ServletException {

  // TODO Auto-generated method stub

  HttpServletRequest httpServletRequest = (HttpServletRequest) arg0;

  HttpServletResponse httpServletResponse = (HttpServletResponse) arg1;

  //擷取GET方法請求參數串

  String queryString = httpServletRequest.getQueryString();

        //是否啟動,web.xml中配置的初始化參數

  if (enabled.equalsIgnoreCase("true")) {

   //開始XSS(METHOD:GET)和sql注入檢測

   boolean isXssFind = false;

   if(queryString!=null && !queryString.equalsIgnoreCase("null")){

    String src = java.net.URLDecoder.decode(queryString,"GB2312");

    src  += "_"+queryString;

    if(src!=null && !src.equalsIgnoreCase("null")){

     String keyword = "";

     for (int i = 0; i < list.size(); i++) {

       keyword = list.get(i).toString();

       if(src.indexOf(keyword)!=-1){

        isXssFind = true;

        break;

       }

     }

     if(isXssFind){

      log.error("發現疑為跨站腳本攻擊,檢測判斷請求位址包含非法字元:"+java.net.URLEncoder.encode(keyword,"GB2312"));

      httpServletRequest.setAttribute("errorMsg", "發現疑為跨站腳本攻擊,檢測判斷請求位址包含非法字元:"+java.net.URLEncoder.encode(keyword,"GB2312"));

      httpServletRequest.getSession(true).setAttribute("injectKey","發現疑為跨站腳本攻擊,檢測判斷請求位址包含非法字元:"+java.net.URLEncoder.encode(keyword,"GB2312"));

      httpServletRequest.getSession().invalidate();

      httpServletResponse.sendRedirect(failthPath);

       throw new java.lang.IllegalAccessError();

     }

    }

   }

   //開始XSS(METHOD:POST)和sql注入檢測

   if(!isXssFind){

    arg2.doFilter(new RequestWrapperXSS(httpServletRequest,httpServletResponse,list,failthPath), arg1);

   }

  }else{

   arg2.doFilter(arg0, arg1);

  }

 }

 public void init(FilterConfig arg0) throws ServletException {

  // TODO Auto-generated method stub

  enabled = arg0.getInitParameter("enabled");

  failthPath = arg0.getInitParameter("failthPath");

  if (enabled == null || "".equals(enabled)) {

   enabled = "true";

  }

  if (failthPath == null || "".equals(failthPath)) {

   enabled = "/TaxWeb/failth.jsp";

  }

  log.info("SQL注入檢測初始化完成");

 }

 static {

  list.add("'");

  list.add("(");

  //list.add("or");

  //list.add("and");

  list.add("[");

  list.add("<");

  list.add(".."+File.separator);

  // 請求參數不能能有腳步

  list.add("script");

  list.add("+");

  //list.add("-");

  list.add("*");

  list.add("%");

 }

}

class RequestWrapperXSS extends HttpServletRequestWrapper {

 protected Log log = LogFactory.getLog(getClass());

 private HttpServletRequest request;

 private HttpServletResponse serlvetResponse;

 private boolean isXssFind=false;

 private Vector keywords;

 private String failForwardPath;

 public RequestWrapperXSS(HttpServletRequest servletRequest) {

  super(servletRequest);

  this.request = servletRequest;

 }

 public RequestWrapperXSS(HttpServletRequest servletRequest,HttpServletResponse serlvetResponse) {

  super(servletRequest);

  this.request = servletRequest;

  this.serlvetResponse = serlvetResponse;

 }

 public RequestWrapperXSS(HttpServletRequest servletRequest,HttpServletResponse serlvetResponse,Vector keywords,String failForwardPath) {

  super(servletRequest);

  this.request = servletRequest;

  this.serlvetResponse = serlvetResponse;

  this.keywords = keywords;

  this.failForwardPath = failForwardPath;

 }

 public String[] getParameterValues(String name){

  String[] values = super.getParameterValues(name);

  //log.debug("parameter name: "+name+" value:"+values.toString());

  try {

   xssCheck(values,keywords);

  } catch (IllegalAccessError e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

   throw e;

  } catch (IOException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  }

  return values;

 }

 public String getParameter(String para){

  String postStrInfo = super.getParameter(para);

  //log.debug("parameter name: "+para+" value:"+postStrInfo);

  try {

   //log.debug("parameter name: "+para);

   log.debug("(檢測)接收到的["+request.getMethod()+"]請求參數值: " + postStrInfo); 

   xssCheck(postStrInfo,keywords);

  } catch (IllegalAccessError e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

   throw e;

  } catch (IOException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  }

  return postStrInfo;

 }

  public ServletInputStream getInputStream() {

   //ServletInputStream

   ServletInputStream stream = null; 

   //POST表單資訊

   String postStrInfo = null;

    try{

      stream = request.getInputStream();

      byte[] buffer = IOUtils.toByteArray(stream);

      postStrInfo = new String(buffer,"GB2312");

      //拆分請求參數串

      String[] args = postStrInfo.split("\r\n");

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

       String line  = args[i];

       //過濾分隔符,和請求參數名稱

       if(line.trim().startsWith("-------------------") || line.trim().startsWith("Content-Disposition")  || line.trim().equals("")){

        log.debug("(忽略)接收到的["+request.getMethod()+"]請求參數值: " + line); 

        continue;

       }

       log.debug("(檢測)接收到的["+request.getMethod()+"]請求參數值: " + line); 

       xssCheck(line,keywords);

      }

      //驗證完成

      final ByteArrayInputStream bais = new ByteArrayInputStream(buffer);

      //生成新的ServletInputStream

      ServletInputStream sis = new ServletInputStream() {

       public int read() throws IOException {

        // TODO Auto-generated method stub

        return bais.read();

       }

      };

      stream = sis;

    }catch(IOException e){

     e.printStackTrace();

    } 

   return  stream;

  }

 private void xssCheck(String postStrInfo,Vector array) throws IOException,

   IllegalAccessError {

  if(postStrInfo==null)return;

  String src = postStrInfo==null?"null":postStrInfo.toLowerCase();

  src = java.net.URLDecoder.decode(src,"GB2312");

  //驗證XSS中是否包含相關關鍵字

  if(src!=null && !src.equalsIgnoreCase("null")){

   String keyword = "";

   for (int i = 0; i < array.size(); i++) {

     keyword = array.get(i).toString();

     if(src.indexOf(keyword)!=-1){

      isXssFind = true;

      break;

     }

   }

   if(isXssFind){

    log.error("發現疑為跨站腳本攻擊,檢測判斷請求位址包含非法字元:"+java.net.URLEncoder.encode(keyword,"GB2312"));

    request.setAttribute("errorMsg", "發現疑為跨站腳本攻擊,檢測判斷請求位址包含非法字元:"+java.net.URLEncoder.encode(keyword,"GB2312"));

    request.getSession(true).setAttribute("injectKey","發現疑為跨站腳本攻擊,檢測判斷請求位址包含非法字元:"+java.net.URLEncoder.encode(keyword,"GB2312"));

    request.getSession().invalidate();

    serlvetResponse.sendRedirect(failForwardPath);

     throw new java.lang.IllegalAccessError();

   }

  }

 }

 private void xssCheck(String[] values,Vector array) throws IOException,IllegalAccessError {

             if(values==null){return;}

             for (int j = 0; j < values.length; j++) {

    String src = java.net.URLDecoder.decode(values[j],"GB2312");

    //驗證XSS中是否包含相關關鍵字

    if(src!=null && !src.equalsIgnoreCase("null")){

     String keyword = "";

     for (int i = 0; i < array.size(); i++) {

       keyword = array.get(i).toString();

       if(src.indexOf(keyword)!=-1){

        isXssFind = true;

        break;

       }

     }

     if(isXssFind){

      log.error("發現疑為跨站腳本攻擊,檢測判斷請求位址包含非法字元:"+java.net.URLEncoder.encode(keyword,"GB2312"));

      request.setAttribute("errorMsg", "發現疑為跨站腳本攻擊,檢測判斷請求位址包含非法字元:"+java.net.URLEncoder.encode(keyword,"GB2312"));

      request.getSession(true).setAttribute("injectKey","發現疑為跨站腳本攻擊,檢測判斷請求位址包含非法字元:"+java.net.URLEncoder.encode(keyword,"GB2312"));

      request.getSession().invalidate();

      serlvetResponse.sendRedirect(failForwardPath);

       throw new java.lang.IllegalAccessError();     }

    }

   }

    }

繼續閱讀