ホームページ > バックエンド開発 > PHPチュートリアル > PHP アプリケーションのセキュリティ、PHP アプリケーションのセキュリティ_PHP チュートリアル

PHP アプリケーションのセキュリティ、PHP アプリケーションのセキュリティ_PHP チュートリアル

WBOY
リリース: 2016-07-12 08:54:06
オリジナル
852 人が閲覧しました

PHP アプリケーションのセキュリティ、PHP アプリケーションのセキュリティ


開発中、インタビュー中、または技術的な議論中であっても、セキュリティについては深い理解と習熟が必要です。


目標

このチュートリアルの目標は、構築する Web アプリケーションを保護する方法を理解できるようにすることです。 SQL インジェクション、GET および POST 変数の操作、バッファ オーバーフロー攻撃、クロスサイト スクリプティング攻撃、ブラウザ内データ操作、リモート フォーム送信など、最も一般的なセキュリティの脅威から保護する方法を学びます。


セキュリティの簡単な紹介

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. 安全で完璧なコード

[php]$myUsername = 'tmyer';
$arrayUsers = array('tmyer', 'tom', 'tommy');
define("GREETING", 'hello there' . $myUsername); [/php]
ただし、次のデータ要素にはすべて欠陥があります。 、 リスト 2. 安全でない欠陥のあるコード

[PHP] $ myusername = $ _post ['username'] // 汚染されています
$ arrayusers = Array ($ myusername, 'tom', 'tommy'); !
define("GREETING", 'hello there' . $myUsername); //tainted! [/php]
最初の変数 $myUsername が間違っているのはなぜですか?これはフォーム POST から直接取得されるためです。ユーザーはこの入力フィールドに任意の文字列を入力できます。これには、ファイルを駆除したり、以前にアップロードしたファイルを実行したりする悪意のあるコマンドも含まれます。 「A ~ Z の文字のみを受け入れるクライアント側 (JavaScript) フォーム検証スクリプトを使用すれば、この危険を回避できないのですか?」と疑問に思われるかもしれません。はい、これは常に有益なステップですが、後で説明するように、誰でもあらゆるフォームを自分のマシンにダウンロードし、変更して、必要なものを再送信できます。
解決策は簡単です。サニタイズコードは $_POST['username'] で実行する必要があります。これを行わないと、(配列や定数などで) $myUsername を使用するたびに、これらのオブジェクトが汚染される危険があります。
ユーザー入力をサニタイズする簡単な方法は、正規表現を使用して処理することです。この例では、文字のみが受け入れられることが想定されています。文字列を特定の文字数に制限したり、すべての文字を小文字にすることを要求したりすることも良いアイデアかもしれません。
リスト 3. ユーザー入力を安全にする
リスト$arrayUsers = array($myUsername, 'tom', 'tommy'); //clean!
define("GREETING", 'こんにちは' . $myUsername); $clean = strto lower($input);
$clean = preg_replace(”/[^a-z]/”, “”, $clean);
$clean = substr($clean,0,12);
return $clean;
}[/php]
ルール 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 = ”;
if (isset( $_POST['ユーザー名'])){
$input = $_POST['ユーザー名'];
}else{
$ input = ”;
}[/php]
2 番目の明確なコード スニペットでは、$input に欠陥があり、安全に処理する前にクリーンアップする必要があることが簡単にわかります
ルール 4: 「多層防御」新しい魔法の武器
このチュートリアルでは、フォームを処理する PHP コードで必要な措置を講じながらオンライン フォームを保護する方法を説明する例を示します。同様に、GET 変数が完全に数値であることを確認するために PHP 正規表現を使用する場合でも、 SQL クエリがエスケープされたユーザー入力を使用するようにするための措置を講じることもできます
多層防御は良いアイデアであるだけでなく、深刻な問題に巻き込まれないようにするための手段です
基本的なルールについて説明したので、見てみましょう。最初の脅威: SQL インジェクション攻撃


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

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







< /form>

[/php]
このフォームは、ユーザーが入力したユーザー名とパスワードを受け入れ、ユーザー入力を verify.php という名前のファイルに送信します。このファイルでは、PHP は以下に示すようにログイン フォームからのデータを処理します。
リスト 6. 安全でない PHP フォーム処理コード
'user'];
$pw = $_POST['pw'];
$sql = "選択count(*) をユーザーの CTR として使用します where
username='".$username."' およびpassword='". $ pw."' 制限 1'';

$result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){
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 = “select count( *) as ctr from users where username='foo' and passwd=” or '1'='1' limit 1''; このクエリは常に 1 のカウントを返すため、PHP はパスワード文字を挿入することでアクセスを許可します。文字列の末尾に悪意のある SQL が含まれている場合、ハッカーは正規のユーザーになりすますことができます。この問題の解決策は、PHP の組み込み mysql_real_escape_string() 関数をユーザー入力のラッパーとして使用することです。これにより、文字がエスケープされなくなります。
リスト 7. 安全な PHP フォーム処理コード
[php ]$okay = 0;
$username = $_POST['user '];
$pw = $_POST['pw'];
$sql = “
username='".mysql_real_escape_string($username)."'
およびpassword='"のユーザーからctrとしてcount(*)を選択します。 .mysql_real_escape_string($pw)."' 制限 1'';

$result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){
if ($data->ctr == 1) {
//アプリケーションに入っても問題ありません!
$okay = 1;
}
}
if ($okay){
$_SESSION['loginokay'] = true;
header("index.php") ;
}else{
header("login.php");
}
?>[/php]

mysql_real_escape_string( ) は、ユーザー入力への悪意のある SQL インジェクションを回避するためにユーザー入力のラッパーとして機能します。ユーザーが SQL インジェクション経由で不正なパスワードを渡そうとすると、次のクエリがデータベースに渡されます:
select count(*) as ctr from users where
username='foo' and passwd='' or '1'='1 「制限 1」
そのようなパスワードに一致するものはデータベース内にありません。たった 1 つの簡単な手順で、Web アプリケーションの大きな穴を塞ぐことができました。ここでの経験則は、SQL クエリのユーザー入力は常にエスケープする必要があるということです。
ただし、塞がなければならないセキュリティ ホールがまだいくつかあります。次の項目は、GET 変数を操作することです。


ユーザーによる変数の操作を防止する


前のセクションでは、ユーザーが不正なパスワードを使用してログインすることを防止しました。賢明な方であれば、学んだことを応用して、SQL ステートメントへのすべてのユーザー入力が確実にエスケープされるようにする必要があります。 ただし、ユーザーは安全にログインしています。ユーザーが有効なパスワードを持っているからといって、そのユーザーがルールに従って行動するわけではありません。ユーザーが損害を与える可能性は数多くあります。たとえば、アプリケーションでは、ユーザーが特別なコンテンツを表示できるようにする場合があります。すべてのリンクは、template.php?pid=33 や template.php?pid=321 などの場所を指します。 URL の疑問符の後の部分はクエリ文字列と呼ばれます。クエリ文字列は URL に直接配置されるため、GET クエリ文字列とも呼ばれます。 PHP では、 register_globals が無効になっている場合、この文字列には $_GET['pid'] でアクセスできます。 template.php ページでは、リスト 8 と同様のことを行うことができます。リスト 8. template.php の例
content = $obj->fetchPage($pid);
//これで、ページを表示する一連の PHP が完成しました
//…
//…
?> [ /php]
ここで何か問題がありますか?まず、ブラウザからの GET 変数 pid は安全であると暗黙的に信頼されます。何が起こるか?ほとんどのユーザーはセマンティック攻撃を構築できるほど賢くありません。ただし、ブラウザの URL 場所フィールドに pid=33 があることに気付いた場合、問題が発生し始める可能性があります。別の数字を入力した場合はおそらく問題ありませんが、SQL コマンドやファイル名 (/etc/passwd など) など、他の何かを入力した場合、または 3,000 と入力するなどのトリックがあった場合は、文字の値、どうなりますか?
この場合、ユーザー入力を信用しないという基本的なルールを思い出してください。アプリケーション開発者は、template.php で受け入れられる個人識別子 (PID) が数値である必要があることを知っているため、以下に示すように、PHP の is_numeric() 関数を使用して、数値以外の PID が受け入れられないようにできます。 GET 変数を制限する
new Page;
$content = $obj->fetchPage($pid);
//これで、ページを表示する一連の PHP が完成しました
//…
//…
}その他{
// is_numeric() テストに合格しませんでした。他のことをしてください!
}?> [/php]
このメソッドは有効のようですが、次の入力は is_numeric() チェックに簡単に合格できます:
100 (有効)
100.1 (小数点以下の桁があってはなりません)
+0123.45e6 (科学的表記 – 悪い)
0xff33669f (16 進数 – 危険! 危険!)
では、セキュリティを重視する PHP 開発者は何をすべきでしょうか?長年の経験から、以下に示すように、正規表現を使用して GET 変数全体が数値で構成されていることを確認するのが最善の方法であることがわかっています。
リスト 10. 正規表現を使用して GET 変数を制限する
[php] & lt;?
$ pid = $_GET['pid'];

if (strlen($pid)){
if (!ereg("^[0-9]+$",$pid)){
//ログアウトするか、ホームページに送り返すなど、適切な処理をしてください
}
}else{
//$pid が空なので、ホームページに送り返してください
}

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

[php]class Page{
function fetchPage($pid){
$sql = “select pid,title,desc,kw,content,
status from page where pid='
” .mysql_real_escape_string($pid).”'”;
//etc, etc….

}
}
?> [/php]
「PID が数値であることは確認したのに、なぜ? エスケープする必要がありますか?」 fetchPage() メソッドがどれほど多くの異なるコンテキストや状況で使用されるかわからないからです。このメソッドが呼び出されるすべての場所で保護を提供する必要があり、メソッド内でのエスケープは多層防御の意味を具体化します。
ユーザーがバッファ オーバーフロー攻撃を開始しようとして、最大 1000 文字などの非常に長い値を入力しようとするとどうなりますか?次のセクションでこれについて詳しく説明しますが、ここでは別のチェックを追加して、入力 PID が正しい長さであることを確認できます。データベースの pid フィールドの最大長は 5 桁であることがわかっているため、次のチェックを追加できます。
リスト 12. 正規表現と長さチェックを使用して GET 変数を制限する

[php]$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 が完成しました
//… …
//…
?> [/php]
現在では、少なくとも GET 文字列が関係するデータベース アプリケーションに 5,000 桁の値を詰め込むことはできません。ハッカーがアプリケーションに侵入しようとしてイライラして歯ぎしりしているところを想像してみてください。また、エラー報告がオフになっているため、ハッカーによる偵察が困難になります。

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

バッファ オーバーフロー攻撃 PHP アプリケーション (より正確には、Apache または基盤となるオペレーティング システム) でメモリ割り当てバッファをオーバーフローさせようとする試み。 Web アプリケーションを PHP などの高級言語で作成している可能性がありますが、最終的には C を呼び出していることに注意してください (Apache の場合)。ほとんどの低レベル言語と同様、C にはメモリ割り当てに関する厳密なルールがあります。
バッファ オーバーフロー攻撃は、大量のデータをバッファに送信し、データの一部を隣接するメモリ バッファにオーバーフローさせ、バッファを破壊したりロジックを書き換えたりします。これにより、サービス拒否、データの破損、またはリモート サーバー上で悪意のあるコードの実行が発生する可能性があります。
バッファ オーバーフロー攻撃を防ぐ唯一の方法は、すべてのユーザー入力の長さをチェックすることです。たとえば、ユーザー名を要求するフォーム要素がある場合、このフィールドに値 40 の maxlength 属性を追加し、バックエンドで substr() を使用して確認します。リスト 13 に、フォームと PHP コードの簡単な例を示します。
リスト13.ユーザー入力の長さをチェック、40);
//処理を続行する…。 ?>” Method=”post”>


”name” id=”name ” size=”20″ maxlength=”40″/ >



[/php]

なぜ maxlength 属性を指定し、バックエンドで substr() チェックを行うのでしょうか?多層防御は常に有効だからです。ブラウザーは、PHP や MySQL が安全に処理できない非常に長い文字列 (誰かが最大 1,000 文字の名前を入力しようとしているところを想像してください) をユーザーが入力することを防ぎ、バックエンド PHP チェックにより、誰もフォーム データをリモートまたはブラウザーで操作していないことを確認します。 。
ご覧のとおり、このアプローチは、前のセクションで strlen() を使用して GET 変数 pid の長さをチェックするのと似ています。この例では、5 桁を超える入力値は無視されますが、以下に示すように、値は適切な長さに簡単に切り詰められます。 php
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg("^[0-9]+$",$pid)){
/ /if non数値の $pid、ホームページに送り返す
}
}else{
//$pid が空なので、ホームページに送り返す
}
//数値の pid がありますが、長すぎる可能性がありますので、確認してみましょう
if (strlen($pid)>5){
$pid = substr($pid,0,5);
}
//架空のクラス Page のオブジェクトを作成します。これは現在
//悪意のあるユーザー入力からさらに保護されます
$obj = new Page;
$content = $obj->fetchPage($pid);
//これで、ページを表示する一連の PHP が完成しました
// …
/ /…
?>[/php]

バッファ オーバーフロー攻撃は、数字や文字の長い文字列に限定されないことに注意してください。また、長い 16 進文字列 (xA3 や xFF のように見える) が表示される場合もあります。バッファ オーバーフロー攻撃の目的は、特定のバッファをフラッディングし、悪意のあるコードや命令を次のバッファに配置し、それによってデータを破損したり、悪意のあるコードを実行したりすることであることに注意してください。 16 進バッファ オーバーフローに対処する最も簡単な方法は、入力が特定の長さを超えないようにすることです。
データベース内で長いエントリを許可するフォームのテキスト領域を扱っている場合、クライアント側でデータの長さを簡単に制限する方法はありません。データが PHP に到達したら、正規表現を使用して 16 進数のような文字列を消去できます。
リスト 15. 16 進文字列の防止
, 0,40);
//潜在的な 16 進文字をすべて削除します
$name = cleanHex($name);
//処理を続行します….
}
function cleanHex($input){
$clean = preg_replace("![][xX]([A-Fa-f0-9]{1,3})!", "",$input);
return $clean;
}
?>
” method=”post”>



< p>


[/php]

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

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

クロスサイト スクリプティング (XSS) 攻撃では、多くの場合、悪意のあるユーザーが (または他のユーザー入力方法を通じて) フォームに情報を入力し、悪意のあるクライアント側タグをフォームに挿入します。プロセスまたはデータベース内で。たとえば、サイトに訪問者が名前、電子メール アドレス、簡単なメッセージを残せる簡単なゲストブック プログラムがあるとします。悪意のあるユーザーはこの機会を利用して、他のユーザーにとって不適切な画像や、ユーザーを別のサイトにリダイレクトする JavaScript など、短いメッセージ以外のものを挿入したり、Cookie 情報を盗んだりする可能性があります。
幸いなことに、PHP には、HTML タグで囲まれたコンテンツを削除できるstrip_tags() 関数が用意されています。また、strip_tags() 関数を使用すると、 など、許可されるタグのリストを提供できます。
リスト 16 は、前の例を基にした例を示しています。用户 リスト 16. ユーザー入力から HTML マークをクリアします

[php] & lt ;? php
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 ;
}
?>
” method=”post”>


”text” name=”name” id=”name” size=”20″ maxlength=”40″/>


< p


[/php]
セキュリティの観点から、一般ユーザー向けinput ストリップタグ()を使用する必要があります。フォームが保護領域 (コンテンツ管理システムなど) にあり、ユーザーがタスク (Web サイトの HTML コンテンツの作成など) を正しく実行することを信頼している場合、strip_tags() の使用は不要であり、生産性に影響を与える可能性があります。
もう 1 つの質問: 投稿やゲスト登録エントリへのコメントなどのユーザー入力を受け入れ、この入力を他のユーザーに表示する必要がある場合は、必ず応答を PHP の htmlspecialchars() 関数に入れてください。この関数は、アンパサンド、< > 記号を HTML エンティティに変換します。たとえば、アンパサンド (&) は & になります。この場合、悪意のあるコンテンツがフロントエンドのstrip_tags()の処理を逃れたとしても、バックエンドのhtmlspecialchars()によって処理されます。


ブラウザ内データ操作
ユーザーがページ上のヘッダー要素やフォーム要素を改ざんできるようにするブラウザー プラグインのクラスがあります。 Mozilla プラグインである Tamper Data を使用すると、多くの非表示のテキスト フィールドを持つ単純なフォームを簡単に操作して、PHP や MySQL に指示を送信できます。
ユーザーがフォームで「送信」をクリックする前に、データ改ざんを開始できます。フォームを送信すると、フォーム データ フィールドのリストが表示されます。データの改ざんを使用すると、ブラウザーがフォームの送信を完了する前に、ユーザーがこのデータを改ざんできます。
前に作成した例に戻りましょう。文字列の長さがチェックされ、HTML タグが削除され、16 進文字が削除されました。ただし、以下に示すように、いくつかの隠しテキスト フィールドが追加されます。
リスト 17. 隠し変数

[php]if ($_POST['submit'] == "go"){
//strip_tags
$name = ストリップ_タグ($_POST['名前']);
$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;
}
?>
” method=”post”>







[/php]
注、隠し変数の 1 つがテーブル名 users を公開します。また、create という値を持つアクション フィールドも表示されます。基本的な SQL の経験がある人なら、これらのコマンドがおそらくミドルウェアの SQL エンジンを制御していることがわかります。大混乱を引き起こしたい人は、テーブル名を変更するか、削除などの別のオプションを提供するだけで済みます。
図 1 は、改ざんデータがもたらす可能性のある損害の範囲を示しています。データ改ざんにより、ユーザーはフォーム データ要素だけでなく、HTTP ヘッダーや Cookie にもアクセスできることに注意してください。

図 1. Tamper Data ウィンドウ


このツールを防御する最も簡単な方法は、どのユーザーも Tamper Data (または同様のツール) を使用できると想定することです。システムがフォームを処理するために必要な最小限の情報のみを提供し、フォームを専用のロジックに送信します。たとえば、登録フォームは登録ロジックにのみ送信する必要があります。
共通のフォーム処理関数を構築し、多くのページがこの共通ロジックを使用している場合はどうなるでしょうか?隠し変数を使用してフローを制御するとどうなるでしょうか?たとえば、非表示のフォーム変数で、書き込むデータベース テーブルや使用するファイル リポジトリを指定できます。オプションは 4 つあります:
何も変更せず、システムに悪意のあるユーザーがいないことを密かに祈ります。
より安全な専用フォーム処理関数を使用し、非表示のフォーム変数の使用を回避するように関数を書き換えます。
md5() またはその他の暗号化メカニズムを使用して、隠しフォーム変数内のテーブル名またはその他の機密情報を暗号化します。 PHP 側で復号化することを忘れないでください。
略語やニックネームを使用して値の意味を曖昧にし、PHP フォーム処理関数でこれらの値を変換します。たとえば、users テーブルを参照したい場合は、u または任意の文字列 (u8y90×0jkL など) を使用して参照できます。
後の 2 つのオプションは完璧ではありませんが、ユーザーがミドルウェア ロジックやデータ モデルを簡単に推測するよりははるかに優れています。
今残っている質問は何ですか?リモートフォーム送信。

リモートフォーム送信

Web の利点は、情報やサービスを共有できることです。欠点は、情報やサービスの共有です。何の躊躇もなく物事を行う人もいます。
フォームを例に挙げてみましょう。誰でも Web サイトにアクセスし、ブラウザ上で [ファイル] > [名前を付けて保存] を使用してフォームのローカル コピーを作成できます。次に、完全修飾 URL (formHandler.php ではなく、フォームはこのサイトにあるため http://www.yoursite.com/formHandler.php) を指すようにアクション パラメーターを変更し、必要な操作を行うことができます。変更を加えて [送信] をクリックすると、サーバーはこのフォーム データを法的な通信フローとして受信します。
まず、$_SERVER['HTTP_REFERER'] をチェックして、リクエストが自分のサーバーからのものであるかどうかを判断することを検討してください。この方法では、ほとんどの悪意のあるユーザーをブロックできますが、最も高度なハッカーをブロックすることはできません。これらの人々は、ヘッダー内の参照元情報を改ざんして、フォームのリモート コピーをサーバーから送信されたように見せかけるほど賢いのです。
リモート フォームの送信を処理するより良い方法は、一意の文字列またはタイムスタンプに基づいてトークンを生成し、このトークンをセッション変数とフォームに入れることです。フォームを送信した後、2 つのトークンが一致するかどうかを確認します。一致しない場合は、誰かがフォームのリモート コピーからデータを送信しようとしていることがわかります。ランダム トークンを作成するには、以下に示すように、PHP 組み込みの MD5 ()、Uniqid ()、および RAND () 関数を使用できます。
リスト 18. 防御リモート フォームの送信
[php] & lt;? );
if ($_POST['submit'] == "go"){
//トークンをチェック
if ($_POST['token'] == $_SESSION['token']){
//strip_tags
$name = ストリップ_タグ($_POST['名前']);
$name = substr($name,0,40);
//潜在的な 16 進文字をすべて削除します
$name = cleanHex($name);
//処理を継続します….
}else{
//すべての処理を停止します!リモートフォーム投稿試行!
}
}
$token = md5(uniqid(rand(), true));
$_SESSION['token']= $token;
function cleanHex($input){
$clean = preg_replace ("![][xX]([A-Fa-f0-9]{1,3})!", "",$input);
return $clean;
}
?>
<フォームアクション=”method=”post”>



”/>



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

結論

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

www.bkjia.com本当http://www.bkjia.com/PHPjc/1121567.html技術記事 PHP アプリケーションのセキュリティ 開発中、インタビュー中、または技術的な議論中であっても、セキュリティについては深い理解と習得が必要です。 目的 このチュートリアル...
関連ラベル:
php
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート