0

私はまだPHPとSQLを学んでいます。Web サイトのイベント リスト用の単純なコンテンツ管理システムを作成しようとしています。すべての入力フォーム フィールドは、テキスト エリアまたはテキスト ボックスのいずれかであり (そうです、そのようにしたいのです)、ユーザーがこれらのフィールドにテキストに加えて HTML リンクを追加できるようにしたいと考えています。次の関数は、ユーザーからの入力をサニタイズすることから始めるのに適しているように思えますが、私はこれに慣れていないので、より知識のある開発者の意見を得たいと思いました。データベースを保護するために、さらに何をすべきですか?

PSこれらの機能についてCSS-Tricksに感謝します。

function cleanInput($input) {

    $search = array(
         '@<script[^>]*?>.*?</script>@si',   // Strip out javascript
         '@<style[^>]*?>.*?</style>@siU',    // Strip style tags properly
         '@<![\s\S]*?--[ \t\n\r]*>@'         // Strip multi-line comments
    );

    $output = preg_replace($search, '', $input);
    return $output;
}

function sanitize($input) {
    if (is_array($input)) {
       foreach($input as $var=>$val) {
          $output[$var] = sanitize($val);
       }
    }
    else {
       if (get_magic_quotes_gpc()) {
          $input = stripslashes($input);
       }
       $input  = cleanInput($input);
   $output = htmlentities($output);
       $output = mysql_real_escape_string($input);
     }
     return $output;
}
4

2 に答える 2

1

非常に簡単に:

$testinput = "<script>alert('p0wned');</script >\n
    <a href='http://example.org' onclick=\"alert('p0Wned again!)\">Click me!</a>";

var_export(cleanInput($testinput));

また、htmlescapeほとんどの場合、使用するのは間違っています。これは、utf8 入力を台無しにします。また、HTML エスケープされたデータを DB に保存しないでください。ここでそれを使用する理由がまったくわかりません.HTMLをエスケープ解除して表示する必要はありませんか?

しかし、あなたはこれについて間違った方法で進んでいます。

  1. 正規表現を使用して html を解析/サニタイズしないでください。DOMDocumentorhtml5libまたは evenなどの実際の html パーサーを使用しtidylibます。残念ながら、PHP にはBleach on Pythonほど素晴らしいものはないようです。そのため、自分で作成する必要があります。ホワイトリストを含む XSLT スタイルシートは、この特定のサニタイズ条件を処理するのに適しているようです。更新: 別のユーザーが、ホワイトリスト ベースの HTML サニタイザーでもあるHTML Purifierを指摘しました。私はそれを使用したことはありませんが、「Bleach in PHP」のように見えます。必ず調べるべきです。
  2. サニタイズよりもエスケープを優先します。PHP 文化にはサニタイズへの執着がありますが、これは明らかに間違っています。アプリケーションの境界 (出力とデータベース) でデータをエスケープします。アプリケーションのコアでは、データはエスケープせずにネイティブ形式である必要があります。

処理の大まかな概要は次のようになります。

  1. 入力

    1. PHP 設定でマジック クォートをオフにします。アプリの上部にコードを含めて、オンの場合にハードに失敗するようにします。if (get_magic_quotes_gpc()) die ('TURN OFF MAGIC QUOTES!!!!');
    2. 各フィールドの予想されるタイプに従って、入力の特定のフィールドを検証し、正規化/サニタイズします。たとえば、「金額」には、ホワイトリストに登録された html フラグメント フィールドとは異なる検証基準があります。(おそらく、検証ライブラリを見つけて使用する必要があります。)
    3. エラーがある場合は、適切な HTTP 応答コードを使用してエラーをユーザーに送り返します。
    4. PDO準備済みステートメントを含むライブラリーなど、パラメーター・バインディングをサポートするデータベース・ライブラリーを使用して、データをデータベースに保存します。この方法では、手動でデータをエスケープすることを覚えておく必要はありません。
    5. 成功すると、作成または変更されたレコードを表示するページにリダイレクトします (コード 303)。
  2. 出力

    1. データベースからデータを取得します。
    2. データ構造の HTML 表示のみを処理するPHP コードであるテンプレートにデータをフィードします。そのデータがどのように取得されるか、または「アプリケーション駆動」の動作を含む方法の詳細を知る必要はありません。テンプレートを、データ構造を受け入れて文字列を返す関数のように扱います。
    3. テンプレート内のデータをエスケープします。データの個々のフィールドは、異なる方法でエスケープする必要があります。ほとんどの場合、htmlspecialchars出力の前に実行する必要があります。これを行わない唯一のケースは、表示する必要があるデータがすでにhtml である場合 (つまり、ホワイトリストでサニタイズされた html フィールド) です。次のようなヘルパー関数を定義して、テンプレートで使用します。

      function h($str) {
          return htmlspecialchars($str, ENT_QUOTES, 'utf-8');
      }
      

      さらに良いのは、文字列を自動的にエスケープし、エスケープを明示的にオフにする必要があるテンプレート ライブラリを使用することです。(一般的なケースは、エラーを避けるために単純であるべきであり、エスケープする必要があるのは一般的なケースです!)

    4. HTML ページは、テンプレートから返された文字列です。これで、ユーザーに表示できます。
于 2013-02-14T17:35:34.167 に答える