XSS腳本攻擊防禦(Antisamy)(上)

由於公司的產品準備全面互聯網化,所以就對安全問題進行了一系列的排查,排查過程中發現了xss腳本攻擊的問題,開始着手瞭解和修改代碼

xss攻擊的簡單解釋

跨站腳本(Cross-site scripting,通常簡稱爲XSS)是一種網站應用程序的安全漏洞攻擊,是代碼注入的一種。它允許惡意用戶將代碼注入到網頁上,其他用戶在觀看網頁時就會受到影響。這類攻擊通常包含了HTML以及用戶端腳本語言。
—維基百科跨站腳本

通過開源項目Antisamy防禦Xss攻擊

Antisamy是owasp下的開源項目(下載地址,需要翻牆),主要用於防禦富文本的xss攻擊。
需要說明的是,在實際情況中,最經常出現的攻擊情況是輸入框的js代碼傳入和按鈕的url篡改,但是由於實際業務的需要,我們並不能嚴格控制輸入框的內容爲漢字或者數字,所以應當對輸入進行過濾。

引入Antisamy包

<dependency>
    <groupId>org.owasp.antisamy</groupId>
    <artifactId>antisamy</artifactId>
    <version>1.5.5</version>
</dependency>```

這段代碼是通過maven工具引入antisamy最新版本的jar包到項目中,如果沒有使用maven項目,就需要手動下載jar包在項目中建立依賴。

jar包中的xml文件

antisamy jar包中包含多個xml配置文件,用於配置項目中允許輸入的內容。其中有
xml配置文件

antisamy-ebay.xml文件是ebay網站使用的過濾富文本輸入的配置文件,其他幾個帶有公司名稱後綴的配置文件是相應公司使用的配置策略。需要注意的是antisamy-anythinggoes.xml文件,這個文件允許所有有效的html和css元素輸入,但是拒絕javascript和css相關的網絡釣魚攻擊。一般不推薦使用,但是可以當作參考,用於研究策略文件定義的基本規則。

Antisamy項目使用

項目的使用並不複雜,下面給出一個最簡單的思路

//定義過濾的策略
Policy policy = Policy.getInstance("file"); //此處的file指使用的策略文件,如antisamy-ebay.xml
//對html輸入進行過濾
Antisamy antisamy = new Antisamy();
CleanResult cr = antisamy.scan(innerHtml,policy);
//輸出過濾後安全的html或異常信息
String cleanHtml = cr.getCleanHTML();
String errMsg = cr.getErrorMessages();

而在項目中的使用是這樣的:

  • 定義一個filter
package com.vivi.test.xssfilter;

import java.io.IOException;

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;

public class XssFilter implements Filter {

    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub

    }

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        System.out.println("enter xssFilter----------------------------");
        chain.doFilter(new XssRequestWrapper((HttpServletRequest) request),
                response);

    }

    public void destroy() {
        // TODO Auto-generated method stub

    }

}
  • 重寫request
package com.vivi.test.xssfilter;

import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.log4j.Logger;
import org.owasp.validator.html.AntiSamy;
import org.owasp.validator.html.CleanResults;
import org.owasp.validator.html.Policy;
import org.owasp.validator.html.PolicyException;
import org.owasp.validator.html.ScanException;

public class XssRequestWrapper extends HttpServletRequestWrapper {
    private static Policy policy = null;
    public static Logger logger = Logger.getLogger(XssRequestWrapper.class);

    static {
        try {
            policy = Policy.getInstance(XssRequestWrapper.class
                    .getClassLoader().getResourceAsStream("antisamy-ebay.xml"));
        } catch (PolicyException e) {
            e.printStackTrace();
        }
    }

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

    @SuppressWarnings("rawtypes")
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> request_map = super.getParameterMap();
        Iterator iterator = request_map.entrySet().iterator();
        System.out.println("request_map" + request_map.size());
        logger.debug("request_map" + request_map.size());
        while (iterator.hasNext()) {
            Map.Entry me = (Map.Entry) iterator.next();
            System.out.println(me.getKey() + ":");
            String[] values = (String[]) me.getValue();
            for (int i = 0; i < values.length; i++) {
                System.out.println(values[i]);
                logger.debug(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++)
            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;
        return xssClean(str);
    }

    private String xssClean(String value) {
        AntiSamy antiSamy = new AntiSamy();
        try {
            if (policy.equals(null)) {
                getPolicy();
            }
            final CleanResults cr = antiSamy.scan(value, policy);
            // 安全的HTML輸出
            return cr.getCleanHTML();
        } catch (ScanException e) {
            e.printStackTrace();
        } catch (PolicyException e) {
            e.printStackTrace();
        }
        return value;
    }

    private void getPolicy() throws PolicyException {
        try {
            policy = Policy.getInstance(XssRequestWrapper.class
                    .getClassLoader().getResourceAsStream("antisamy-ebay.xml"));
        } catch (PolicyException e) {
            e.printStackTrace();
        }
    }
}

實際使用起來也特別方便。

時間所限,這是上篇,下篇寫antisamy原理的簡單解析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章