PHPのセキュリティに関する世界観です。
セキュリティも参照のこと。
自分の書いたブログ「神々とともに生きる詩人」2021/02/02より。
PHPのセキュリティに言えるのは、「絶対に任意の悪意あるコードを実行させてはならない」ということ。
JavaScriptを挿入されて実行されたり、別のサイトからコードを実行、あるいはセッションを乗っとられたり、SQLを挿入されたり、コマンドを実行されたりするのに共通するのは、任意の悪意あるコードを実行されるということ。
実際には、セッションハイジャックやパスやエラーから情報が流出するなど、ほかにもセキュリティ攻撃はある。
しかしながら、任意の悪意あるコードの実行を防ぐなら、HTMLタグのエスケープ、トークン、SQLでのプレースホルダなど、対策における「本質」を知った上での対策ができる。
Web上にPHPのWebアプリケーションを公開する前に、必ずセキュリティ対策を確認しましょう。
たとえば、ユーザーが投稿したデータを表示する時には、htmlspecialchars()関数を使って、JavaScriptなどのコードが含まれていた場合(<script>~</script>を含む投稿が投稿された場合)、HTMLタグの特殊な文字を変換し、HTMLタグをただの文字として表示することができます。
<?php echo htmlspecialchars($_POST['howto'],ENT_QUOTES,'UTF-8'); ?>
以下は具体的なセキュリティ対策。
パーフェクトPHP (PERFECT SERIES 3)はさまざまなセキュリティ対策についてとても詳しく記述されている。一読の価値あり。
まず、セキュリティ対策の一般的な方法として、バリデーションを行う。バリデーションは、入力に使うデータの値の種類や範囲をあらかじめ決めておくこと。
セキュリティアタックで、特に多いアタックの方法が、任意の悪意あるスクリプトやコードを外部から挿入されて実行されること。
入力されるコンテンツの中にJavaScriptコードを挿入される方法を、スクリプト挿入攻撃と呼ぶ。
また、クロスサイトスクリプティング(XSS)は、リンクから悪意あるページに誘導するなどの間接的な方法でスクリプトを実行させる。
意図しないスクリプトの実行を防ぐには、htmlspecialchars()関数を使って<script>~</script>タグなどをエスケープすることで対策できる。
JavaScriptだけではなく、SQLのデータベース操作文が狙われることもある。
SQL文の中に不正に悪意あるSQL文を挿入されて実行される攻撃をSQLインジェクションと呼ぶ。
SQLインジェクションは、プリペアドステートメントやプレースホルダを使うことで回避できる。
また、これら以外に、ユーザーの権限やセッションを乗っ取ったり不正に取得することで攻撃に使う方法もある。
クロスサイトリクエストフォージェリ(CSRF)は、正規に得られたユーザーの権限を利用して別の人間が悪意ある意図しない操作を誘導させる方法。
CSRFは、攻撃者に推測されにくい合言葉であるワンタイムトークンをページに埋め込んでチェックすることで回避できる。
また、ユーザーが取得したセッションを不正に使った攻撃の例として、セッション固定攻撃やセッションハイジャックが挙げられる。
ほかには、外部からの値やデータを使う際には、それが本当に信頼できるデータなのか、内部で実行に使っても大丈夫なのかを注意しなければならない。
セキュリティ攻撃は、PHPだけで対策できるものもあれば、そうではないものもある。PHPで対策できるものについては、パーフェクトPHP (PERFECT SERIES 3)が参考になる。
SQLも参照のこと。その他のセキュリティ攻撃(PHPで対策できる以外)については、セキュリティも参照のこと。
==は型をキャストして値を比較するが、===は型をキャストせずに値を比較する(厳密な比較)。
Webサービスを作る上で、不用意に==を使うと、大変なことになることがある。
たとえば、IDやパスワードを比較する際に、0164が164と同じものとして比較されたり、0164で登録したのに164で処理が通ってしまい、164で登録されたりする。
特に理由がない時は、厳密な比較をするように心がけよう。
詳しくは以下の書籍が参考になります。
また、エラーなどで余計な情報を出さないようにしよう。
たとえば、IDとパスワードのどちらかが間違っていたとして、どちらが間違っている、という情報はいらない。どちらかが間違っている、という情報で良い。ハッカーにできるだけ情報を与えすぎないようにしよう。
わざわざ親切に「IDが間違っています」とか「パスワードが間違っています」と言うのではなく、「IDあるいはパスワードが間違っています」と言う方が良い。