2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【PHP】セキュリティを強化する、csrf対策トークンの実装

Last updated at Posted at 2023-06-03

目次

  1. はじめに
  2. CSRFの対策
  3. ワンタイムトークンの生成
  4. リンク先での整合性の確認

1. はじめに

CSRFとはクロスサイトリクエストフォージェリ(cross site request forgery)の略です。
簡単に説明しますと、フォームでデータを送信する際、Webアプリケーション利用者が意図しない処理を実行してしまう脆弱性、または攻撃手法のことです。

下の記事が脆弱性について詳しいので、参考にしていただけたらと思います。

2. CSRFの対策

CSRFの対策として、現在ベストプラクティスの一つとされているのがワンタイムトークンを利用した方法になります。
流れとしては、入力フォームのあるサイトを表示する際、サーバがクライアントに対してランダムな文字列(トークン)を発行します。
データを送信した際に、このトークンがリクエストに入っていなかったり、整合性が取れなかったりすれば、処理を終了することで不正なリクエストを防ぎます。

Laravelフレームワークにおいては「@csrf」によって簡単にトークンが生成されますが、今回は仕組みを知るためにコードを一つ一つ書いていきます。

3. ワンタイムトークンの生成

フォームのあるページの最初にトークンを生成するコードを、フォーム内にトークンをhiddenで埋め込みます。

2023/6/4追記:
 ランダムバイトの生成は「openssl_random_pseudo_bytes()」がPHP5.3以降、「random_bytes()」がPHP7以降で使用可能です。
 「openssl_random_pseudo_bytes()」は疑似ランダムコードであり、「random_bytes()」は公式の説明で「Get cryptographically secure random bytes(暗号的に安全なランダムバイトを取得)」とあり、特別の理由がない限り、「random_bytes()」が推奨されるようです。

form.php
<?php
// セッションの開始
session_start();

// ワンタイムトークンの生成
$toke_byte = random_bytes(16);
$csrf_token = bin2hex($toke_byte);

// トークンをセッションに保存
$_SESSION['csrf_token'] = $csrf_token;
?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <title>フォーム</title>
</head>
<body>
  <form method="POST" action="target.php">

 // hiddenで生成したトークンを埋め込む
  <input type="hidden" name="csrf_token" value="<?= $csrf_token; ?>">
  ...
</form>
<!-- 以下略 -->

4. リンク先での整合性の確認

POSTでcsrf_tokenのパラメーターが送信されていなかったり、送信されていればその値がセッションに保存された値と一致しなかったりしたときにexitで処理を中止します。

target.php
<?php
if (!isset($_POST["csrf_token"]) 
 || $_POST["csrf_token"] != $_SESSION['csrf_token']) {
  echo "不正なリクエストです";
  exit();
}
// 以下、処理続行
2
6
4

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
2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?