web-dev-qa-db-ja.com

フィルタリングせずにURLパラメーターにリダイレクトしても安全ですか?

Webページは、次のように、フィルタリングせずにパラメーターredirectで指定されたURLにリダイレクトします。

$newURL=$_GET["redirect"];
header('Location: '.$newURL);

login.php?redirect=home.php

それが入力をエコーする場合、XSS攻撃を実行することが可能であることがわかっていますが、それがヘッダーメソッドで使用されているときにコードを挿入できますか?これは安全なスクリプトですか?

8
Fast Snail

短い答え

いいえ、これは安全ではなく、実行すべきではありません。実際、これは OWASP Top 1 の最後の1つです。

A10。未検証のリダイレクトと転送

Webアプリケーションは頻繁にユーザーを他のページやWebサイトにリダイレクトして転送し、信頼できないデータを使用して宛先ページを決定します。適切な検証がなければ、攻撃者は被害者をフィッシングサイトやマルウェアサイトにリダイレクトしたり、転送を使用して不正なページにアクセスしたりできます。

マルウェアのフィッシングと拡散

攻撃者は任意のページにリダイレクトするURLを作成し、それをどこにでも拡散する可能性があります。

http://trusted.com/index.php?redirect=http%3A%2F%2Fmalicious.com

悪意のあるURLは、すべての文字をURLエンコードしてユーザーが検出できないように難読化され、%68%74%74%70%3A%2F%2F%6D%61%6C%69%63%69%6F%75%73%2E%63%6F%6Dのような文字列が得られます。

これで、ユーザーがサイトへの通常の安全なリンクのように見えるものをクリックすると、どこにでも移動する可能性があります。

  • あなたのサイトとまったく同じように見えるサイトで、ユーザー名とパスワードを尋ねます。ブーム、アカウントが盗まれた。
  • ドライブバイダウンロードによってマルウェアを拡散するサイト。これは技術的にはあなたのサイトがそれを広めているのではないので、これはあなたの問題ではないと主張することを試みることができます。被害者が同意するかどうかはわかりません。
  • 何でも。ユーザーがあなたのサイトへのリンクをクリックして、最終的に違法またはNSFWまたはNSFLコンテンツに到達することを望みますか?

ユーザーのログイン後にこれを行うと、質問で示唆したように、実際にページにログインして資格情報を入力すると、ユーザーが実際にサイトにいると信じるようになるため、さらに危険です。ログイン後に「間違ったパスワード、再試行」タイプのページを表示するのは簡単です。

ヘッダー挿入

Steffen Ullrichがこの質問に answer と私が this で別の質問に答えたときにすでに述べたように、PHP 5.1より古いバージョン) .2これはヘッダー挿入に使用できます。

代わりに何をすべきか

ホワイトリストまたは検証

多くの場合、解決策はホワイトリストに登録することです。 PHPの例:

$param = $_GET["redirect"];
$allowed = array(
    "index" => "index.php",
    "blog"  => "blog/index.php",
    // ...and so on...
);
$redirect = isset($allowed[$param]) ? $allowed[$param] : "index.php";
header('Location: '.$redirect);

リダイレクトしたいページがたくさんある場合、これは面倒です。 URLがどのように見えるかに応じて、自分のサイトのURLを検証できます。たとえば、それらがhttp://trutsted.com/?pageid=1234の形式になっている場合は、ページングされたものだけを受け入れてリダイレクトし、それが実際に数値であることを確認できます。

リファラーチェック

自分のサイト内からリダイレクトリンクのみを機能させたい場合は、リクエストのHTTPリファラーの見出しを確認できます。 HTTPページとHTTPSページの両方にリンクしている場合、リファラーヘッダーが送信されないため、HTTPとHTTPSの両方でサイトを提供している場合、これはいくつかの問題に遭遇する可能性があります。

ここにいくつかのサンプルコードがあります:

$headers = Apache_request_headers();
$referer = isset($headers['referer']) ? parse_url($headers['referer'], PHP_Host) : "";
if($referer == "trusted.com") {
    //Do the redirect. If you want your code to be safe on old PHP versions,
    //you will need to filter out newlines or just URL encode the URL.
}
else {
    //Inform the user of the problem or just redirect to your index page.
}

もっと読む

  • [〜#〜] owasp [〜#〜] 検証されていないリダイレクトに関するチートシート。 (ここでそれを行わない方法の例の1つは、質問でそれをどのようにしたかとほとんど同じです。)
  • トロイ・ハント はこのトピックについて素晴らしい作品を持っています。
10
Anders

現在のバージョンのPHPヘッダー関数での改行インジェクションの検出と防止、 HTTPヘッダーインジェクションを回避する方法(改行文字) を参照)バージョンpf PHPあなたはおそらく次のようなことをすることができます

 login.php?redirect=%0D%0A%0D%0A<script>...

ヘッダーから抜け出して、

 Location:

 <script>...

そして、スクリプトは、セッションハイジャックのためにセッションCookieにアクセスして転送するなど、必要なことをすべて実行できます。

これは、スクリプトが現在のPHPで安全であることを意味するものではありません。任意のURLへのリダイレクトは決して良い考えではないので、newURLをリダイレクトに期待するURLに制限する必要があります。

5
Steffen Ullrich

他の人が言ったことに追加するには:

リダイレクト先の一連の既知のURL(識別子にマップできる)がある場合、「リダイレクト」パラメーター値には既知の識別子のみを許可する方がはるかに優れています。次に、識別子を安全な既知のURLにマップできます。

このようなテクニックのおかげで、「すべての問題」が解消されます。

もちろん、URLの値がユーザーにとって100%任意である場合、またはすべての可能なURLのセットがない場合、これは適用できません。しかし、あなたのURLがあなたが制御している既知のページに対応しているなら、それのために進んでください!

2
niilzon

私が考えることができる最初の脆弱性は、ユーザーをサイトの偽のコピーにリダイレクトする引数として完全なURLを渡すことです(login.php?redirect=http://malicious.com

それ以外にも、リダイレクトが発生して悪意のあるHTML/JavaScriptが表示されるのを防ぐ方法はいくつかあると思います。

原則として、any URLパラメータはサニタイズする必要があります。

1
user7094