ホームページ > ウェブフロントエンド > htmlチュートリアル > ベスト プラクティス シリーズ (3) - PHP セキュリティの 3 つの柱: フィルタリング、検証、エスケープ - Filtering_html/css_WEB-ITnose

ベスト プラクティス シリーズ (3) - PHP セキュリティの 3 つの柱: フィルタリング、検証、エスケープ - Filtering_html/css_WEB-ITnose

WBOY
リリース: 2016-06-24 11:16:42
オリジナル
1254 人が閲覧しました

私たちがアプリケーションを開発するときは、一般に、自分の管理下にないデータ ソースからのデータを信頼しないという慣例があります。たとえば、次の外部ソース:

  • $_GET
  • $_POST
  • $_REQUEST
  • $_COOKIE
  • $argv
  • php://stdin
  • php://input
  • file_get_contents()
  • リモートデータベース
  • リモート API
  • クライアントからのデータ

これらすべての外部ソースは、悪意のあるデータを (意図的または非意図的に) PHP スクリプトに挿入する可能性のある攻撃ベクトルとなる可能性があります。ユーザー入力を受け入れて出力をレンダリングする PHP スクリプトを作成するのは簡単ですが、安全に実行するには多大な労力が必要です。 Chen Yaojin の 3 段階の斧を導入として使用して、入力のフィルタリング、データの検証、出力のエスケープという 3 つのトリックを紹介します。

1. 入力のフィルタリング

入力のフィルタリングとは、安全でない文字をエスケープまたは削除することを意味します。入力データがアプリケーションのストレージ層に到達する前に必ずフィルタリングしてください。これが防御の第一線です。 Web サイトのコメント ボックスが HTML を受け入れる場合、ユーザーは以下に示すように、悪意のある タグをコメントに追加できます。ユーザーがこのページにアクセスすると、安全でない可能性のあるフィッシング Web サイトにリダイレクトされます (この攻撃には、より専門的な名前が付けられています: XSS 攻撃)。この簡単な例は、制御していない入力データをフィルタリングする必要がある理由を示す良い例です。通常、フィルタリングしたい入力データには、HTML、SQL クエリ、ユーザー情報などが含まれます。

HTML

PHP が提供する htmlentities 関数を使用して HTML をフィルタリングできます。この関数は、すべての HTML タグ文字 (&、<、> など) を対応する HTML エンティティに変換して取得できるようにします。アプリケーションストレージ層からの安全なレンダリング。ただし、特に画像やリンクほどではないリッチ テキストを入力する場合に、ユーザーに特定の HTML 要素の入力を許可することがあります。ただし、htmlentities は HTML を検証できず、入力文字列の文字セットを検出できないため、そのような機能は実装できません。 。

<p>这篇文章很有用!</p><script>windows.location.href=“http://laravelacademy.org”;</script>
ログイン後にコピー

htmlentities の最初のパラメータは処理される HTML 文字列を表し、2 番目のパラメータはエスケープされる一重引用符を表し、3 番目のパラメータは入力文字列の文字セット エンコーディングを表します。

htmlentities の反対は html_entity_decode メソッドで、すべての HTML エンティティを対応する HTML タグに変換します。

さらに、PHP には同様の組み込み関数 htmlspecialchars も提供されており、これも HTML タグの文字を HTML エンティティに変換するために使用されますが、変換できる文字は限られています (公式ドキュメントを参照してください: http://php .net/manual/ zh/function.htmlspecialchars.php)、すべての文字を変換したい場合は、引き続き htmlentities メソッドを使用します。htmlentities と同様に、htmlspecialchars にも対応するメソッド htmlspecialchars_decode があることに注意してください。

入力文字列からすべての HTML タグを直接削除したい場合は、strip_tags メソッドを使用できます。

より強力な HTML フィルタリング関数が必要な場合は、HTML Purifier ライブラリを使用できます。これは、指定されたルールを使用して HTML 入力をフィルタリングするように特別に設計された非常に堅牢で安全な PHP ライブラリです。 Laravel では、対応する拡張パッケージを使用してフィルタリング関数を実装できます: http://laravelacademy.org/post/3914.html

SQL クエリ

場合によっては、アプリケーションは入力データに基づいて SQL クエリを構築する必要があります。 HTTP リクエストのクエリ文字列は、HTTP リクエストの URI フラグメントから取得される可能性もあります。注意しないと、悪意のあるユーザーが SQL インジェクション攻撃 (SQL ステートメントを結合してデータベースを破壊したり、データを取得したりする) を実行するために使用される可能性があります。機密情報)。多くの若手プログラマは次のようなコードを作成する可能性があります:

<?php$input = '<p><script>alert('Laravel学院');</script></p>';echo htmlentities($input, ENT_QUOTES, ‘UTF-8');
ログイン後にコピー

これは非常に危険です。たとえば、誰かが次の方法で HTTP にリクエストを送信します:

$sql = sprintf(    'UPDATE users SET password = “%s” WHERE id = %s’,    $_POST[‘password’],    $_GET[‘id’]);
ログイン後にコピー

この HTTP リクエストは各ユーザーのパスワードを abc に設定します。これは、多くの SQL データベースが処理するためです。 - コメントの先頭として使用されるため、後続のテキストは無視されます。

SQL クエリで入力データを使用する場合は、PDO 前処理ステートメントを使用する必要があります (PDO は、さまざまなデータベース ドライバーに統合インターフェイスを提供する PHP の組み込みデータベース抽象化レイヤーです)。 )、PDO 前処理ステートメントは PDO によって提供される機能で、外部データをフィルターし、フィルターされたデータを SQL ステートメントに埋め込むことで、上記の SQL インジェクションの問題を回避できます。また、前処理ステートメントは複数のコンパイルと実行が行われます。これにより、システム リソースの占有が効果的に削減され、より高い実行効率が得られます。 PDO の後はデータベース部分に焦点を当てます。

注目に値するのは、多くの最新の PHP フレームワークは MVC アーキテクチャ パターンを使用してデータベース操作をモデル層にカプセル化しており、提供されているメソッドを使用している限り、フレームワークの最下位層はすでに SQL インジェクションをうまく回避しているということです。モデルクラスによってデータベース操作を実行する操作は、基本的に SQL インジェクションのリスクを回避できます。

Laravel を例として、基礎となる層が SQL インジェクションをどのように回避するかを見てみましょう。コードは次のようになります。

$id = $_GET['id'];$password = $_POST['password'];User::find($id)->update(['password'=>bcrypt($password)]);
ログイン後にコピー

由于模型类底层调用的是是查询构建器的方法,所以最终会调用Builder( Illuminate\Database\Query\Builder)的 update方法:

public function update(array $values){    $bindings = array_values(array_merge($values, $this->getBindings()));    $sql = $this->grammar->compileUpdate($this, $values);    return $this->connection->update($sql, $this->cleanBindings($bindings));}
ログイン後にコピー

这段代码传入参数是要更新的值,然后通过 $bindings获得绑定关系,这里我们我们获取到的应该是包含 password和 updated_at(默认更新时间戳)的数组,然后再通过Grammar( Illuminate\Database\Query\Grammars\Grammar)类的 compileUpdate方法生成预处理SQL语句,这里对应的sql语句是:

update `users` set `password` = ?, `updated_at` = ? where `id` = ?
ログイン後にコピー

然后最终将预处理sql语句和对应绑定关系传递给数据库去执行。关于SQL注入我们还会在后续数据库部分继续讨论。

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