ホームページ > php教程 > php手册 > PHP アプリケーションのセキュリティ -- 違反してはいけない 4 つのセキュリティ ルール

PHP アプリケーションのセキュリティ -- 違反してはいけない 4 つのセキュリティ ルール

WBOY
リリース: 2016-06-13 12:36:18
オリジナル
940 人が閲覧しました

セキュリティが重要であることは誰もが知っていますが、業界の傾向は最後の瞬間までセキュリティを追加しないことです。 Web アプリケーションを完全に保護することは不可能なので、わざわざ心配する必要はありません。間違っている。いくつかの簡単な手順を実行するだけで、PHP Web アプリケーションのセキュリティを大幅に向上させることができます。




始める前に

このチュートリアルでは、PHP Web アプリケーションにセキュリティを追加する方法を学習します。このチュートリアルでは、PHP Web アプリケーションの作成経験が少なくとも 1 年あることを前提としているため、PHP 言語の基本的な知識 (規則または構文) についてはここでは説明しません。目的は、構築する Web アプリケーションを保護する方法についてのアイデアを提供することです。



目的
このチュートリアルでは、SQL インジェクション、GET および POST 変数の操作、バッファ オーバーフロー攻撃、クロスサイト スクリプティング攻撃などの最も一般的なセキュリティの脅威に対する防御方法を説明します。 - ブラウザ攻撃 データ操作とリモート フォーム送信。



前提条件
このチュートリアルは、少なくとも 1 年のプログラミング経験を持つ PHP 開発者を対象に書かれています。 PHP の構文と規則については理解する必要がありますが、ここでは説明しません。ここで説明するルールの多くは他の言語や環境にも適用されるため、Ruby、Python、Perl などの他の言語を使用した経験のある開発者もこのチュートリアルから恩恵を受けるでしょう。



システム要件

PHP V4 または V5 および MySQL を実行する環境が必要です。 Linux、OS X、または Microsoft Windows を使用できます。 Windows を使用している場合は、WAMPServer バイナリをダウンロードし、Apache、MySQL、および PHP をマシンにインストールします。




セキュリティの簡単な概要
Web アプリケーションの最も重要な部分は何ですか?誰が質問に答えるかによって、この質問に対する答えは異なる場合があります。ビジネスマンは信頼性と拡張性を必要としています。 IT サポート チームは、堅牢で保守可能なコードを必要としています。エンドユーザーは、タスクを実行する際に美しいユーザー インターフェイスと高いパフォーマンスを必要とします。ただし、答えが「セキュリティ」であれば、これが Web アプリケーションにとって重要であることに誰もが同意するでしょう。

しかし、ほとんどの議論はそこで止まります。セキュリティはプロジェクトのチェックリストに含まれていますが、多くの場合、プロジェクトが納品されるまで対処されません。このアプローチを採用している Web アプリケーション プロジェクトの数は驚異的です。開発者は何か月もかけて取り組み、最後にセキュリティ機能を追加して、Web アプリケーションを一般公開できるようにしました。

コードはセキュリティ機能が追加される前に検査され、単体テストされ、より大きなフレームワークに統合されているため、結果は混乱したり、再作業が必要になったりすることがよくあります。セキュリティを追加すると、主要なコンポーネントが動作しなくなる場合があります。セキュリティを統合すると、スムーズな (ただし安全ではない) プロセスに余分な負担やステップが追加されます。

このチュートリアルでは、セキュリティを PHP Web アプリケーションに統合するための優れた方法を提供します。ここでは、いくつかの一般的なセキュリティのトピックについて説明し、その後、主要なセキュリティの脆弱性とその解決方法について詳しく説明します。このチュートリアルを完了すると、セキュリティについてより深く理解できるようになります。



トピックには以下が含まれます:
SQL インジェクション攻撃
GET 文字列の操作
バッファ オーバーフロー攻撃
クロスサイト スクリプティング攻撃 (XSS)
ブラウザ データ操作
リモート フォーム送信




Web セキュリティ 101
セキュリティの実装の詳細について説明する前に、より高いレベルのアプリケーション セキュリティから Web について説明するのが最善です。このセクションでは、作成する Web アプリケーションの種類に関係なく、心に留めておくべきセキュリティ哲学の基本原則をいくつか紹介します。これらのアイデアの中には、Chris Shiflett (PHP セキュリティーに関する著書は貴重な宝庫です) から得たもの、Simson Garfinkel (「参考文献」を参照) から得たもの、そして長年蓄積された知識から得たものもあります。



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

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

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


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

$myUsername = 'tmyer'
$arrayUsers = array('tmyer', 'tom; ', 'tommy');
define("GREETING", 'hello there' . $myUsername);

ただし、次のデータ要素には欠陥があります。

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

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

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

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

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

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

$myUsername = cleanInput($_POST['username']) //clean! array($myUsername, 'tom', 'tommy'); //clean!
define("GREETING", 'hello there' . $myUsername);

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



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

確認する 2 番目の設定は、エラー報告レベルです。開発中はできるだけ多くのエラー レポートを取得したいと考えますが、プロジェクトを納品するときは、エラーを画面に表示するのではなくログ ファイルに記録したいと考えます。なぜ?悪意のあるハッカーは、エラー報告情報 (SQL エラーなど) を使用して、アプリケーションが何を行っているかを推測する可能性があるためです。この種の偵察は、ハッカーがアプリケーションに侵入するのに役立つ可能性があります。この脆弱性を解決するには、php.ini ファイルを編集して error_log エントリの適切な保存先を指定し、display_errors を Off に設定します。



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

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

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

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

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

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

if (isset($_POST['ユーザー名']) {
$input = $_POST['username'];
}else{
$input = '';
?>明確なコード スニペットでは、$input に欠陥があり、安全に処理する前にクリーンアップする必要があることが簡単にわかります。


ルール 4: 「多層防御」は新しい魔法の武器です

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

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

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




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

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

リスト 5. 簡単なログインフォーム


ログイン 🎜>


>




このフォームはユーザーからの入力を受け入れます名前とパスワードを入力し、ユーザー入力を verify.php という名前のファイルに送信します。このファイルでは、PHP はログイン フォームからのデータを次のように処理します。

リスト 6. 安全でない PHP フォーム処理コード

$okay = 0
$username = $_POST['user'];
$pw = $_POST['pw'];

$sql = "username =' のユーザーから count(*) を選択します。 $username."' とパスワード = '"。 $pw."' 制限 1"; )){
if ($data->ctr == 1){
//アプリケーションに入っても大丈夫です!
$okay = 1; }
}

if ($okay){
$_SESSION['loginokay'] = true;
header("index.php")
}else{
header ("login. php");
}
?>

このコードは問題ありませんね。世界中の数百 (数千ではないにしても) の PHP/MySQL サイトがこのようなコードを使用しています。何が問題なのでしょうか? 「ユーザー入力は信頼できない」ということを覚えておいてください。ここではユーザーからの情報はエスケープされないため、アプリケーションは脆弱なままになります。具体的には、あらゆる種類の SQL インジェクション攻撃が発生する可能性があります。

たとえば、ユーザーがユーザー名として foo を入力し、パスワードとして ' または '1'='1 を入力すると、実際には次の文字列が PHP に渡され、クエリが MySQL に渡されます。
$sql = "ユーザー名='foo' およびパスワード='' または '1'='1' 制限 1 のユーザーからカウント (*) を選択します
? >

このクエリは常にカウント 1 を返すため、PHP はアクセスを許可します。ハッカーは、パスワード文字列の末尾に悪意のある SQL を挿入することで、正規のユーザーになりすますことができます。

この問題の解決策は、PHP の組み込み mysql_real_escape_string() 関数をユーザー入力のラッパーとして使用することです。この関数は文字列内の文字をエスケープするため、文字列内でアポストロフィなどの特殊文字を渡すことができなくなり、MySQL が特殊文字を操作できるようになります。リスト 7 はエスケープされたコードを示しています。

リスト 7. セキュアな PHP フォーム処理コード

$okay = 0;
$username = $_POST['user']; pw = $_POST['pw'];

$sql = "username='".mysql_real_escape_string($username)." および mysql_real_escape_string のユーザーから ctr として選択します。 ($pw)."' 制限 1";

$result = mysql_query($sql);

while ($data = mysql_fetch_object($result)){
if ( $ data->ctr == 1){
{
$_SESSION['loginokay'] = true;
header("index.php");
header("login.php");
}
?>

ユーザー入力への悪意のある SQL インジェクションを回避するために、ユーザー入力のラッパーとして mysql_real_escape_string() を使用します。ユーザーが SQL インジェクションを介して不正なパスワードを渡そうとすると、次のクエリがデータベースに渡されます:

select count(*) as ctr from users where username='foo' and passwd='' または'1' ='1' 制限 1"

そのようなパスワードに一致するものはデータベース内にありません。簡単な 1 つの手順を実行するだけで、Web アプリケーションの大きな穴が塞がれました。ここで学んだ教訓は、SQL クエリに対するユーザー入力です。

ただし、次の項目は GET 変数の操作です。

前のセクションでは、ユーザーが不正なパスワードでログインできないようにしました。賢明であれば、学んだ方法を適用して、すべてのユーザー入力が確実に保護されるようにする必要があります。ユーザーが安全にログインしているからといって、ユーザーがルールに従って行動するわけではありません。アプリケーションでは、すべてのリンクがテンプレートのような場所を参照することを許可されている可能性があります。 php?pid=321。URL の疑問符の後の部分はクエリ文字列と呼ばれます。PHP では、register_globals が無効になっている場合、GET クエリ文字列とも呼ばれます。 $_GET['pid'] を使用して、template.php ページのこの文字列にアクセスします。リスト 8

リスト 8 と同様の操作を実行できます。 template.php

$pid = $_GET['pid'];

// 架空のクラス Page
$obj = new Page
$content = $obj-> を作成します。 fetchPage($pid);
//これで、ページ
?>



を表示することができました。ブラウザからの GET 変数 pid は安全であるという暗黙の信念がありますが、ほとんどのユーザーはセマンティック攻撃を構築するほど賢明ではありませんが、ブラウザの URL ロケーション フィールドに pid=33 があることに気づくと、攻撃を引き起こす可能性があります。トラブル。別の数字を入力した場合はおそらく問題ありませんが、SQL コマンドやファイル名 (/etc/passwd など)、または 3,000 文字の長さの値などの他のいたずらを入力した場合はどうなりますか。 ?

この場合、ユーザー入力を信用しないという基本的なルールを覚えておいてください。アプリケーション開発者は、template.php で受け入れられる個人識別子 (PID) が数値である必要があることを知っているため、以下に示すように、PHP の is_numeric() 関数を使用して、数値以外の PID が受け入れられないようにできます。 GET 変数を制限するには is_numeric() を使用します

$pid = $_GET['pid'];

if (is_numeric($pid)){
// 架空のクラス Page のオブジェクトを作成します
$obj = new Page
$content = $obj->fetchPage($pid); // これで、次のバッチが作成されました。ページを表示する PHP
}else{
// is_numeric() テストに合格しなかったので、何か他のことをしてください
}
?> このメソッドは次のようになります。有効ですが、次の入力は is_numeric() チェックに簡単に合格できます:

100 (有効)
100.1 (小数点以下の桁があってはなりません)
0123.45e6 (科学表記 - OK なし)
0xff33669f (16 進数 - 危険! 危険!)

それでは、セキュリティを重視する PHP 開発者は何をすべきでしょうか?長年の経験から、以下に示すように、正規表現を使用して GET 変数全体が数値で構成されていることを確認するのがベスト プラクティスであることがわかっています。

リスト 10. 正規表現を使用して GET 変数を制限する

< ;?php
$pid = $_GET['pid'];

if (strlen($pid)){
if (!ereg("^[0-9] $" , { ホームページ
}

//架空のクラス Page のオブジェクトを作成します。これは
//悪意のあるユーザー入力から適度に保護されています
$obj = new Page;
$content = $obj->fetchPage($pid);
//これで、ページ
?> を表示する PHP のバッチが完成しました。 use strlen () は、変数の長さがゼロ以外であるかどうかをチェックし、ゼロでない場合は、すべて数値の正規表現を使用してデータ要素が有効であることを確認します。 PID に文字、スラッシュ、ピリオド、または 16 進数に類似したものが含まれている場合、このルーチンはそれを捕捉し、ユーザーのアクティビティからページをブロックします。 Page クラスの舞台裏を見ると、以下に示すように、セキュリティを意識した PHP 開発者がユーザー入力 $pid をエスケープし、それによって fetchPage() メソッドを保護していることがわかります:

リスト 11。 fetchPage() メソッドをエスケープします。

class Page{
function fetchPage($pid){
$sql = "select pid,title,desc, kw,content, pid='".mysql_real_escape_string($pid)."'";
}
}
?>

「PID がすでに確認されているので、は数値ですが、なぜエスケープする必要があるのでしょうか? fetchPage() メソッドがどれだけ多くの異なるコンテキストや状況で使用されるかわからないからです。このメソッドが呼び出されるすべての場所で保護を提供する必要があり、メソッド内でのエスケープは多層防御の意味を具体化します。

ユーザーがバッファ オーバーフロー攻撃を開始しようとして、最大 1000 文字などの非常に長い値を入力しようとするとどうなりますか?次のセクションでこれについて詳しく説明しますが、ここでは別のチェックを追加して、入力 PID が正しい長さであることを確認できます。データベースの pid フィールドの最大長は 5 桁であることがわかっているため、次のチェックを追加できます。

リスト 12. 正規表現と長さチェックを使用して GET 変数を制限する

$pid = $_GET['pid'];

if (strlen($pid)){
if (!ereg("^[0-9] $",$pid) && strlen($pid) > 5){
// 適切な処理を行います。おそらくログアウトするか、ホームページに送り返すか
}
} else {
} // $pid が空なので、ホームページに送り返す
}
// を作成します架空のクラス Page のオブジェクト。
//悪意のあるユーザー入力からさらに保護されています
$obj = new Page;
$content = $obj->fetchPage($pid); 🎜> //そして、ページ
?> を表示する PHP のバッチができました。これで、データベース アプリケーションに 5,000 桁の値を詰め込むことは誰もできません - 少なくともまだこれは可能ですGET 文字列が関係する場合は起こりません。アプリケーションに侵入しようとしてイライラしているハッカーが歯ぎしりしているところを想像してみてください。また、エラー報告がオフになっているため、ハッカーによる偵察が困難になります。




バッファ オーバーフロー攻撃

バッファ オーバーフロー攻撃は、PHP アプリケーション (より正確には、Apache または基盤となるオペレーティング システム) に問題を起こそうとする試みです。 ) メモリ割り当てバッファ オーバーフローが発生しました。 Web アプリケーションを PHP などの高級言語で作成している場合でも、最終的には C を呼び出すことになる (Apache の場合) ことに注意してください。ほとんどの低レベル言語と同様、C にはメモリ割り当てに関する厳密なルールがあります。

バッファ オーバーフロー攻撃では、大量のデータがバッファに送信され、データの一部が隣接するメモリ バッファにオーバーフローして、バッファが破壊されたり、ロジックが書き換えられたりします。これにより、サービス拒否、データの破損、またはリモート サーバー上で悪意のあるコードの実行が発生する可能性があります。

バッファ オーバーフロー攻撃を防ぐ唯一の方法は、すべてのユーザー入力の長さをチェックすることです。たとえば、ユーザー名を必要とするフォーム要素がある場合、このフィールドに値 40 の maxlength 属性を追加し、バックエンドで substr() を使用してチェックします。リスト 13 に、フォームと PHP コードの簡単な例を示します。

リスト 13. ユーザー入力の長さのチェック

if ($_POST['submit'] == "go"){
$name = substr ($_POST['name'],0,40);
}
?



< ;/p>



なぜ maxlength 属性を提供するだけでなく、バ​​ックエンドで substr() チェックも実行するのでしょうか?多層防御は常に有効だからです。ブラウザは、PHP や MySQL が安全に処理できない非常に長い文字列 (誰かが 1,000 文字までの名前を入力しようとしているところを想像してください) をユーザーが入力することを防ぎ、バックエンド PHP チェックにより、誰もフォーム データをリモートまたはブラウザで操作していないことを確認します。

ご覧のとおり、このアプローチは、前のセクションで strlen() を使用して GET 変数 pid の長さをチェックするのと似ています。この例では、5 桁を超える入力値は無視されますが、以下に示すように、値は適切な長さに簡単に切り詰められます。

リスト 14. 入力 GET 変数の長さの変更

$pid = $_GET['pid'];

if (strlen($pid)){
if (!ereg("^[ 0-9 ] $",$pid)){
$pid、ホームページに戻ります
}

// 数値の PID がありますが、長すぎる可能性があるため、
if (strlen($pid)>5){
$pid = substr($pid,0,5);
}

// 架空のクラスのオブジェクトを作成しますページは現在
//悪意のあるユーザー入力からさらに保護されています
$obj = new Page;
$content = $obj->fetchPage($pid);
//ページ
?> を表示する大量の PHP があります。

バッファ オーバーフロー攻撃は、数字や文字の長い文字列に限定されないことに注意してください。また、長い 16 進文字列 (xA3 や xFF のように見える) が表示される場合もあります。バッファ オーバーフロー攻撃の目的は、特定のバッファをフラッドし、悪意のあるコードや命令を次のバッファに配置し、それによってデータを破損したり、悪意のあるコードを実行したりすることであることに注意してください。 16 進バッファ オーバーフローに対処する最も簡単な方法は、入力が特定の長さを超えないようにすることです。

データベース内で長いエントリを許可するフォーム テキスト領域を扱っている場合、クライアント側でデータの長さを簡単に制限する方法はありません。データが PHP に到着したら、正規表現を使用して 16 進数のような文字列をクリアできます。

リスト 15. 16 進文字列の禁止

if ($_POST['submit'] == "go"){
$name = substr($ _POST['name'],0,40);
//潜在的な 16 進文字を削除します
$name = cleanHex($name)
//処理を続行します。

function cleanHex($input){
$clean = preg_replace("![][xX]([A-Fa-f0-9]{1,3})!" , "", $input);
return $clean;
}
?>






この一連の操作は少し厳密すぎると思われるかもしれません。結局のところ、16 進文字列には、外国語で文字を印刷するなど、正当な用途があります。 16 進正規表現をどのように展開するかはあなた次第です。より良い戦略は、1 行に 16 進文字列が多すぎる場合、または文字列が特定の文字数 (128 や 255 など) を超えている場合にのみ 16 進文字列を削除することです。




クロスサイト スクリプティング攻撃

クロスサイト スクリプティング (XSS) 攻撃では、多くの場合、悪意のあるユーザーが何らかの形で (または他の方法を介して) 存在します。ユーザー入力メソッド ) 悪意のあるクライアント側タグをプロセスまたはデータベースに挿入する入力情報。たとえば、サイトに訪問者が名前、電子メール アドレス、簡単なメッセージを残せる簡単なゲストブック プログラムがあるとします。悪意のあるユーザーは、この機会を利用して、他のユーザーにとって不適切な画像や、ユーザーを別のサイトにリダイレクトする JavaScript など、短いメッセージ以外の何かを挿入したり、Cookie 情報を盗んだりする可能性があります。

幸いなことに、PHP には、HTML タグで囲まれたコンテンツを削除できるstrip_tags() 関数が用意されています。また、strip_tags() 関数を使用すると、 など、許可されるタグのリストを提供できます。

リスト 16 は、前の例を基にした例を示しています。

リスト 16. ユーザー入力から HTML タグを消去する

if ($_POST['submit'] == "go"){
//strip_tags
$name =trip_tags($_POST['name']);
$name = substr($name,0,40);
// 潜在的な 16 進文字を削除します
$name = cleanHex($name);
//処理を続行します....
}

function cleanHex($input){
$clean = preg_replace("![][xX] [A-Fa-f0-9]{1,3})!", "",$input);
return $clean;
}
?>





セキュリティの観点から、公開ユーザー入力でstrip_tags()を使用することが必要です。フォームが保護領域 (コンテンツ管理システムなど) にあり、ユーザーがタスク (Web サイトの HTML コンテンツの作成など) を正しく実行すると信頼している場合、strip_tags() の使用は不要であり、生産性に影響を与える可能性があります。

もう 1 つの質問: 投稿やゲスト登録項目に対するコメントなどのユーザー入力を受け入れ、この入力を他のユーザーに表示する必要がある場合は、応答を PHP の htmlspecialchars() に入れる必要があります。関数。この関数は、アンパサンド、< > 記号を HTML エンティティに変換します。たとえば、アンパサンド (&) は & になります。この場合、悪意のあるコンテンツがフロントエンドのstrip_tags()処理を逃れたとしても、バックエンドのhtmlspecialchars()によって処理されます。




ブラウザ内データ操作

ユーザーがページ上のヘッダー要素やフォーム要素を改ざんできるタイプのブラウザー プラグインがあります。 Mozilla プラグインである Tamper Data を使用すると、多くの隠しテキスト フィールドを持つ単純なフォームを簡単に操作して、PHP や MySQL にコマンドを送信できます。

ユーザーはフォームで [送信] をクリックする前に、データの改ざんを開始できます。フォームを送信すると、フォーム データ フィールドのリストが表示されます。データの改ざんを使用すると、ブラウザーがフォームの送信を完了する前に、ユーザーがこのデータを改ざんできます。

前に作成した例に戻りましょう。文字列の長さがチェックされ、HTML タグが削除され、16 進文字が削除されました。ただし、いくつかの隠しテキスト フィールドは次のように追加されます。

リスト 17. 隠し変数

if ($_POST['submit'] == " go") {
//strip_tags
$name =trip_tags($_POST['name']);
$name = substr($name,0,40);
//潜在的な 16 進数を削除します文字
$name = cleanHex($name);
//処理を続行します....
}

function cleanHex($input){
$clean = preg_replace(" ![][xX]([A-Fa-f0-9]{1,3})!", "",$input);
return $clean;
}
? >


<入力タイプ="hidden" name="table" value="users"/>




隠し変数の 1 つがテーブル名 users を公開していることに注意してください。値 create を持つアクション フィールドも表示されます。基本的な SQL の経験がある人なら、これらのコマンドがおそらくミドルウェアの SQL エンジンを制御していることがわかります。大混乱を引き起こしたい人は、テーブル名を変更するか、削除などの別のオプションを提供するだけで済みます。

図 1 は、タンパー データがもたらす可能性のある損害の範囲を示しています。データ改ざんにより、ユーザーはフォーム データ要素だけでなく、HTTP ヘッダーや Cookie にもアクセスできることに注意してください。

図 1. Tamper Data ウィンドウ


このツールを防御する最も簡単な方法は、どのユーザーも Tamper Data (または同様のツール) を使用できる可能性があると想定することです。システムがフォームを処理するために必要な最小限の情報のみを提供し、フォームを専用のロジックに送信します。たとえば、登録フォームは登録ロジックにのみ送信する必要があります。

共通のフォーム処理関数を構築し、多くのページがこの共通のロジックを使用している場合はどうなるでしょうか?隠し変数を使用してフローを制御するとどうなるでしょうか?たとえば、非表示のフォーム変数で、書き込むデータベース テーブルや使用するファイル リポジトリを指定できます。 4 つのオプションがあります:

何も変更せず、システム上に悪意のあるユーザーがいないことを祈ります。
非表示のフォーム変数の使用を避けるために、より安全な専用フォーム処理関数を使用するように関数を書き換えました。
md5() またはその他の暗号化メカニズムを使用して、隠しフォーム変数内のテーブル名またはその他の機密情報を暗号化します。 PHP 側でそれらを復号化することを忘れないでください。
略語やニックネームを使用して値の意味を曖昧にし、PHP フォーム処理関数でこれらの値を変換します。たとえば、users テーブルを参照したい場合は、u または任意の文字列 (u8y90x0jkL など) を使用して参照できます。
後の 2 つのオプションは完璧ではありませんが、ユーザーがミドルウェア ロジックやデータ モデルを簡単に推測するよりははるかに優れています。

今残っている質問は何ですか?リモートフォーム送信。




リモートフォーム送信

Web の利点は、情報やサービスを共有できることです。欠点は、情報やサービスの共有です。何の躊躇もなく物事を行う人もいます。

フォームを例に挙げます。誰でも Web サイトにアクセスし、ブラウザ上で [ファイル] > [名前を付けて保存] を使用してフォームのローカル コピーを作成できます。次に、完全修飾 URL (formHandler.php ではなく、フォームはこのサイトにあるため http://www.yoursite.com/formHandler.php) を指すようにアクション パラメーターを変更し、必要なことを実行できます。変更を行った場合は、「送信」をクリックすると、サーバーはこのフォーム データを法的な通信フローとして受信します。

まず、$_SERVER['HTTP_REFERER'] をチェックして、リクエストが自分のサーバーからのものであるかどうかを判断することを検討してください。この方法では、ほとんどの悪意のあるユーザーをブロックできますが、最も高度なハッカーをブロックすることはできません。これらの人々は、ヘッダー内の参照元情報を改ざんして、フォームのリモート コピーをサーバーから送信されたように見せかけるほど賢いのです。

リモート フォームの送信を処理するより良い方法は、一意の文字列またはタイムスタンプに基づいてトークンを生成し、このトークンをセッション変数とフォームに入れることです。フォームを送信した後、2 つのトークンが一致するかどうかを確認します。一致しない場合は、誰かがフォームのリモート コピーからデータを送信しようとしていることがわかります。

ランダム トークンを作成するには、以下に示すように、PHP の組み込み md5()、uniqid()、および rand() 関数を使用できます。

リスト 18. リモート フォーム送信に対する防御

session_start();

if ($_POST['submit'] == "go"){
//トークンをチェック
if ( $ _POST['token'] == $_SESSION['token']){
//strip_tags
$name = ストリップ_tags($_POST['name'])
$name = substr($ name ,0,40);
/すべてのリモートフォーム投稿の試行を停止します!
}
}
$token = md5(rand(), true); 🎜>$ _SESSION['token']= $token;

function cleanHex($input){
$clean = preg_replace("![][xX]([A-Fa-f0-9]{1 ,3})!", "", $input);
return $clean;
}
?>







このテクノロジーは事実上、PHP ではセッション データをサーバー間で移行できないためです。誰かがあなたの PHP ソース コードを取得し、それを自分のサーバーに移動し、あなたのサーバーに情報を送信したとしても、あなたのサーバーが受け取るのは、空の、または不正な形式のセッション トークンと、最初に提供されたフォーム トークンだけです。これらは一致しないため、リモート フォームの送信は失敗します。




結論

このチュートリアルでは多くの問題について説明しました:

SQL インジェクションの問題を防ぐには mysql_real_escape_string() を使用します。
正規表現と strlen() を使用して、GET データが改ざんされていないことを確認します。
正規表現と strlen() を使用して、ユーザーが送信したデータがメモリ バッファーをオーバーフローしないようにします。
strip_tags() と htmlspecialchars() を使用して、ユーザーが有害な可能性のある HTML タグを送信できないようにします。
Tamper Data などのツールによるシステムの侵害を防ぎます。
一意のトークンを使用して、ユーザーがリモートからサーバーにフォームを送信できないようにします。
このチュートリアルでは、ファイル インジェクション、HTTP ヘッダー スプーフィング、その他の脆弱性などのより高度なトピックについては説明しません。ただし、ここで学んだことは、現在のプロジェクトをより安全にするために十分なセキュリティをすぐに追加するのに役立ちます。




参考文献

学習
Zend.com で役立つ PHP 101 チュートリアルを見つけてください。
Chris Shiflett の『Essential PHP Security』のコピーを入手してください。彼が行う紹介は、このチュートリアルよりもはるかに詳細です。
Simson Garfinkel の『Web セキュリティ、プライバシー、コマース』のコピーを入手してください。
PHP セキュリティ コンソーシアムについて詳しくは、こちらをご覧ください。
「PHP セキュリティ上の間違いトップ 7」を読んでください。
developerWorks の「推奨される PHP 読書リスト」を確認してください。
developerWorks の記事「PHP の監査、パート 1: register_globals について」を読んでください。
PHP セキュリティ HOWTO ウェブキャストをご覧ください。
PHP の詳細については、IBM developerWorks の PHP プロジェクト リファレンスを参照してください。
developerWorks の技術イベントや Web キャストにご注目ください。
世界中の IBM オープンソース開発者向けの今後のカンファレンス、社内プレビュー、Web キャスト、その他のイベントについて学びます。
developerWorks のオープンソース ゾーンにアクセスしてください。オープンソース テクノロジーを使用した開発や IBM 製品での使用に役立つ、豊富なハウツー情報、ツール、プロジェクトの更新情報が含まれています。
ソフトウェア開発者間の興味深いインタビューやディスカッションを聞くには、developerWorks ポッドキャストを必ずチェックしてください。



製品とテクノロジーを入手
Windows ユーザーは WAMPServer をダウンロードできます。
PHP を使用して次の開発プロジェクトを構築します。
ダウンロードまたは DVD で入手できる IBM 試用版ソフトウェアを使用して、次のオープンソース開発プロジェクトを改善します。



ディスカッション
developerWorks ブログに参加して、developerWorks コミュニティに参加してください。




著者について
Thomas Myer は、情報アーキテクチャを専門とするテキサス州オースティンにある Web コンサルティング会社 Triple Dog Dare Media の創設者であり中心人物です。 Webアプリケーション開発とXMLコンサルティング。彼は、『No Nansense XML Web Development with PHP』 (SitePoint 発行) の著者です。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のおすすめ
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート