ホームページ > バックエンド開発 > PHPチュートリアル > PHP アプリケーションのセキュリティ -- 違反できない 4 つのセキュリティ ルール_PHP チュートリアル

PHP アプリケーションのセキュリティ -- 違反できない 4 つのセキュリティ ルール_PHP チュートリアル

WBOY
リリース: 2016-07-21 16:00:08
オリジナル
813 人が閲覧しました

セキュリティが重要であることは誰もが知っていますが、業界の傾向は最後の瞬間までセキュリティを追加しないことです。 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'); 'こんにちは' . $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' ); //クリーン!

関数 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 変数として誤って解釈することがなくなります。

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



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

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

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

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

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

//難読化されていないコード
$input = '';
$input = $_POST['username']){
$input = ' ' ;
}
?>

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


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

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

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

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




SQL インジェクション攻撃を防ぐ

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

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





;/p>


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

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

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

$sql = "ユーザー名='".$username."' およびパスワード='" の制限として count(*) を選択します。 1";

$result = mysql_query($sql);

while ($data = mysql_fetch_object($result)){
if ($data->ctr == 1){
//彼らは大丈夫ですアプリケーションを入力してください。
$ ok = 1;
}}

($ ok) {
$ _Session ['loginokay'] = true
header ("index.php"); Else {{
Header(" login.php");
}
?>

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

たとえば、ユーザーがユーザー名として foo を入力し、パスワードとして ' または '1'='1 を入力すると、実際には次の文字列が PHP に渡され、クエリが MySQL に渡されます。 php
$sql = "select count(*) as ctr from users where username='foo' and password='' or '1'='1' limit 1"; このクエリは常にカウントを返します。値 1 なので、PHP はアクセスを許可します。ハッカーは、パスワード文字列の末尾に悪意のある SQL を挿入することで、正規のユーザーになりすますことができます。

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

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

$username = $_POST['user']
$pw = $_POST['pw']; = "ユーザー名='".mysql_real_escape_string($username)."' およびパスワード='" から count(*) を CTR として選択します。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;
}else{
header("login.php"); ?>

ユーザー入力への悪意のある SQL インジェクションを回避するために、ユーザー入力のラッパーとして mysql_real_escape_string() を使用します。ユーザーが 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 に直接配置されるため、PHP では、register_globals が無効になっている場合は、template.php で $_GET[.pid'] を使用してアクセスできます。例 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 変数を制限するには

$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.45 e6 (科学表記 - 悪い)
0xff33669f (16 進数 - 危険! 危険!)

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

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

$pid = $ _GET['pid'];

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

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

class Page{
function fetchPage($pid){
$sql = "pid='のページからpid、title、desc、kw、content、statusを選択します".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){
// ログアウトするかホームページに戻すなど、適切な操作を行います
{
//空$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、ホームページに送り返す
}
}else{
// $pid が空なので、ホームページに送り返す
}

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

// 架空のクラス Page のオブジェクトを作成します。これは Now// / 悪意のあるユーザー入力からさらに保護
$ Obj = New Page
$Content = $Fetchpage ($ Pid); バッファ オーバーフロー攻撃は次のものに限定されないことに注意してください。数字や文字の長い文字列。また、長い 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);
// 処理を続行します。
}

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

名前

;input type="submit" name="submit" value="go"/>




セキュリティの観点から、公開ユーザー入力には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;
?>

;/p>
;input type="hidden" name="status" value="live"/>

;


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

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

図 1. データ改ざんウィンドウ


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

共通のフォーム処理関数を構築し、多くのページがこの共通ロジックを使用している場合はどうなるでしょうか?隠し変数を使用してフローを制御するとどうなるでしょうか?たとえば、非表示のフォーム変数で、書き込むデータベース テーブルや使用するファイル リポジトリを指定できます。オプションは 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 = strip_tags( 'name']); uniqid(rand(), true));
$_SESSION['token'] = $token;

function cleanHex($input){
$clean = preg_replace("![][xX]([A-Fa- f0-9]{1,3})!", "",$input
;label for="name">名前




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




結論

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

SQL インジェクションの問題を防ぐために mysql_real_escape_string() を使用します。
正規表現と strlen() を使用して、GET データが改ざんされていないことを確認します。
正規表現と strlen() を使用して、ユーザーが送信したデータがメモリ バッファーをオーバーフローしないようにします。
strip_tags() と htmlspecialchars() を使用して、ユーザーが有害な可能性のある HTML タグを送信しないようにします。
データ改ざんなどのツールによるシステムの侵害を防ぎます。
一意のトークンを使用して、ユーザーがリモートからサーバーにフォームを送信できないようにします。
このチュートリアルでは、ファイル インジェクション、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 アプリケーション開発、および XML コンサルティングを専門とする、テキサス州オースティンにある Web コンサルティング会社、Triple Dog Dare Media の創設者および主要人物です。彼は、『No Nansense XML Web Development with PHP』 (SitePoint 発行) の著者です。

www.bkjia.com本当http://www.bkjia.com/PHPjc/317197.html技術記事セキュリティが重要であることは誰もが知っていますが、業界の傾向は最後の瞬間までセキュリティを追加しないことです。 Web アプリケーションを完全にセキュリティで保護することは不可能なので、なぜわざわざ苦労する必要があるのでしょうか...
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート