web-dev-qa-db-ja.com

URLのすべての文字を許可することが危険なのはなぜですか?

CodeIgniterの構成を確認すると、次の行が見つかりました。

$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';

そしてそれが言うドキュメント:

/*
|--------------------------------------------------------------------------
| Allowed URL Characters
|--------------------------------------------------------------------------
|
| This lets you specify which characters are permitted within your URLs.
| When someone tries to submit a URL with disallowed characters they will
| get a warning message.
|
| As a security measure you are STRONGLY encouraged to restrict URLs to
| as few characters as possible.  By default only these are allowed: a-z 0-9~%.:_-
|
| Leave blank to allow all characters -- but only if you are insane.
|
| The configured value is actually a regular expression character group
| and it will be executed as: ! preg_match('/^[<permitted_uri_chars>]+$/i
|
| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
|
*/

ただし、URL内のすべての文字を許可するために影響または安全性の懸念が存在する可能性があることは完全には明確ではありませんでした。

この問題を引き起こす可能性のある問題は何ですか?

4
Juan Pinzón

この方法で文字セットを制限すること(ホワイトリストとも呼ばれます)は、 入力検証 の推奨される方法の1つです。入力検証の目的は、意図しない問題を引き起こす可能性のあるデータに対してプログラムが実行されないようにすることです。

不正な形式のURLが原因で成功した攻撃が数多くあります(これらは実際の攻撃URLではなく、攻撃の代表です)。

  • ファイルパスインジェクション:_http://example.com/?C:\documents\top_secrets.txt_
  • バッファオーバーフロー:_http://example.com/aaaaaaaaaaaaaaaaaaaaaaaaa...aaaEvilShellCode_
  • スクリプトインジェクション:http://example.com/?<script>alert("Click me!")</script>
  • SQLインジェクション:_http://example.com/?USER=' or 1=1; select * from users_

これらの攻撃に対する最初の反応は、バックスラッシュ文字、引用符、アスタリスク、および小なり記号と大なり記号を禁止することでした。これはブラックリストと呼ばれます。残念ながら、ブラックリストは主に「攻撃について学習した後のパッチ」アプローチです。ホワイトリストはブラックリストよりもいくらか効果的です。ただし、URLに表示される文字を制限しても、 percent encoding を使用してすべてを回避できる場合、これらの攻撃の多くを防ぐために実質的に何もしない可能性があります。これにより、攻撃者は承認されたホワイトリストの文字のみを使用できます:%2Fは/などと同じです。

効果的にするには、CodeIgniterの正規表現は、パーセントエンコーディングがデコードされた後に実行する必要があります。また、単純に正規表現でデータをテストしながらバッファオーバーフローの問題を防ぐために、バリデーターの最初のステップは長さのチェックでなければなりません。

ホワイトリストを使用して防止しようとしている可能性のある別の問題があり、それは RLハイジャックnicode文字を使用してシミュレートするASCII文字 です。リンクをクリックするだけの人間にとって、文字列 "exampleZurichBank.com"と "exampleZuricⱨBank.com"は似ています。[AZ] [az]の範囲にないUnicode文字をブロックすると、これらを防ぐのに役立ちます。また、大きなセグメントの権利が奪われますネイティブアルファベットでURLをブロックすることにより、惑星の。

入力の検証は、まだ実装する必要がある多くの対策の1つにすぎないことに注意してください。アプリケーションは、XSS、CSRF、SQLインジェクション、セッションハイジャックなど、他の一般的な脆弱性から防御する必要があります。

3
John Deters

サーバーで実行されているすべてのコードがURLを適切に解析してエンコードし、ファイルシステムルックアップを作成するとき、データベースクエリに含めるとき、シェルコマンドに渡すときなどに、コードが考慮される時期に関して完全に一貫していると仮定した場合等しい文字列(たとえば、URLパーセントエンコーディング、大文字と小文字の区別、非ASCIIエンコーディング、Unicode正規化など)の場合、URLに文字を許可しても害はありません。

しかし、実行しているすべてのコードが完全に安全で一貫していることをどの程度確信していますか?

許可される文字のセットを減らすと、脆弱性の可能性が減ります。たとえば、sprintf("select where name = '%s'", url.param[1])などのURLの一部を直接挿入してSQLクエリを構築するコードがあるが、URLに'%27も含めることが許可されていない場合、これはSQLインジェクションの脆弱性が実際に悪用されることはありません。