ホームページ  >  記事  >  バックエンド開発  >  PHP WEBのセキュリティ問題

PHP WEBのセキュリティ問題

WBOY
WBOYオリジナル
2016-06-23 14:31:42933ブラウズ



ルール 1: 外部データや入力を決して信頼しない

Web アプリケーションのセキュリティについて最初に認識しなければならないことは、外部データを信頼すべきではないということです。外部データには、プログラマによって PHP コードに直接入力されないデータが含まれます。他のソースからのデータ (GET 変数、フォーム POST、データベース、構成ファイル、セッション変数、Cookie など) は、セキュリティを確保するための手順が講じられるまで信頼できません。

たとえば、次のデータ要素は PHP で設定されているため安全であると考えられます。


リスト 1. 安全で完璧なコード

$myUsername = 'tmyer';
$arrayUsers = array('tmyer', 'tom', 'tommy'); 'こんにちは' . $myUsername);
?> ただし、次のデータ要素にはすべて欠陥があります。

リスト 2. 安全でない欠陥のあるコード

$myUsername = $_POST['username'] //汚染されています!
$arrayUsers = array($myUsername, 'tom', 'tommy' ); /tainted!
define("GREETING", 'hello there' . $myUsername); //tainted!

最初の変数 $myUsername が間違っているのはなぜですか?これはフォーム POST から直接取得されるためです。ユーザーはこの入力フィールドに任意の文字列を入力できます。これには、ファイルを駆除したり、以前にアップロードしたファイルを実行したりする悪意のあるコマンドも含まれます。 「A ~ Z の文字のみを受け入れるクライアント側 (Javascript) フォーム検証スクリプトを使用すれば、この危険を回避できないのですか?」と疑問に思われるかもしれません。はい、これは常に有益なステップですが、後で説明するように、誰でもあらゆるフォームを自分のマシンにダウンロードし、変更して、必要なものを再送信できます。

解決策は簡単です。サニタイズコードは $_POST['username'] で実行する必要があります。これを行わないと、(配列や定数などで) $myUsername を使用するたびに、これらのオブジェクトが汚染される危険があります。

ユーザー入力をサニタイズする簡単な方法は、正規表現を使用して処理することです。この例では、文字のみが受け入れられることが想定されています。文字列を特定の文字数に制限したり、すべての文字を小文字にすることを要求したりすることも良いアイデアかもしれません。

リスト 3. ユーザー入力を安全にする

$myUsername = cleanInput($_POST['username']) //clean!
$arrayUsers = array($myUsername, 'tom', ' tommy' ); //クリーン!

function cleanInput($input){
$clean = preg_replace ("/[^a-z]/", "", $clean);
$clean = substr($clean,0,12);
?>


ルール 2: PHP を無効にするセキュリティの実装を困難にする設定

ユーザー入力を信頼できないことがわかったので、マシン上での PHP の構成方法も信頼すべきではないことも理解する必要があります。たとえば、register_globals が無効になっていることを確認してください。 register_globals が有効な場合、$variable を使用して GET または POST 文字列を同じ名前に置き換えるなどの不注意な行為が可能になります。この設定を無効にすると、PHP は正しい名前空間の正しい変数を参照するように強制します。フォーム POST から変数を使用するには、$_POST['variable'] を引用符で囲む必要があります。こうすることで、この特定の変数を Cookie、セッション、または GET 変数と間違えることがなくなります。


ルール 3: 理解できない場合、保護することはできません

一部の開発者は、奇妙な構文を使用したり、ステートメントを非常に厳密に編成して、短くても曖昧なコードを形成します。このアプローチは効率的かもしれませんが、コードが何をしているのかを理解していないと、コードを保護する方法を決定できません。

たとえば、次の 2 つのコードのうちどれが好きですか?

リスト 4. コードを保護しやすくする

//難読化されたコード
$input = (isset($_POST['username']) ? $_POST['username']:'');

//難読化されていないコード
$input = '';

if (isset($_POST['username'])){
$input = $_POST['username']
}else{
$input = ' ' ;
}
?>

2 番目のよりクリーンなコード スニペットでは、$input に欠陥があり、安全に処理する前にクリーンアップする必要があることが簡単にわかります。


ルール 4: 「多層防御」が新しい魔法です

このチュートリアルでは、フォームを処理する PHP コードで必要な措置を講じながら、オンライン フォームを保護する方法を例を使用して説明します。同様に、PHP 正規表現を使用して GET 変数が完全に数値であることを確認する場合でも、SQL クエリでエスケープされたユーザー入力が使用されることを確認する手順を実行できます。

多層防御は良いアイデアであるだけでなく、深刻な問題に巻き込まれないようにします。

基本的なルールについて説明したので、最初の脅威である SQL インジェクション攻撃を見てみましょう。



SQL インジェクション攻撃の防止

SQL インジェクション攻撃では、ユーザーはフォームまたは GET クエリ文字列を操作することでデータベース クエリに情報を追加します。たとえば、単純なログイン データベースがあるとします。このデータベースの各レコードには、ユーザー名フィールドとパスワード フィールドがあります。ユーザーがログインできるようにするログイン フォームを作成します。
リスト 5. 単純なログイン フォーム

ログイン</head> <br><form action="verify.php " Method="post"> <br> <br><label for='user'>ユーザー名</label> <br><input type='text' name='user' id='user'/> <br> <br> <br> <br> <br><label for='pw'>パスワード</label> <br><input type='password' name='pw' id='pw'/> <br> <br> <br><input type= ' submit' value='login'/> <br> <br> <br></form> <br></html> <br> <br> このフォームは、ユーザーが入力した内容を名前はファイル verify.php です。このファイルでは、PHP はログイン フォームからのデータを次のように処理します。 <br> <br>リスト 6. 安全でない PHP フォーム処理コード <br> <br><?php <br />$username = $_POST['user ']; <br /> $pw = $_POST['pw']; <br /> <br />$sql = "ユーザー名='".$username."' およびパスワード='" の制限 1 から count(*) を選択します。 "; <br /> <br />$result = mysql_query($sql); <br /> <br />while ($data = mysql_fetch_object($result)){ <br />if ($data->ctr == 1){ <br>//入力しても大丈夫ですアプリケーションです! login.php"); <br>} <br>?> <br> <br>このコードは問題ありませんね?このようなコードは、世界中の数百 (数千ではないにしても) の PHP/MySQL サイトで使用されています。どうしたの? 「ユーザー入力は信頼できない」ということを覚えておいてください。ここではユーザーからの情報はエスケープされないため、アプリケーションは脆弱なままになります。具体的には、あらゆる種類の SQL インジェクション攻撃が可能です。 <br> <br>たとえば、ユーザーがユーザー名として foo を入力し、パスワードとして ' または '1'='1 を入力すると、実際には次の文字列が PHP に渡され、クエリが MySQL に渡されます: <br> <br><?php <br /> $sql = "select count(*) as ctr from users where username='foo' and passwd='' or '1'='1' limit 1"; <br /> <br />このクエリは常にカウント値 1 を返します。 , したがって、PHP はアクセスを許可します。ハッカーは、パスワード文字列の末尾に悪意のある SQL を挿入することで、正規のユーザーになりすますことができます。 <br /> <br /> この問題の解決策は、PHP の組み込み mysql_real_escape_string() 関数をユーザー入力のラッパーとして使用することです。この関数は文字列内の文字をエスケープするため、文字列内でアポストロフィなどの特殊文字を渡すことができなくなり、MySQL が特殊文字に基づいて動作できるようになります。リスト 7 はエスケープされたコードを示しています。 <br /> <br />リスト 7. 安全な PHP フォーム処理コード <br /> <br /><?php <br />$okay = 0; <br />$username = $_POST['user'] <br /> <br />$ sql = "ユーザー名='".mysql_real_escape_string($username)."' およびパスワード='" から count(*) を CTR として選択します。mysql_real_escape_string($pw)."' 制限 1"; $sql); <br /> <br />while ($data = mysql_fetch_object($result)){ <br />if ($data->ctr == 1){ <br />//アプリケーションに入っても大丈夫です <br />$okay = 1 ; <br />} <br />} <br /> <br />if ($okay){ <br />$_SESSION['loginokay'] = true; <br />}else{ <br />header("login.php"); ?> <br> <br> ユーザー入力への悪意のある SQL インジェクションを回避するために、ユーザー入力のラッパーとして mysql_real_escape_string() を使用します。ユーザーが SQL インジェクション経由で不正なパスワードを渡そうとすると、次のクエリがデータベースに渡されます: <br> <br>select count(*) as ctr from users where username='foo' and passwd='' or '1'= '1' 制限 1" <br> <br>そのようなパスワードに一致するデータベースはありません。たった 1 つの簡単な手順を実行するだけで、Web アプリケーションの大きな穴が塞がれました。ここでの教訓は、常に SQL クエリを使用する必要があるということです。ユーザー入力はエスケープされます <br> <br>。ただし、塞がなければならないセキュリティ ホールがまだいくつかあります。次の項目は GET 変数の操作です。 <br> <br> <br> <br>ユーザーによる GET 変数の操作を防止する <br> <br> 前のセクションでは、ユーザーが不正なパスワードを使用してログインすることを防止しました。賢明な方であれば、これまでに学んだことを応用して、SQL ステートメントへのすべてのユーザー入力が確実にエスケープされるようにする必要があります。 <br> <br>ただし、ユーザーは現在安全にログインしています。ユーザーが有効なパスワードを持っているからといって、ルールに従って行動するわけではありません。損害を引き起こす可能性は数多くあります。たとえば、アプリケーションでは、ユーザーが特別なコンテンツを表示できるようにする場合があります。すべてのリンクは、template.php?pid=33 や template.php?pid=321 などの場所を指します。 URL の疑問符の後の部分はクエリ文字列と呼ばれます。クエリ文字列は URL に直接配置されるため、GET クエリ文字列とも呼ばれます。 <br> <br>PHP では、 register_globals が無効になっている場合、この文字列には $_GET['pid'] でアクセスできます。 template.php ページでは、リスト 8 と同様のことを行うことができます。 <br> <br>リスト 8. template.php の例 <br> <br><?php <br />$pid = $_GET['pid']; <br /> <br />//架空のクラス Page <br />$obj = new Page を作成します。 = $obj->fetchPage($pid); <br>//そして、ページを表示する大量の PHP ができました <br>?> ここで何が間違っているのでしょうか?まず、ブラウザからの GET 変数 pid は安全であると暗黙的に信頼されます。何が起こるか?ほとんどのユーザーはセマンティック攻撃を構築できるほど賢くありません。ただし、ブラウザの URL 場所フィールドに pid=33 があることに気付いた場合、問題が発生し始める可能性があります。別の数字を入力した場合はおそらく問題ありませんが、SQL コマンドやファイル名 (/etc/passwd など)、または 3,000 文字の長さの値などの他の何かを入力した場合はどうなりますか。 ? <br> <br>この場合、ユーザー入力を信用しないという基本的なルールを思い出してください。アプリケーション開発者は、template.php で受け入れられる個人識別子 (PID) が数値である必要があることを知っているため、以下に示すように、PHP の is_numeric() 関数を使用して、数値以外の PID が受け入れられないようにすることができます。 ) GET 変数を制限するには <br> <br><?php <br />$pid = $_GET['pid']; <br /> <br />if (is_numeric($pid)){ <br />//架空のクラス Page <br />$obj = のオブジェクトを作成しますnew Page; <br />$content = $obj->fetchPage($pid); <br>//これで、ページを表示する一連の PHP が完成しました <br>}else{ <br>// is_numeric() テストに合格しませんでした、何か他のことをしてください! <br>} <br>?> <br> <br>このメソッドは有効であるように見えますが、次の入力は is_numeric() チェックを簡単に通過できます: <br> <br>100 (有効) <br>100.1 (小数点以下の桁があってはなりません) <br>0123.45 e6 (科学的表記?? 悪い) <br>0xff33669f (16 進数?? 危険! 危険!) <br> <br>それでは、セキュリティを意識した PHP 開発者は何をすべきでしょうか?長年の経験から、以下に示すように、正規表現を使用して GET 変数全体が数値で構成されていることを確認するのがベスト プラクティスであることがわかっています。 <br> <br>リスト 10. 正規表現を使用して GET 変数を制限する <br> <br><?php <br />$pid = $ _GET['pid']; <br /> <br />if (strlen($pid)){ <br />if (!ereg("^[0-9] $",$pid){ <br />//ログ記録など、適切な処理を実行しますそれらを送信するか、ホームページに送り返します <br />} <br />}else{ <br />//$pid が空なので、ホームページに送り返します <br />} <br /> <br />//架空のクラス Page のオブジェクトを作成します。これは現在 <br /> です/ /悪意のあるユーザー入力から適度に保護されています <br />$obj = new Page; <br />$content = $obj->fetchPage($pid); これで、ページを表示する大量の PHP が完成しました <br>?> <br> 行う必要があるのは、strlen() を使用して変数の長さがゼロ以外であるかどうかを確認することだけです。そうであれば、完全な <br> <br> 正規表現を使用してデータ要素が有効であることを確認します。 PID に文字、スラッシュ、ピリオド、または 16 進数に類似したものが含まれている場合、このルーチンはそれを捕捉し、ユーザーのアクティビティからページをブロックします。 Page クラスの舞台裏を見ると、以下に示すように、セキュリティを意識した PHP 開発者がユーザー入力 $pid をエスケープし、それによって fetchPage() メソッドを保護していることがわかります。 ) エスケープするメソッド <br> <br><?php <br />class Page{ <br />function fetchPage($pid){ <br />$sql = "mysql_real_escape_string($ の場合、ページから pid、title、desc、kw、content、status を選択します)"。 pid)."'" <br />} <br />} <br /> <br />;「PID が数値であることがすでに確認されているのに、なぜエスケープする必要があるの?」と疑問に思われるかもしれません。なぜなら、 fetchPage() メソッドがどれだけ多くの異なるコンテキストや状況で使用されるかわからないからです。このメソッドが呼び出されるすべての場所で保護を提供する必要があり、メソッド内でのエスケープは多層防御の意味を具体化します。 <br /> <br /> ユーザーが最大 1000 文字などの非常に長い値を入力しようとして、バッファ オーバーフロー攻撃を開始しようとした場合はどうなりますか?次のセクションでこれについて詳しく説明しますが、ここでは別のチェックを追加して、入力 PID が正しい長さであることを確認できます。データベースの pid フィールドの最大長は 5 桁であることがわかっているため、次のチェックを追加できます。 <br /> <br />リスト 12. 正規表現と長さチェックを使用して GET 変数を制限する <br /> <br /><?php <br />$pid = $_GET['pid']; <br /> <br />if (strlen($pid)){ <br />if (!ereg ( "^[0-9] $",$pid) && strlen($pid) > <br>//ログアウトするかホームページに戻すなど、適切な処理を行います <br>} <br>} else { <br> // $pid が空なので、ホームページに送り返します <br>} <br>// 架空のクラス Page のオブジェクトを作成します。これで、 <br>// 悪意のあるユーザー入力からさらに保護されます <br>$obj = new Page <br>; $content = $obj->fetchPage($pid); <br>//これで、ページを表示する大量の PHP ができました <br>?> さて、データベース アプリケーションに 5,000 桁の値を組み込むことは誰にもできないでしょうか? ? 少なくとも GET 文字列は関係しません。アプリケーションに侵入しようとしてイライラしているハッカーが歯ぎしりしているところを想像してみてください。また、エラー報告がオフになっているため、ハッカーによる偵察が困難になります。 <br> <br> <br> <br>バッファ オーバーフロー攻撃 <br> <br>バッファ オーバーフロー攻撃 PHP アプリケーション (より正確には、Apache または基盤となるオペレーティング システム) でメモリ割り当てバッファをオーバーフローさせようとする試み。 Web アプリケーションを PHP などの高級言語で作成している可能性がありますが、最終的には C を呼び出していることに注意してください (Apache の場合)。ほとんどの低レベル言語と同様、C にはメモリ割り当てに関する厳密なルールがあります。 <br> <br>バッファ オーバーフロー攻撃は、大量のデータをバッファに送信し、データの一部を隣接するメモリ バッファにオーバーフローさせ、バッファを破壊したり、ロジックを書き換えたりします。これにより、サービス拒否、データの破損、またはリモート サーバー上で悪意のあるコードの実行が発生する可能性があります。 <br> <br> バッファ オーバーフロー攻撃を防ぐ唯一の方法は、すべてのユーザー入力の長さをチェックすることです。たとえば、ユーザー名を要求するフォーム要素がある場合、このフィールドに値 40 の maxlength 属性を追加し、バックエンドで substr() を使用して確認します。リスト 13 に、フォームと PHP コードの簡単な例を示します。 <br> <br>リスト 13. ユーザー入力の長さのチェック <br> <br><?php <br />if ($_POST['submit'] == "go"){ <br />$name = substr($_POST['name'],0, 40 ); <br />} <br />?> <br> <br><form action="<?php echo $_SERVER['PHP_SELF'];?>" <br> <br><label for=" " >名前</label> <br><input type="text" name="name" id="name" size="20" maxlength="40"/> <br> <br> <br> <br><input type=" submit " name="submit" value="go"/> <br> <br> <br></form> <br> <br>なぜ maxlength 属性を提供するだけでなく、バ​​ックエンドで substr() チェックも実行するのでしょうか?多層防御は常に有効だからです。ブラウザーは、PHP や MySQL が安全に処理できない非常に長い文字列 (誰かが最大 1,000 文字の長さの名前を入力しようとしているところを想像してください) をユーザーが入力することを防ぎ、バックエンド PHP チェックにより、誰もフォーム データをリモートまたはブラウザーで操作していないことを確認します。 。 <br> <br> ご覧のとおり、このアプローチは、前のセクションで strlen() を使用して GET 変数 pid の長さをチェックするのと似ています。この例では、5 桁を超える入力値は無視されますが、以下に示すように、値は適切な長さに簡単に切り詰められます。 <br> <br>リスト 14. 入力 GET 変数の長さの変更 <br> <br>< $pid = $_GET['pid']; <br /> <br />if (strlen($pid)){ <br />if (!ereg("^[0-9] $",$pid)){ <br />//数値以外の場合 $ pid、ホームページに送り返す <br />} <br />}else{ <br />//$pid が空なので、ホームページに送り返す <br />} <br /> <br />//数値の pid がありますが、長すぎる可能性があるので、 check <br />if (strlen($pid)>5){ <br />$pid = substr($pid,0,5); <br />} <br /> <br />//架空のクラス Page のオブジェクトを作成します。これは <br />//悪意のあるユーザー入力からさらに保護されます <br />$obj = new Page; <br />$content = $obj->fetchPage($pid); <br>//これで、ページを表示する大量の PHP が完成しました <br> <br> ;バッファ オーバーフロー攻撃は、数字や文字の長い文字列に限定されないことに注意してください。また、長い 16 進文字列 (xA3 や xFF のように見える) が表示される場合もあります。バッファ オーバーフロー攻撃の目的は、特定のバッファをフラッドし、悪意のあるコードや命令を次のバッファに配置し、それによってデータを破損したり、悪意のあるコードを実行したりすることであることに注意してください。 16 進バッファ オーバーフローに対処する最も簡単な方法は、入力が特定の長さを超えないようにすることです。 <br> <br> データベース内で長いエントリを許可するフォーム テキスト領域を扱っている場合、クライアント側でデータの長さを簡単に制限することはできません。データが PHP に到達したら、正規表現を使用して 16 進数のような文字列を消去できます。 <br> <br>リスト 15. 16 進文字列の禁止 <br> <br><?php <br />if ($_POST['submit'] == "go"){ <br />$name = substr($_POST['name'],0 ,40); <br />//潜在的な 16 進文字をすべて削除します <br />$name = cleanHex($name); <br />//処理を続行します.... <br />} <br /> <br />function cleanHex($input){ <br />$clean = preg_replace(" ![][ xX]([A-Fa-f0-9]{1,3})!", "",$input); <br />return $clean; <br />} <br />?> <br><form action=" <?php echo $_SERVER['PHP_SELF'];?>" method="post"> <br> <br><label for="name">名前</label> <br><input type="text" name="name " id="name" size="20" maxlength="40"/> <br> <br> <br> <br><input type="submit" name="submit" value="go"/> <br> <br> <br></ form> <br /> <br />この一連の操作は少し厳密すぎると思われるかもしれません。結局のところ、16 進文字列には、外国語で文字を印刷するなど、正当な用途があります。 16 進正規表現をどのように展開するかはあなた次第です。より良い戦略は、1 行に 16 進文字列が多すぎる場合、または文字列が特定の文字数 (128 や 255 など) を超える場合にのみ、16 進文字列を削除することです。 <br /> <br /> <br /> <br />クロスサイト スクリプティング攻撃<br /> <br /> クロスサイト スクリプティング (XSS) 攻撃では、多くの場合、悪意のあるユーザーが (または他のユーザー入力方法を通じて) フォームに情報を入力し、悪意のあるクライアント側のタグをプロセスまたはデータベース内で。たとえば、サイトに訪問者が名前、電子メール アドレス、簡単なメッセージを残せる簡単なゲストブック プログラムがあるとします。悪意のあるユーザーはこの機会を利用して、他のユーザーにとって不適切な画像や、ユーザーを別のサイトにリダイレクトする Javascript など、短いメッセージ以外の内容を挿入したり、Cookie 情報を盗んだりする可能性があります。 <br /> <br />幸いなことに、PHP には、HTML タグで囲まれたコンテンツを削除できるstrip_tags() 関数が用意されています。また、strip_tags() 関数を使用すると、 や など、許可されたタグのリストを提供することもできます。 <br /> <br />ブラウザ内データ操作 <br /> <br /> ユーザーがページ上のヘッダ要素やフォーム要素を改ざんできるようにするブラウザ プラグインの一種があります。 Mozilla プラグインである *****per Data を使用すると、多くの非表示のテキスト フィールドを持つ単純なフォームを操作して、PHP や MySQL に指示を送信することが簡単になります。 <br /> <br />ユーザーはフォームで [送信] をクリックする前に、データごとに ***** を開始できます。フォームを送信すると、フォーム データ フィールドのリストが表示されます。 *****per Data を使用すると、ブラウザがフォームの送信を完了する前に、ユーザーがこのデータを改ざんできます。 <br /> <br />前に作成した例に戻りましょう。文字列の長さがチェックされ、HTML タグが削除され、16 進文字が削除されました。ただし、以下に示すように、いくつかの隠しテキスト フィールドが追加されています。 <br /> <br />リスト 17. 隠し変数 <br /> <br /><?php <br />if ($_POST['submit'] == "go"){ <br />//strip_tags <br />$ name =trip_tags($_POST['name']); <br />$name = substr($name,0,40); <br />//潜在的な 16 進文字を削除します <br />$name = cleanHex($name);処理中.... <br />} <br /> <br />function cleanHex($input){ <br />$clean = preg_replace("![][xX]([A-Fa-f0-9]{1,3})!", "" ,$input); <br />return $clean; <br />?> <br><form action="<?php echo $_SERVER['PHP_SELF'];?>" ;label for="name">名前</label><input type="text" name="name" id="name" size="20" maxlength="40"/> ;input type="hidden" name="table" value="users"/> <br><input type="hidden" name="action" value="create"/> " name="ステータス" 値="ライブ"/> <br> <br><input type="submit" name="submit" value="go"/> <br> <br> <br></form> <br> <br> 隠し変数の 1 つがテーブル名を公開していることに注意してください。また、create の値を持つアクション フィールドも表示されます。基本的な SQL の経験がある人なら、これらのコマンドがおそらくミドルウェアの SQL エンジンを制御していることがわかります。大混乱を引き起こしたい人は、テーブル名を変更するか、削除などの別のオプションを提供するだけで済みます。 <br> <br>今残っている質問は何ですか?リモートフォーム送信。 <br> <br>リモートフォーム送信 <br> <br> Web の利点は、情報やサービスを共有できることです。欠点は、情報やサービスの共有です。何の躊躇もなく物事を行う人もいます。 <br> <br>フォームを例に挙げてみましょう。誰でも Web サイトにアクセスし、ブラウザ上で [ファイル] > [名前を付けて保存] を使用してフォームのローカル コピーを作成できます。次に、完全修飾 URL (フォームはこのサイトにあるため、formHandler.php ではなく、http://www.yoursite.com/formHandler.php) を指すようにアクション パラメーターを変更し、必要な操作を行うことができます。変更を行う場合は、「送信」をクリックすると、サーバーはこのフォーム データを法的な通信フローとして受信します。 <br> <br> まず、$_SERVER['HTTP_REFERER'] をチェックして、リクエストが自分のサーバーからのものであるかどうかを判断することを検討してください。この方法では、ほとんどの悪意のあるユーザーをブロックできますが、最も高度なハッカーをブロックすることはできません。これらの人々は、ヘッダー内の参照元情報を改ざんして、フォームのリモート コピーをサーバーから送信されたかのように見せかけるほど賢いのです。 <br> <br> リモート フォームの送信を処理するより良い方法は、一意の文字列またはタイムスタンプに基づいてトークンを生成し、このトークンをセッション変数とフォームに入れることです。フォームを送信した後、2 つのトークンが一致するかどうかを確認します。一致しない場合は、誰かがフォームのリモート コピーからデータを送信しようとしていることがわかります。 <br> <br>ランダム トークンを作成するには、以下に示すように、PHP の組み込み md5()、uniqid()、および rand() 関数を使用できます。 <br> <br>リスト 18. リモート フォーム送信に対する防御 <br> <br><?php <br />session_start () ; <br /> <br />if ($_POST['submit'] == "go"){ <br />//トークンをチェック <br />if ($_POST['token'] == $_SESSION['token']){ <br />//ストリップタグ <br /> $name = ストリップ_tags($_POST['name']); <br />$name = substr($name,0,40) <br />//潜在的な 16 進文字を削除します <br />$name = cleanHex($name); // 処理を続行します.... <br />}else{ <br />//すべてのリモートフォーム投稿の試行を停止します! <br />} <br />} <br />$token = md5(uniqid(rand(), true)); '] = $token; <br /> <br />function cleanHex($input){ <br />$clean = preg_replace("![][xX]([A-Fa-f0-9]{1,3})!", "", $input ); <br />return $clean; <br />?> <br><form action="<?php echo $_SERVER['PHP_SELF'];?>"ラベル = "name">名前</label><input type="text" name="name" id="name" size="20" maxlength="40"/> <br /> <br /> <br />< input type ="hidden" name="token" value="<?php echo $token;?>"/> <br> <br><input type="submit" name="submit" value="go"/ > <br> <br> <br></form> <br> <br>PHP ではセッション データをサーバー間で移行できないため、この手法は機能します。誰かがあなたの PHP ソース コードを取得し、それを自分のサーバーに移動し、あなたのサーバーに情報を送信したとしても、あなたのサーバーが受け取るのは、空の、または不正な形式のセッション トークンと、最初に提供されたフォーム トークンだけです。これらは一致しないため、リモート フォームの送信は失敗します。 <br> <br> <br> <br></p></div><div class="nphpQianMsg"><div class="clear"></div></div><div class="nphpQianSheng"><span>声明:</span><div>この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。</div></div></div><div class="nphpSytBox"><span>前の記事:<a class="dBlack" title="PHP および AJAX リクエスト" href="http://m.php.cn/ja/faq/265915.html">PHP および AJAX リクエスト</a></span><span>次の記事:<a class="dBlack" title="PHP および AJAX リクエスト" href="http://m.php.cn/ja/faq/265917.html">PHP および AJAX リクエスト</a></span></div><div class="nphpSytBox2"><div class="nphpZbktTitle"><h2>関連記事</h2><em><a href="http://m.php.cn/ja/article.html" class="bBlack"><i>続きを見る</i><b></b></a></em><div class="clear"></div></div><ins class="adsbygoogle" style="display:block" data-ad-format="fluid" data-ad-layout-key="-6t+ed+2i-1n-4w" data-ad-client="ca-pub-5902227090019525" data-ad-slot="8966999616"></ins><script> (adsbygoogle = window.adsbygoogle || []).push({}); </script><ul class="nphpXgwzList"><li><b></b><a href="http://m.php.cn/ja/faq/1.html" title="cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法" class="aBlack">cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法</a><div class="clear"></div></li><li><b></b><a href="http://m.php.cn/ja/faq/1.html" title="cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法" class="aBlack">cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法</a><div class="clear"></div></li><li><b></b><a href="http://m.php.cn/ja/faq/1.html" title="cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法" class="aBlack">cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法</a><div class="clear"></div></li><li><b></b><a href="http://m.php.cn/ja/faq/1.html" title="cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法" class="aBlack">cURL を使用して PHP で Get リクエストと Post リクエストを実装する方法</a><div class="clear"></div></li><li><b></b><a href="http://m.php.cn/ja/faq/2.html" title="正規表現内のすべての式記号 (概要)" class="aBlack">正規表現内のすべての式記号 (概要)</a><div class="clear"></div></li></ul></div></div><ins class="adsbygoogle" style="display:block" data-ad-format="autorelaxed" data-ad-client="ca-pub-5902227090019525" data-ad-slot="5027754603"></ins><script> (adsbygoogle = window.adsbygoogle || []).push({}); </script><footer><div class="footer"><div class="footertop"><img src="/static/imghwm/logo.png" alt=""><p>福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!</p></div><div class="footermid"><a href="http://m.php.cn/ja/about/us.html">私たちについて</a><a href="http://m.php.cn/ja/about/disclaimer.html">免責事項</a><a href="http://m.php.cn/ja/update/article_0_1.html">Sitemap</a></div><div class="footerbottom"><p> © php.cn All rights reserved </p></div></div></footer><script>isLogin = 0;</script><script type="text/javascript" src="/static/layui/layui.js"></script><script type="text/javascript" src="/static/js/global.js?4.9.47"></script></div><script src="https://vdse.bdstatic.com//search-video.v1.min.js"></script><link rel='stylesheet' id='_main-css' href='/static/css/viewer.min.css' type='text/css' media='all'/><script type='text/javascript' src='/static/js/viewer.min.js?1'></script><script type='text/javascript' src='/static/js/jquery-viewer.min.js'></script><script>jQuery.fn.wait = function (func, times, interval) { var _times = times || -1, //100次 _interval = interval || 20, //20毫秒每次 _self = this, _selector = this.selector, //选择器 _iIntervalID; //定时器id if( this.length ){ //如果已经获取到了,就直接执行函数 func && func.call(this); } else { _iIntervalID = setInterval(function() { if(!_times) { //是0就退出 clearInterval(_iIntervalID); } _times <= 0 || _times--; //如果是正数就 -- _self = $(_selector); //再次选择 if( _self.length ) { //判断是否取到 func && func.call(_self); clearInterval(_iIntervalID); } }, _interval); } return this; } $("table.syntaxhighlighter").wait(function() { $('table.syntaxhighlighter').append("<p class='cnblogs_code_footer'><span class='cnblogs_code_footer_icon'></span></p>"); }); $(document).on("click", ".cnblogs_code_footer",function(){ $(this).parents('table.syntaxhighlighter').css('display','inline-table');$(this).hide(); }); $('.nphpQianCont').viewer({navbar:true,title:false,toolbar:false,movable:false,viewed:function(){$('img').click(function(){$('.viewer-close').trigger('click');});}}); </script></body></html>