LoginSignup
0
0

More than 3 years have passed since last update.

PHPのセキュリティ関係

Last updated at Posted at 2020-07-28

この記事は以下の書籍のアウトプットとして執筆しました。

Webアプリケーションの入力は何をするか

入力処理では入力値に対して以下の処理を行う

a. 文字エンコーディングの妥当性検証
→文字エンコーディングを使った攻撃対策ため

b. 文字エンコーディングの変換
→HTTPメッセージとプログラム内部でも自演コーディグが異なるため
c. 入力値の妥当性検証
→セキュリティ上の保険的な対策

文字エンコーディングの検証

PHPではmb_check_encoding関数が使える

文字エンコーディングの変換

PHPはphp.iniでの設定で自動変換と明示的な返還を選べる。

入力値検証

バイナリセーフとヌルバイト攻撃

バイナリセーフ

入力値がどんなバイト列であっても正しく扱えることを意味する。
典型亭には値ゼロのバイト(ヌルバイト、PHP言語では\0と表記)が現れても正しく処理することを指す。

ヌルバイトが特別扱いされるのはC言語及びUnixやウィンドウズのAPIでは、ヌルバイトを文字列の終端とみなす取り決めがある。

C言語で開発されたPHPは塗るバイトを文字列の終端としてそれ以降を切り詰める関数がある。
このような関数をバイナリセーフでない関数という。

eregの検査を回避

この関数は PHP 5.3.0 で 非推奨 となり、 PHP 7.0.0 で 削除 されました。

<body>
<?php
  $p = $_GET['p'];
  if (ereg('^[0-9]+$', $p) === FALSE) {
    die('整数値を入力してください');
  }
  echo $p;
?>
</body>

出典:体系的に学ぶ 安全なWebアプリケーションの作り方 第2版[固定版] 脆弱性が生まれる原理と対策の実践より

このコードに対して以下のようにアクセスするとeregを回避される。
?p=1%00<script>alert('XSS')</script>

回避される理由

URLの中に%00がある。これは値ゼロのバイトすなわちヌルバイトでereg関数はバイナリセーフの関数ではないため、塗るバイトがあるとそこで文字列が終わっていると判断してしまう。

ヌルバイト対策はバイナリセーフの関数のみを用いてアプリを開発すればいいが、それは困難

ファイル名のように仕様上ヌルバイトを許容しないパラメータがあるから。

このため、アプリの入り口で倍ナチセーフを使って入力値の塗るバイトをチェックして、塗るバイトがあればエラーにする方法がある

制御文字のチェック

制御文字とは改行やタブ等通常表示されない文字のことでヌルバイトも含まれる。

文字数のチェック

すべてのパラメータで最大文字数をチェックスべき。
これをチェックしておくとセキュリティ上で保険になる。
攻撃は文字列が長いことが多いため。

PHPの正規表現

入力値検証には正規表現が便利。

関数 説明
perg 文字エンコーディングがUTF-8の場合のみ日本語が使える
mb_ereg 様々な文字エンコーディングに使える

1文字以上5文字以下の英数字をチェックする正規表現

preg_match('/A[a-z0-9]{1,5}\z/ui',$p);

出典:体系的に学ぶ 安全なWebアプリケーションの作り方 第2版[固定版] 脆弱性が生まれる原理と対策の実践より

名前 説明
u修飾子 UTF-8エンコーディングであることを示す。
i修飾子 大文字小文字を区別しない

u修飾子は不要の場合があるが。正規表現の「.」なドアが意図しない結果になるため、常にu修飾子を指定しておくほうがいい

全体一致は\Aと\zで示す

データの先頭は\Aデータの末尾は\zで示す。
^$は「行の」先頭と末尾を示すものだから$は改行にマッチする。
このため^$をデータの先頭・末尾として使うと不具合が生じる場合がある。

参考文献

0
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0