cookie跨站腳本漏洞解決方案


近日項目碰到一個跨腳本注入的問題:

這安全測評工具也是厲害了,直接將腳本注入到cookie里頭,以前沒有碰到這樣的情況。

之前寫過一篇文章過濾跨腳本注入的問題。《淺談XSS攻擊原理與解決方法》關於跨腳本注入的問題,不曉得原理的同學可以看下。但是里頭沒有處理cookie注入的問題。接下來介紹下如何處理。

關鍵代碼在這里:首先獲取到cookie,檢查下是否有敏感字符,如果有的話,就進行替換。

//防止cookie跨站注入問題,替換敏感字符。
         Cookie[] cookies = ((HttpServletRequest) request).getCookies();
         if(cookies!=null) {
            for(Cookie cookie: cookies){     
                if(CookieFilterUtil.isValidate(cookie.getValue())){
                    cookie.setValue(CookieFilterUtil.xssClean(cookie.getValue()));
                    Cookie newCookie=cookie;
                    cookie.setMaxAge(0);
                    ((HttpServletResponse) response).addCookie(newCookie);
                    break;
                }                 
             }
         }

CookieFilter.java

public class CookieFilterUtil {
     //將敏感字符進行替換
     public static String xssClean(String value) {
            //ClassLoaderUtils.getResourceAsStream("classpath:antisamy-slashdot.xml", XssHttpServletRequestWrapper.class)
            if (value != null) {
                // NOTE: It's highly recommended to use the ESAPI library and
                // uncomment the following line to
                // avoid encoded attacks.
                // value = encoder.canonicalize(value);
                value = value.replaceAll("\0", "");
                
                // Avoid anything between script tags
                Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>",
                        Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");

                // Avoid anything in a src='...' type of expression
                scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                                | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid anything in a href='...' type of expression
                scriptPattern = Pattern.compile("href[\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(...) expressions
                scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                                | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");

                // Avoid expression(...) expressions
                scriptPattern = Pattern.compile("expression\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                                | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");

                // Avoid javascript:... expressions
                scriptPattern = Pattern.compile("javascript:",
                        Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");

                // Avoid vbscript:... expressions
                scriptPattern = Pattern.compile("vbscript:",
                        Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");

                // Avoid onload= expressions
                scriptPattern = Pattern.compile("onload(.*?)=",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                                | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
            }  
              return value; 
    }
    //校驗是否含有敏感字符
    public static boolean isValidate(String value) {
            //ClassLoaderUtils.getResourceAsStream("classpath:antisamy-slashdot.xml", XssHttpServletRequestWrapper.class)
            boolean flag=false;
            if (value != null) {
                // NOTE: It's highly recommended to use the ESAPI library and
                // uncomment the following line to
                // avoid encoded attacks.
                // value = encoder.canonicalize(value);
                value = value.replaceAll("\0", "");
                
                // Avoid anything between script tags
                Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>",
                        Pattern.CASE_INSENSITIVE);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
    
                // Avoid anything in a src='...' type of expression
                scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                                | Pattern.DOTALL);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
                
                // Avoid anything in a href='...' type of expression
                scriptPattern = Pattern.compile("href[\r\n]*=[\r\n]*\\\"(.*?)\\\"",
                                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                                            | Pattern.DOTALL);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
                
    
                // Remove any lonesome </script> tag
                scriptPattern = Pattern.compile("</script>",
                        Pattern.CASE_INSENSITIVE);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
    
                // Remove any lonesome <script ...> tag
                scriptPattern = Pattern.compile("<script(.*?)>",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                                | Pattern.DOTALL);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
    
                // Avoid eval(...) expressions
                scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                                | Pattern.DOTALL);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
                
                // Avoid expression(...) expressions
                scriptPattern = Pattern.compile("expression\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                                | Pattern.DOTALL);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
                
                // Avoid javascript:... expressions
                scriptPattern = Pattern.compile("javascript:",
                        Pattern.CASE_INSENSITIVE);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
    
                // Avoid vbscript:... expressions
                scriptPattern = Pattern.compile("vbscript:",
                        Pattern.CASE_INSENSITIVE);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
                
                // Avoid onload= expressions
                scriptPattern = Pattern.compile("onload(.*?)=",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                                | Pattern.DOTALL);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
            }  
            return flag; 
          }
}
XssFilter.java
public class XssFilter implements Filter {
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        
         //防止cookie跨站注入問題,替換敏感字符。
         boolean flag=false;
         Cookie[] cookies = ((HttpServletRequest) request).getCookies();
         if(cookies!=null) {
            for(Cookie cookie: cookies){     
                if(CookieFilterUtil.isValidate(cookie.getValue())){
                    flag=true;
                    cookie.setValue(CookieFilterUtil.xssClean(cookie.getValue()));
                    Cookie newCookie=cookie;
                    cookie.setMaxAge(0);
                    ((HttpServletResponse) response).addCookie(newCookie);
                    break;
                }                 
             }
         }
         
         //如果存在跨站注入問題,跳轉到登錄頁。
         if(!flag){
             String path = ((HttpServletRequest) request).getContextPath();
             String protAndPath = request.getServerPort() == 80 ? "" : ":"
                     + request.getServerPort();
             String basePath = request.getScheme() + "://"
                     + request.getServerName() + protAndPath + path + "/";
             String returnUrl = basePath+"login.do";
             request.setCharacterEncoding("UTF-8");
             response.setContentType("text/html; charset=UTF-8"); // 轉碼
             response.getWriter().println(
                           "<script language=\"javascript\">if(window.opener==null){window.top.location.href=\""
                                   + returnUrl
                                   + "\";}else{window.opener.top.location.href=\""
                                   + returnUrl
                                   + "\";window.close();}</script>");
         }else{
             chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
         }
         
    }

    @Override
    public void destroy() {
    }
    
   
}

 這兒的操作如果有敏感字符,那么就調整到登錄首頁,刪除cookie,當然也可以不處理,像以下代碼這樣

 //防止cookie跨站注入問題,替換敏感字符。
         Cookie[] cookies = ((HttpServletRequest) request).getCookies();
         if(cookies!=null) {
            for(Cookie cookie: cookies){     
                if(CookieFilterUtil.isValidate(cookie.getValue())){
                    cookie.setValue(CookieFilterUtil.xssClean(cookie.getValue()));
                    Cookie newCookie=cookie;
                    cookie.setMaxAge(0);
                    ((HttpServletResponse) response).addCookie(newCookie);
                    break;
                }                 
             }
         }         
         chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);

xss過濾器實現XssHttpServletRequestWrapper.java

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @SuppressWarnings("rawtypes")
    public Map<String,String[]> getParameterMap(){
        Map<String,String[]> request_map = super.getParameterMap();
        Iterator iterator = request_map.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry me = (Map.Entry)iterator.next();
            String[] values = (String[])me.getValue();
            for(int i = 0 ; i < values.length ; i++){
                values[i]=HtmlRegexpUtil.fiterHtmlByTagArr(values[i]);
                values[i] = xssClean(values[i]);
            }
        }
        
        return request_map;
    }
     public String[] getParameterValues(String paramString)
      {
        String[] arrayOfString1 = super.getParameterValues(paramString);
        if (arrayOfString1 == null)
          return null;
        int i = arrayOfString1.length;
        String[] arrayOfString2 = new String[i];
        for (int j = 0; j < i; j++){
            arrayOfString1[j]=HtmlRegexpUtil.fiterHtmlByTagArr(arrayOfString1[j]);
            arrayOfString2[j] = xssClean(arrayOfString1[j]);
        }
        return arrayOfString2;
      }

      public String getParameter(String paramString)
      {
        String str = super.getParameter(paramString);
        if (str == null)
          return null;
        return xssClean(str);
      }

      public String getHeader(String paramString)
      {
        String str = super.getHeader(paramString);
        if (str == null)
          return null;
        str = str.replaceAll("\r|\n", "");
        return xssClean(str);
      }
      
      
      private String xssClean(String value) {
        //ClassLoaderUtils.getResourceAsStream("classpath:antisamy-slashdot.xml", XssHttpServletRequestWrapper.class)
        if (value != null) {
            // NOTE: It's highly recommended to use the ESAPI library and
            // uncomment the following line to
            // avoid encoded attacks.
            // value = encoder.canonicalize(value);
            value = value.replaceAll("\0", "");
            
            // Avoid anything between script tags
            Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>",
                    Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");

            // Avoid anything in a src='...' type of expression
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                            | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid anything in a href='...' type of expression
            scriptPattern = Pattern.compile("href[\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(...) expressions
            scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                            | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");

            // Avoid expression(...) expressions
            scriptPattern = Pattern.compile("expression\\((.*?)\\)",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                            | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");

            // Avoid javascript:... expressions
            scriptPattern = Pattern.compile("javascript:",
                    Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");

            // Avoid vbscript:... expressions
            scriptPattern = Pattern.compile("vbscript:",
                    Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");

            // Avoid onload= expressions
            scriptPattern = Pattern.compile("onload(.*?)=",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
                            | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
        }  
          return value; 
          }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM