XSSとは何ですか?防御する方法は?SpringbootでXSS防御を構成する方法と詳細なコード分析を教えてください!


1.XSSの簡単な理解

さあ、バイドゥは最初に段落をコピーします。
HTMLは、一部の文字を特別に処理することによってテキストとマークアップを区別するハイパーテキストマークアップ言語です。たとえば、小なり記号(<)はHTMLタグの先頭と見なされ、その間の文字はページのタイトルなどです。動的ページに挿入されるコンテンツにこれらの特殊文字(<など)が含まれている場合、ユーザーのブラウザーはそれをHTMLタグの挿入と間違えます。これらのHTMLタグがJavaScriptスクリプトを導入すると、これらのスクリプトがユーザーに表示されます。ブラウザで実行します。したがって、これらの特殊文字を動的ページでチェックできない場合、またはチェックにエラーがある場合、XSSの脆弱性が発生します。
わかりやすい例を
使って紹介しましょう防御を使う前に、ユーザー管理機能とユーザー登録機能があるとしましょう。ユーザーがフロントデスクに登録されている場合、ユーザー名が含まれ、ユーザー管理がこのユーザー情報を表示すると、ボックスが常にポップアップ表示されます。これは単純なXSS攻撃です。

2.防御する方法

従来のXSS防御では、主にキーワード「javascript」を検索するために、攻撃の識別に機能マッチング方法を使用しますが、この識別は十分な柔軟性がありません。送信された情報に「javascript」がある場合は常に、厳密になります。 XSS攻撃と判断されました。

コード変更に基づく防御。Webページの開発者は、プログラムを作成するときにいくつかの間違いや脆弱性を抱えていることがよくあります。XSS攻撃は間違いや脆弱性を使用します。したがって、理想的な方法は、Webアプリケーション開発を最適化することにより、脆弱性を減らし、攻撃を回避することです。1)ユーザーサーバーに送信された情報は、URL、添付されたHTTPヘッダー、POSTデータなどについて照会され、指定された形式と長さではないコンテンツについてフィルター処理される必要があります。2)セッショントークン、CAPTCHAシステム、またはHTTP参照ヘッダーチェックを実現して、サードパーティのWebサイトによる機能の実行を防止します。3)受信したコンテンツが適切に標準化され、最小で安全なタグのみが含まれていること(javascriptなし)を確認し、リモートコンテンツ(特にスタイルシートとjavascript)への参照をすべて削除し、HTTPのみのCookieを使用します。

クライアント側の階層型防御戦略。クライアント側のクロスサイトスクリプティング攻撃の階層型防御戦略は、スレッドの独立した割り当てと階層型防御戦略に基づくセキュリティモデルです。クライアント(ブラウザ)上に構築されています。これが他のモデルとの最大の違いです。クライアントのセキュリティが非常に重要である理由は、クライアントがサーバー情報を受信し、関連するコンテンツを選択的に実行しているためです。これにより、XSS攻撃に対する防御が容易になります。モデルは主に3つの部分で構成されます。1)各Webページに独立したスレッドを割り当ててリソース消費を分析する「Webページスレッド分析モジュール」。2)4つの階層化された防御戦略が含まれます。ルールユーザー入力分析モジュール; 3)インターネット上のXSS悪意のあるWebサイトに関する情報を保存するXSS情報データベース

気分が悪い場合は、上記を見る必要はありません。
気分が良い場合は、すべてBaiduからのものであるため、実際には上記を見る必要はありません。


Googleは現在、一連のエスケープ標準を提供しています。より大きい記号と小さい記号は、他の表現に変換されます。
例:ここにはフルセットがありますが、皆さんはフル
ここに写真の説明を挿入
セットを見たいと思っています。原則として、この一連の標準を使用することです。エスケープされた文字列はデータベースに保存され、フォアグラウンドが解析されるときにこのルールによって提示されます。
転送方法、転送先は?このアプローチは非常に興味深いものです。最初にコードを公開します。結局のところ、一部の人々はそれを使いたがっています。コードがリリースされたら、もう一度説明します。誰も理解できないと思います。理解できない場合は、私のベッドに座って説明します。

SpringBoot構成XSS防御

まず、Mavenは必要な依存関係をインポートします。すでにインポートされている場合は、再度インポートする必要はありません。Mavenの公式Webサイトにアクセスして、最新バージョンを見つけることができます。

<!--xss防御-->
<dependency>
  <groupId>org.jsoup</groupId>
  <artifactId>jsoup</artifactId>
  <version>1.10.2</version>
</dependency>
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.5</version>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.73</version>
</dependency>

次に行うことは、処理をインターセプトするフィルターを作成することです

XssFilterを記述して、すべてのリクエストをフィルタリングします

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
 * XSS过滤器
 * @author Jozz
 */
@WebFilter(filterName="xssFilter",urlPatterns="/*")
public class XssFilter implements Filter {
    
    
    @Override
    public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
    
    
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String path = request.getServletPath();
        //由于我的@WebFilter注解配置的是urlPatterns="/*"(过滤所有请求),所以这里对不需要过滤的静态资源url,作忽略处理(大家可以依照具体需求配置)
        String[] exclusionsUrls = {
    
    ".js",".gif",".jpg",".png",".css",".ico"};
        for (String str : exclusionsUrls) {
    
    
            if (path.contains(str)) {
    
    
                filterChain.doFilter(servletRequest,servletResponse);
                return;
            }
        }
        filterChain.doFilter(new XssHttpServletRequestWrapper(request),servletResponse);
    }
    @Override
    public void destroy() {
    
    
    }
};

次に、ServletRequestパッケージングクラスに移動します。このクラスは説明できないように見える場合があります。説明を待ちます。

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringEscapeUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
/**
 * ServletRequest包装类,对request做XSS过滤处理
 * @author Jozz
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    
    
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
    
    
        super(request);
    }

    @Override
    public String getHeader(String name) {
    
    
        return StringEscapeUtils.escapeHtml4(super.getHeader(name));
    }
    @Override
    public String getQueryString() {
    
    
        return StringEscapeUtils.escapeHtml4(super.getQueryString());
    }
    @Override
    public String getParameter(String name) {
    
    
        return StringEscapeUtils.escapeHtml4(super.getParameter(name));
    }
    @Override
    public String[] getParameterValues(String name) {
    
    
        String[] values = super.getParameterValues(name);
        if(values != null) {
    
    
            int length = values.length;
            String[] escapseValues = new String[length];
            for(int i = 0; i < length; i++){
    
    
                escapseValues[i] = StringEscapeUtils.escapeHtml4(values[i]);
            }
            return escapseValues;
        }
        return values;
    }
    @Override
    public ServletInputStream getInputStream() throws IOException {
    
    
        String str=getRequestBody(super.getInputStream());
        Map<String,Object> map= JSON.parseObject(str,Map.class);
        Map<String,Object> resultMap=new HashMap<>(map.size());
        for(String key:map.keySet()){
    
    
            Object val=map.get(key);
            if(map.get(key) instanceof String){
    
    
                resultMap.put(key,StringEscapeUtils.escapeHtml4(val.toString()));
            }else{
    
    
                resultMap.put(key,val);
            }
        }
        str=JSON.toJSONString(resultMap);
        final ByteArrayInputStream bais = new ByteArrayInputStream(str.getBytes());
        return new ServletInputStream() {
    
    
            @Override
            public int read() throws IOException {
    
    
                return bais.read();
            }
            @Override
            public boolean isFinished() {
    
    
                return false;
            }
            @Override
            public boolean isReady() {
    
    
                return false;
            }
            @Override
            public void setReadListener(ReadListener listener) {
    
    
            }
        };
    }
    private String getRequestBody(InputStream stream) {
    
    
        String line = "";
        StringBuilder body = new StringBuilder();
        int counter = 0;
        // 读取POST提交的数据内容
        BufferedReader reader = new BufferedReader(new InputStreamReader(stream, Charset.forName("UTF-8")));
        try {
    
    
            while ((line = reader.readLine()) != null) {
    
    
                body.append(line);
                counter++;
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        return body.toString();
    }
}

最後に、@ ServletComponentScanアノテーションがスキャンフィルターのスタートアップクラスに追加されます。

@SpringBootApplication
@MapperScan("com.kid.mapper")
//@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
@ServletComponentScan//扫描过滤器
@EnableCaching
public class Boot {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Boot.class, args);
    }
}

それでは、今すぐ始めて効果を示しましょう
ここに写真の説明を挿入
。アカウントに不正な文字を入力したことがわかります。バックグラウンドで取得した情報を印刷しました。
ここに写真の説明を挿入
実際、受け取ったものはこのようなものではなく、転送されただけでした。それでおしまい。

コード分​​析

この事件はフィルターで処理された後、うまく防御されたことを誰もが知っていると思います。では、フィルターは正確に何をしたのでしょうか?一部の写真やその他のファイルによって要求されたURLが許可されていることを除いて、フィルターは何もせずに削除されたように見えます。
しかし、フローを詳しく見てみましょう。着信リクエストオブジェクト
filterChain.doFilter(new XssHttpServletRequestWrapper(request)、servletResponse);
ここでは、リクエストオブジェクトが別のオブジェクトにラップされ、衣服が着用されています。
実際、このデザインパターンはデコレータパターンと呼ばれ、単純な接続プールの章でもこのパターンについて具体的に説明しました。興味があるかどうかもわかります。
シンプルな接続プールとデコレータモード

FilterChainインターフェースでわかるように、var1パラメーターはServletRequestタイプのオブジェクトで渡す必要があるため、ここでのオブジェクトは、ServletRequestインターフェースを実装する任意のオブジェクトにすることができます。

public interface FilterChain {
    
    
    void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}

ソースコードを見ると、HttpServletRequestがインターフェイスであり、ServletRequestインターフェイスを継承していることもわかります。

public interface HttpServletRequest extends HttpServletRequest 

したがって、この場所は、HttpServletRequestインターフェイスを実装するクラスまたはHttpServletRequestインターフェイスを実装するクラスを実装するだけで済みます。
フィルタで取得するリクエストオブジェクトはHttpServletRequestタイプであるため、これをラップする必要があります。次に、このリクエストをラップするHttpServletRequestインターフェイスを実装するクラスを作成する必要があります。

ただし、上記のコードから、HttpServletRequestWrapperオブジェクトを継承しました。実際、このHttpServletRequestWrapperオブジェクトは、HttpServletRequestインターフェイスを実装し、すべてのインターフェイスを実装し、各メソッドはそのままコピーされます。

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper 

上記の部分は実際には知られているかどうかはわかりませんが、プログラマーとしてはこれらを理解する必要があると思います

次に、HttpServletRequestオブジェクトがフィルターでのみ置き換えられることがわかります。明らかに、XSS防御を実装する必要があります。getParameterなどの文字列を取得するこれらのメソッドで文字列を取得するだけで、最初に取得した文字列をツールクラスに転送して変換できます。もう一度発信者に戻ります。

  @Override
    public String getParameter(String name) {
    
    
        return StringEscapeUtils.escapeHtml4(super.getParameter(name));
    }

以下は私が単純に描いた絵です、hahahahahahaまたはhahahahahahahahahahahahahahahahahahahaha、見てみましょう。次の章でお会いしましょう!
ここに写真の説明を挿入

おすすめ

転載: blog.csdn.net/qq_39150049/article/details/109379025