一般的な URLScan シナリオ

発行日 : 2008 年 6 月 5 日 (作業者 : iisteam (英語))
更新日 : 2009 年 2 月 19 日 (作業者 : iisteam (英語))

この記事ではURLScanの一般的な利用シナリオについて列挙し、Urlscan.ini構成ファイルを設定してシナリオを有効にする方法を説明します。

特定文字列パターンを含む要求を禁止するルールの作成

URLScan v3.1 に追加された新機能では、ルールの一覧を作成できます。このルールの一覧を使用すると、HTTP 要求の特定部分に適合するパターンに基づいて要求を拒否するルールを指定できます。この機能の主要な構成は、[Options] セクションの RuleList キーです。このキーの値は、ルールを定義する、コンマで区切られたセクション名の一覧です。ルール "Foo" の定義は、次のようになります。

**[Options]
RuleList=Foo

**[**Foo]
AppliesTo=.htm
DenyDataSection=Foo Strings
ScanUrl=0
ScanAllRaw=0
ScanQueryString=0
ScanHeaders=Foo-Header:
DenyUnescapedPercent=1

**[**Foo Strings]
--
**<>

[Options]RuleList には、実行されるすべてのルールの一覧を記述します。この例では、評価が必要なルール "Foo" があります。これは、コンマ区切りの複数のルールである場合もあります。同じ [Foo] という名前のセクションではルールを定義します。RuleList の項目に、宣言されたセクションがない場合は、フィルターにより構成エラーがログ ファイルに記録されます。このセクションに属する AppliesTo キーでは、このルールが適用されるファイル拡張子を指定します。DenyDataSection キーでは、このルールで照合される文字列パターンを含むセクションを指定します。ここに示されているとおり、3 つのパターンが記述された [Foo Strings] セクションがあります。この一覧は大文字と小文字の区別がなく、形式 %XX のエンコードされた値を入力できます (XX は 16 進数字)。[Foo] セクションのその他のキーでは、このルールが適用される要求の部分を指定します。URL (ScanUrl)、生の HTTP 要求 (ScanAllRaw)、クエリ文字列 (ScanQueryString)、特定のヘッダーの一覧 (ScanHeaders) などを指定できます。ScanHeaders 以外の Scan キーには、boolean 値を指定します。ScanHeaders には、コンマで区切られた実際のヘッダー値の一覧を指定し、ヘッダー値の後にはコロンを付ける必要があります。上記の例では、要求の "Foo-Header" のみで特定の文字列をスキャンします。データ セクションの前にあるルールの最後の設定 (DenyUnescapedPercent) は、エスケープ シーケンスとして使用されない % 文字を、要求の特定部分でスキャンし、このようなシーケンスが見つかった要求をブロックするために使用します。そのため DenyUnescapedPercent を 1 に設定すると、シーケンス %XX ではブロックされますが、%20 または %u0020 ではブロックされません。これは、後者 2 つはエスケープされた [空白] 文字を表すためです。この設定は、URLScan v3.1 から導入されました。URLScan v3.0 には存在しません。

以下の要求は、そのヘッダー Foo-Header に "--" パターンが含まれているため、このルールに適合します。

GET /iisstart.htm HTTP/1.1\r\n
Host:localhost\r\n
Accept:*/*\r\n
**** Foo-Header:Test--value\r\n \r\n

以下の要求は、 Foo-Header  にエスケープ シーケンスを示すために使用する "%" 文字が含まれているため、このルールに適合します。

GET /iisstart.htm HTTP/1.1\r\n
Host:localhost\r\n
Accept:*/*\r\n
**** Foo-Header:E%XEC\r\n \r\n

 

 

SQL インジェクションのシグニチャーをブロックするためのルール

先に進む前に、この方法はアプリケーションで SQL インジェクションを回避する推奨の方法ではないということに留意してください。悪意のある攻撃にさらされたサーバーに対する一時的な対策にすぎません。このようなルールがあると、「Preventing SQL Injections in ASP (英語)」 にあるベスト プラクティスを使用してアプリケーションを修正する際に、余裕ができます。また以下のようなルールは、誤検知が発生し、有効なアプリケーション要求に失敗する可能性が高くなります。もう 1 つの重要な点は、以下のルールは、要求エンティティ本体を介した SQL インジェクションの試みをブロックするわけではないということです。

上記を理解した上で、SQL インジェクションをブロックする一般的なルールを記述するとすれば、以下のように記述できます。

**[SQL Injection]
AppliesTo=.asp,.aspx
DenyDataSection=SQL Injection Strings
ScanUrl=0
ScanAllRaw=0
ScanQueryString=1
ScanHeaders=
DenyUnescapedPercent=1

[SQL Injection Strings]
--
%3b ; セミコロン
/*
@ ; @@ もキャッチ
char ; nchar と varchar もキャッチ
alter
begin
cast
convert
create
cursor
declare
delete
drop
end
exec ; execute もキャッチ
fetch
insert
kill
open
select
sys ; sysobjects と syscolumns もキャッチ
table
update**

このルールを実行したいのは静的でないページだけなので、AppliesTo を使用して、このルールを適用するファイル拡張子の一覧を記述できます。この例では、このルールは、従来の ASP および ASP.NET 要求に対してのみ実行されます。関心がある部分はクエリ文字列と Cookie ヘッダーのみです。そして上記のスキャン オプションを設定して、そのことを示すことができます。[Sql Injection Strings] セクションでは、禁止するすべてのパターンを定義します。

しかし上述のルールでは、どのヘッダーもチェックされません。すべてのヘッダーをチェックする場合は、文字列一覧を調整して誤検知を減らす必要があります。短い文字列とセミコロンがたとえばセッション Cookie に出現し、有効な要求に失敗する可能性があります。また、すべてのヘッダーが関係するとは限りません。そのためヘッダーを、SQL インジェクションに実際に使用されるヘッダーだけに調整することになります。Cookie ヘッダーは、間違いなくこの対象になります。これに対応するために、以下のように、上述のルールを改良できます。

**[SQL Injection Headers]
AppliesTo=.asp,.aspx
DenyDataSection=SQL Injection Headers Strings
ScanUrl=0
ScanAllRaw=0
ScanQueryString=0
ScanHeaders=Cookie:

[SQL Injection Headers Strings]
--
@ ; @@ もキャッチ
alter
cast
convert
create
declare
delete
drop
exec ; execute もキャッチ
fetch
insert
kill
select**

URL とクエリ文字列のセーフ リストの作成

URLScan v3.1 を使用すると、すべてのチェックとルールをバイパスする安全な URL とクエリ文字列を指定できます。URLScan v3.0 では、URL またはクエリ文字列の各チェックをバイパスするだけですが、URLScan v3.1 では、すべてのチェックとルールをバイパスします。この機能は慎重に使用してください。このセクションで構成を間違えると、悪意のある要求によって拒否規則がバイパスされる可能性があるので慎重に使用してください。たとえば URL ‘/my.login.page.asp’ が、定義された拒否規則をトリガーする場合でも、ユーザーがこの URL を常に許可したい場合は、以下のように構成を追加して許可することができます。

**[AlwaysAllowedUrls]
/my.login.page.asp

URL が有効な URL として受け入れられるためには、先頭に ‘/’ が必要です。ユーザーがクエリ文字列 ‘session<1’ を許可したい場合は (許可しなければ定義された拒否規則がトリガーされます)、以下のように構成を追加して許可することができます。

**[AlwaysAllowedQueryStrings]
session<1

クエリ文字列の先頭に ‘?’を指定する必要はありません。

要求部分の上限の設定

ヘッダー値の長さの制限

[RequestLimits] セクションに、値 Max-<Header Name>=<N> を追加します。"Header Name" は、値の長さを制限する特定のヘッダーの名前です。"N" は、有効なヘッダーで指定できる最大バイト数です。"N" がゼロの場合は、特定のヘッダーは事実上許可されません。

たとえば、Content-Type ヘッダーの値が 100 バイトを超えないようにする場合、構成は次のようになります。

[RequestLimits]
Max-Content-Type=100

要求の最大コンテンツ長の制限

[RequestLimits] セクションで、値 MaxAllowedContentLength=<N> を追加します。"N" は、Content-Length ヘッダーで使用できる最大バイト数です。Content-Length ヘッダーの値よりも長いデータを送信すると、指定した長さ以降のデータは別の要求として解釈されます。

たとえば、1000 バイトより長いコンテンツ長を禁止する場合、構成は次のようになります。

[RequestLimits]
MaxAllowedContentLength=1000

URL の最大長の制限

[RequestLimits] セクションで、値 MaxUrl=<N> を追加します。"N" は、要求の URL で使用できる最大文字数です。

たとえば 100 文字より長い URL を禁止する場合、構成は次のようになります。

[RequestLimits]
MaxUrl=100

クエリ文字列の最大長の制限

[RequestLimits] セクションで、値 MaxQueryString=<N> を追加します。"N" は、URL のクエリ文字列で使用できる最大文字数です。

たとえば、100 文字より長いクエリ文字列を禁止する場合、構成は次のようになります。

[RequestLimits]
MaxQueryString=100

 

特定の種類の要求の禁止

許可された HTTP 動詞の許可一覧または拒否一覧の作成

許可一覧については、[AllowVerbs] セクションを作成し、許可する動詞の一覧を追加します。許可一覧では大文字と小文字が区別されます。拒否一覧の前に評価され、ルールの評価では拒否一覧のほうが優先されます。

たとえば、GET、HEAD、および POST 動詞のみを許可する場合、構成は次のようになります。

[AllowVerbs]
GET
HEAD
POST

拒否一覧については、[DenyVerbs] セクションを作成し、拒否する動詞の一覧を追加します。拒否一覧は、大文字と小文字が区別されません。

たとえば、WebDAV 動詞を禁止する場合、構成は次のようになります。

[DenyVerbs]
PROPFIND
PROPPATCH
MKCOL
DELETE
PUT
COPY
MOVE
LOCK
UNLOCK
OPTIONS
SEARCH

URI 拡張子の許可一覧または拒否一覧の作成

許可一覧については、[AllowExtension] セクションを作成し、許可する拡張子の一覧を追加します。許可一覧は大文字と小文字の区別がなく、拒否一覧の前に評価されます。

たとえば、.htm ファイルおよび .html ファイルのみの実行を許可する場合、構成は次のようになります。

**[AllowExtensions]
**.htm
.html

拒否一覧については、[DenyExtensions] セクションを作成し、拒否する拡張子の一覧を追加します。拒否一覧は、大文字と小文字が区別されません。

たとえば、要求で実行可能ファイルを拒否する場合、構成は次のようになります。

**[DenyExtensions]
.exe
.com
.bat
**.cmd

ヘッダーの拒否一覧の作成

ヘッダーの一覧を拒否するには、[DenyHeaders] セクションを作成し、拒否するヘッダーの一覧を追加します。拒否一覧は、大文字と小文字が区別されません。

たとえば、Transfer-Encoding ヘッダーのある要求を拒否する場合、構成は次のようになります。

[DenyHeaders]
Transfer-Encoding

URL シーケンスの拒否一覧の作成

すべての要求の URL シーケンスの一覧を拒否するには、[DenyUrlSequences] セクションを作成し、要求の URL で拒否する文字列の一覧を追加します。この拒否一覧は大文字と小文字の区別がなく、形式 %XX のエンコードされた値を指定できます (XX は 16 進数字)。

たとえば、".."、"./"、またはキャリッジ リターンとライン フィード (CRLF) シーケンスを持つ URL を拒否する場合、構成は次のようになります。

**[DenyUrlSequences]
..
./
%0D%0A

この一覧の最後にある %0D%0A にお気付きのことと思います。URLScan v3.1 を使用すると、シーケンスでエンコードされた値を指定できます。0x0D はキャリッジ リターン文字で 0x0A はライン フィード文字を表します。

クエリ文字列シーケンスの拒否一覧の作成

すべての要求のクエリ文字列シーケンスの一覧を拒否するには、[DenyQueryStringSequences] セクションを作成し、要求のクエリ文字列で拒否する文字列の一覧を追加します。この拒否一覧は大文字と小文字の区別がなく、形式 %XX のエンコードされた値を指定できます (XX は 16 進数字)。

たとえば、クエリ文字列で <script> タグを拒否し、山かっこの間の空白を許可する場合は、山かっこ文字を拒否することができます。構成は次のようになります。

[DenyQueryStringSequences]
<
>

このパターンのエスケープ バージョンとエスケープのないバージョンの両方をスキャンしたい場合があります。そのため、<script> シーケンスがエスケープされた http://www.foo.com/id=%3C%53%43%52%49%50%54%3E のような要求を送信する場合は、このクエリ文字列のエスケープのないバージョンもチェックします。これを行うには、[Options] セクションで UnescapeQueryString=1 を設定します。これは、クエリ文字列のパターンを 2 回チェックします。1 回は生のクエリ文字列に対して、もう 1 回はエスケープされていないクエリ文字列に対してです。

URLScan ログの使用

URLScan v3.1 では、ログ ファイルで W3C 形式が使用されるため、ユーザーは URLScan ログに対するクエリのように SQL を記述できます。これは、URLScan 構成の誤検知の分析に非常に便利です。

ログ専用モードの URLScan の構成

運用サーバーでは、実際に要求を失敗させることなく、特定の URLScan 構成の動作を確認できると便利です。この目的で、URLScan のログ専用モードを使用できます。これを設定するには、Urlscan.ini で次の構成変更を行います。

[Options]
RejectResponseUrl=/~*

RejectResponseUrl は、URLScan によってブロックされた URL にカスタム応答を送信するのに使用されます。ただし上述のように値が設定されている場合は、URLScan にログ専用モードに移行するように通知されます。ログ専用モードでは、URLScan は要求をブロックしませんが、ブロックされた場合の要求を記録します。

URLScan ログでの Log Parser の使用

URLScanv3.1 では W3C 形式のログを使用するため、ユーザーは Log Parser を使用してログ ファイルに対してクエリを実行できます。Log Parser には、その使用方法の情報が含まれている .chm ドキュメント ファイルが付属しています。このセクションでは、URLScan に特化したいくつかの例を示しますが、Log Parser でできることすべてに関してカバーするわけではありません。

ログで利用可能なデータ フィールドをすべて表示する場合は、次のコマンドを実行します。

LogParser –h –i:W3C <ログ ファイル名>

このコマンドは、<ログ ファイル名> で指定されたログ ファイルが W3C 入力形式であることを明確にし、クエリで利用できるフィールドの一覧を表示します。この出力例は次のとおりです。

Fields:
  LogFilename (S)      RowNumber (I)      Date (T)           Time (T)
  c-ip (S)             s-siteid (I)       cs-method (S)      cs-uri (S)
  x-action (S)         x-reason (S)       x-context (S)      cs-data (S)
  x-control (S)

サイト別の URLScan エラーの分析

サイトごとのエラー数を調べるクエリを発行する場合は、次のコマンドを発行できます。

LogParser.exe -i:W3C "SELECT s-siteid, COUNT(*) FROM mylogfile.log GROUP BY s-siteid"

このクエリは以下のような結果を示し、より多くの URLScan エラーが発生しているサイトを判断するのに使用できます。

s-siteid COUNT(ALL *)
-------- ------------
1        15
2        2087
-        2

原因別の URLScan エラーの分析

エラー原因の分布を取得するクエリを発行する場合は、次のコマンドを発行できます。

LogParser.exe -i:W3C "SELECT x-reason, COUNT(*) FROM mylogfile.log GROUP BY x-reason"

このクエリは以下のような結果を示し、ルールによる誤検知の分析に使用できます。

x-reason                          COUNT(ALL *)--------------------------------- ------------rule+'Rule1'+triggered            2090Invalid+config.+Error+0x8007000d. 2URL+too+long                      1query+string+too+long             1verb+not+allowed                  2disallowed+header                 2extension+not+allowed             3disallowed+query+string+sequence  2URL+is+double+escaped             1

悪意のあるクライアントに対応するための URLScan エラーの分析

クライアント IP アドレスに基づいてエラー分布を取得するクエリを発行する場合は、次のコマンドを発行できます。

**LogParser.exe -i:W3C "SELECT c-ip, COUNT(*) FROM mylogfile.log GROUP BY c-ip"

このクエリは以下のような結果を示し、悪意のあるクライアントの分析に使用できます。この後、IP 制限リストを使用して、このような悪意のあるクライアントをブロックできます。

c-ip         COUNT(ALL *)------------ ------------::1          151.2.3.4      1080.80.80.80  2077-            2

 

関連コンテンツ

記事