4

私の REST API の 1 つは、ユーザーからの入力として URL を期待するプロパティ「url」を期待しています。XSS 攻撃を防ぐために ESAPI を使用しています。問題は、ユーザーが指定した URL が次のようなものであることです。

http://example.com/alpha?abc=def&phil=key%3dbdj

ESAPI エンコーダーの cannonicalize メソッドは、ここで侵入例外をスローし、入力にエンコードが混在していると主張します。これは、URL がエンコードされており、'&phi' が HTML エンコードされたものとして扱われ、例外が発生するためです。

2 番目のクエリ パラメータが「pa」または「pi」で始まり、HTML デコードによってデルタまたはパイ文字に変換されたアプリケーション URL の 1 つをサニタイズする際に、同様の問題がありました。以前の Stackoverflow の質問を参照してください。

問題は、URL 全体がユーザーからの入力として送られてくるため、単純にクエリ パラメータを解析して個別にサニタイズすることはできません。悪意のある入力が 2 つのクエリ パラメータを組み合わせて作成され、それらを個別にサニタイズしてもうまくいかないからです。場合。

例: <scr come は最初のクエリ パラメータ値の最後の部分であり、ipt>alert(0); または、次のクエリ パラメータ コントロール コンテキストの最初の部分として何かが来ます。

誰かが同様の問題に直面しましたか?皆さんが実装したソリューションを知りたいです。ご指摘ありがとうございます。

編集:「avgvstvs」からの以下の回答は、侵入例外をスローしません (ありがとう!!)。ただし、cannonicalize メソッドは元の入力文字列を変更するようになりました。ESAPI は、クエリ パラメータの &phi を HTML でエンコードされた文字として扱い、「?」に置き換えます。文字。ここにリンクされている私の前の質問のようなもの。違いは、これがユーザー入力であるのに対し、私のアプリケーションの URL であるということです。ここでホワイトリストを維持する唯一のオプションはありますか?

4

1 に答える 1

2

ここで直面している問題は、URL のさまざまな部分をエンコードするためのさまざまな規則があることです。覚えておくと、URL にはさまざまなエンコード規則を持つ 4 つのセクションがあります。UriBuilderまず、Java でクラスを使用して URL を作成する必要がある理由を理解します。URL仕様は、核心的な詳細に役立ちます。

問題は、URL 全体がユーザーからの入力として送られてくるため、単純にクエリ パラメータを解析して個別にサニタイズすることはできないということです。2 つのクエリ パラメータを組み合わせて悪意のある入力を作成し、それらを個別にサニタイズしてもうまくいかないからです。場合。

ここでの唯一の実際のオプションはjava.net.URI.

これを試して:

URI dirtyURI = new URI("http://example.com/alpha?abc=def&phil=key%3dbdj");

String cleanURIStr = enc.canonicalize( dirtyURI.getPath() );

への呼び出しURI.getPath()は、パーセントでエンコードされていない URL を提供する必要があり、enc.canonicalize()その段階の後に二重エンコードが検出された場合は、実際には二重にエンコードされた文字列があり、単一にエンコードされた URL 文字列のみを受け入れることを呼び出し元に通知する必要があります。はURI.getPath()、URL 文字列の各部分にデコード ルールを使用するほどスマートです。

それでも問題が発生する場合、API リファレンスには、URL のさまざまな部分でさまざまなことを行う必要がある場合に備えて、URL の他の部分を抽出する他のメソッドがあります。たとえば、GET リクエストでパラメーターを手動で解析する必要がある場合は、実際にはクエリ文字列自体を返すだけで済み、デコード パスが実行されます。

=============JUNITテストケース============

package org.owasp.esapi;

import java.net.URI;
import java.net.URISyntaxException;

import org.junit.Test;

public class TestURLValidation {

    @Test
    public void test() throws URISyntaxException {
        Encoder enc = ESAPI.encoder();
        String input = "http://example.com/alpha?abc=def&phil=key%3dbdj";
        URI dirtyURI = new URI(input);
        enc.canonicalize(dirtyURI.getQuery());
        
    }

}

=================更新された質問の回答====================

これを回避する方法はありません。 Encoder.canonicalize()エスケープされた文字シーケンスを縮小された Java 固有の形式に縮小することを目的としています。URL は特殊なケースと見なされる可能性が高いため、意図的に考慮対象から除外された可能性が高いです。ホワイトリストなしであなたのケースを処理する方法は次のとおりですEncoder.canonicalize().

上記のコードを使用して、入力の URI 表現を取得します。

ステップ 1: ステップ 2 を除くすべての URI 部分を正規URI.getQuery() 化します。ライブラリ パーサーを使用して、クエリ文字列をデータ構造に解析します。commons の httpclient-4.3.3.jar と httpcore-4.3.3.jar を使用します。次に、次のようにします。

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.List;

import javax.ws.rs.core.UriBuilder;

import org.apache.http.client.utils.URLEncodedUtils;
import org.junit.Test;
import org.owasp.esapi.ESAPI;
import org.owasp.esapi.Encoder;

public class TestURLValidation
{

  @Test
  public void test() throws URISyntaxException {
    Encoder enc = ESAPI.encoder();
    String input = "http://example.com/alpha?abc=def&phil=key%3dbdj";
    URI dirtyURI = new URI(input);
    UriBuilder uriData = UriBuilder.fromUri(enc.canonicalize(dirtyURI.getScheme()));
    uriData.path(enc.canonicalize(enc.canonicalize(dirtyURI.getAuthority() + dirtyURI.getPath())));
    println(uriData.build().toString());
    List<org.apache.http.NameValuePair> params = URLEncodedUtils.parse(dirtyURI, "UTF-8");
    Iterator<org.apache.http.NameValuePair> it = params.iterator();
    while(it.hasNext()) {
      org.apache.http.NameValuePair nValuePair = it.next();
      uriData.queryParam(enc.canonicalize(nValuePair.getName()), enc.canonicalize(nValuePair.getValue()));
    }
    String canonicalizedUrl = uriData.build().toString();
    println(canonicalizedUrl);
  }

  public static void println(String s) {
    System.out.println(s);
  }
  
}

ここで実際に行っているのは、標準ライブラリを使用して inputURL を解析し (したがって、すべての負担を取り除きます)、各セクションを解析した後にパーツを正規化することです。

リストしたコードは、すべてのURL タイプで機能するとは限らないことに注意してください... URL には、スキーム/権限/パス/クエリよりも多くの部分があります。(欠けているのは、userInfo または port の可能性です。これらが必要な場合は、このコードを適宜変更してください。)

于 2014-05-03T18:23:32.907 に答える