2020年3月1日日曜日

PHPのセキュリティ対策3選

はじめまして!
B20の自己推薦で配属されたy_takaya(高谷)です。

本日より「春のAdventCalendar2020」と称して、B20生がバトンリレーで記事を投稿していきます!
初日は学年リーダ(らしい)の私からです。




本日私が紹介するのは、誰でも単語は聞いたことあるだろう「PHP」についてです。
PHPは「Personal Home Page tools」の略だかと言われています。

私はPHPをプログラミング初心者であるあなたにおすすめしたいです。
PHPのメリットはWebとの親和性の高さ、データベースとの接続の容易さだと思っています。
他にもPHPはコンパイルする必要がないため、アイデアをすぐに反映しやすいところもメリットだと思っています。

導入

懇切丁寧に書いてましたが、自分の環境に合わせてどこかのQiitaを見ながら導入した方が確実だと思ったので割愛しました。

セキュリティ対策


ということで今回私が解説するのはセキュリティ対策についてです。

セッション固定化攻撃を防ぐ

URIによるセッション管理を禁止して、セッションIDを変更します。

攻撃者がセッションIDを指定してしまう攻撃で、PHP5.3以前では簡単な形式チェックのみでしたので受け入れられてしまいました。
対策として、URIによるセッション管理を禁止します。

```php.ini
session.use_only_cookies = 1
```

そして、セッションIDは定期的にリジェネレートしましょう。
session_start()関数でセッションを開始した後に、リジェネレートを行うには次の関数を呼び出します。

```
session.regenerate_id(TRUE);
```

引数は、リジェネレート前のセッションIDを削除するかどうかです。削除しましょう。意味がなくなります。

SQLインジェクション対策


SQLインジェクションとは意図しないSQL文を実行させる攻撃です。
例えば、ログインフォームなどで、ログインIDとパスワードを入力してログインをします。
ここで対策を行なっていないと、ユーザ名に「username' --」のように入力した時に、パスワードの入力なしで通ってしまう可能性があります。
これはSQLのコメントアウト(--)を利用した抜け穴ですね。
この時実行されるSQL文はこうなります。

```SQL
SELECT * FROM user WHERE user='username' -- 'AND password=''
```

これをさせないために行うのが、プリペアドステートメントです。
プリペアドステートメントは、複数のデータを一括登録する場合に、用いるSQL文は同じで、データのみが異なる場合に用いるものです。
SQL文の実行に先立って、SQL文の構文解析、コンパイル、最適化が行われ、未対策の時からセキュリティ性が向上するだけではなく、処理速度も早くなることもあります。
ここでは、最初にSQL文を準備します。そしてデータ部分には「?」を入れましょう。

```SQL
SELECT * FROM user WHERE user=? AND password=?
```

次に、?への割り当てを行います。

```PHP
if ($stmt = mysqli_prepare($link, $sql)) {
// 変数のバインド。変数の型がどちらもs(string)であることを記述する
mysql_stmt_bind_param($stmt, 'ss', $_POST['id'], $_POST['password']);
// クエリの実行
mysqli_stmt_execute($stmt);
// リザルトの転送
mysqli_stmt_store_result($stmt);
}
```

私はPDOを使用しているので、次みたくしてます。

```PHP
$stmt = $pdo->prepare("INSERT INTO user(user, password ) VALUES (?, ?)");
$stmt->execute(array($_POST['id'], $_POST['password']));
```

または

```PHP
$stmt = $pdo->prepare("INSERT INTO user(user, password ) VALUES (:user, :password)");
$stmt->bindParam(':user', $_POST['id']);
$stmt->bindParam(':password', $_POST['password']);
$stmt->execute();
```

楽しくなって来ちゃいましたね。

NULLバイト攻撃

NULLバイトを使ってプログラムを誤作動させる攻撃です。
NULLバイトは「¥x00や¥0」のことで、文字列の終端と判断してしまう関数が存在します。
例えば正規表現を行う場合にバイナリセーフでないereg()関数を使ってしまうと、URIのファイルの後に「?u=+x-///」と入力することによって、「」以降の正規表現をチェックしません。
あんまりない気がする(個人では対策したことない)実装ですが、調べると他にも色々な対策方法が出てきます。

とくにPHPはバージョンによって様々な脆弱性の対策が施されてきています。
もしかしたら、今紹介した中でも、わざわざ対策する必要がないものを出てくるのではないかと考えています。
ぜひ、参考にしてみてください。

0 件のコメント:

コメントを投稿