CSRF攻撃に対する予防措置
CSRF (クロスサイト リクエスト フォージェリ) 攻撃は一般的な Web 攻撃です。つまり、攻撃者はユーザーのログイン ID を使用して、ユーザーの知らない間に悪意のあるリクエストをターゲット Web サイトに送信し、それによって攻撃の目的を達成します。この記事では、Web 開発者がユーザー情報のセキュリティをより適切に保護できるように、CSRF 攻撃の原則と一般的な予防策を紹介します。
CSRF攻撃の原理
CSRF 攻撃の原理は比較的単純で、攻撃者はユーザーのログイン ID を使用してターゲット Web サイトに悪意のあるリクエストを送信し、攻撃の目的を達成します。具体的には、攻撃者は自分の Web サイト上に悪意のあるリンクまたはフォームを構築し、ユーザーがリンクをクリックするかフォームを送信するように誘導し、ターゲット Web サイトに悪意のあるリクエストが送信されるようにします。ユーザーはすでにターゲット Web サイトにログインしているため、悪意のあるリクエストにはユーザーの ID 情報が含まれます。ターゲット Web サイトでは、リクエストがユーザー自身によって開始されたものであるか、攻撃者によって偽造されたリクエストであるかを区別できないため、攻撃に対して脆弱です。
CSRF攻撃に対する予防措置
CSRF 攻撃を回避するには、開発者は Web アプリケーションのセキュリティを強化するためにいくつかの予防措置を講じる必要があります。一般的な CSRF 攻撃の防止策をいくつか示します。
1. ランダムトークン
ランダム トークンは一般的な CSRF 攻撃防止手段であり、リクエストがターゲット Web サイトに送信されるたびに、ランダムに生成されたトークン (トークン) を運ぶ必要があり、ターゲット Web サイトはリクエストを処理するときにトークンを検証します。無効な場合はリクエストを拒否します。攻撃者は有効なトークンを偽造できないため、CSRF 攻撃を回避できます。
PHP でのランダム トークンの生成と検証コードの例を次に示します。
<?php
// 生成随机令牌
function generate_csrf_token()
{
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;
return $token;
}
// 校验随机令牌
function verify_csrf_token()
{
if (isset($_POST['csrf_token']) && $_POST['csrf_token'] === $_SESSION['csrf_token']) {
return true;
}
return false;
}
// 示例:生成随机令牌
$csrf_token = generate_csrf_token();
// 示例:校验随机令牌
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (verify_csrf_token()) {
// 处理表单数据...
} else {
// 令牌校验失败,拒绝请求
die("Invalid CSRF token");
}
}
?>
上記のサンプルコードでは、ランダムトークンを生成・検証するgenerate_csrf_token()
関数とverify_csrf_token()
関数を定義しました。具体的には、random_bytes()
関数を使用してランダムなバイト配列を生成し、bin2hex()
関数を使用してそれをトークンとして機能する 16 進文字列に変換します。同時に、トークンの有効性を後で検証できるように、トークンを PHP の $_SESSION 配列に保存します。
フォームが送信されると、トークンを非表示フィールドとしてフォームに追加し、サーバー側でトークンの有効性を検証できます。トークンが無効な場合、リクエストは拒否されます。
2. リファラーの検証
リファラー検証は単純な CSRF 攻撃防止手段です。つまり、リクエストの処理時に、リクエストのリファラー ヘッダー情報が検証され、リクエストのソースが正当であることが確認されます。ブラウザは自動的に Referer ヘッダー情報を送信するため、攻撃者は正規の Referer を偽造できず、CSRF 攻撃を回避できます。
以下は、PHP のリファラー検証コードの例です。
<?php
// 校验 Referer 头部信息
function verify_referer()
{
if (isset($_SERVER['HTTP_REFERER']) && parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) === $_SERVER['HTTP_HOST']) {
return true;
}
return false;
}
// 示例:校验 Referer 头部信息
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (verify_referer()) {
// 处理表单数据...
} else {
// Referer 校验失败,拒绝请求
die("Invalid Referer");
}
}
?>
上記サンプルコードでは、verify_referer()
リクエストのRefererヘッダ情報を確認する関数を定義しています。$_SERVER['HTTP_REFERER']
具体的には、変数を使用してリクエストのRefererヘッダー情報を取得し、parse_url()
関数を使用して情報を解析し、そのホスト名(host)部分を抽出し、現在のWebサイトのホスト名と比較します。2 つが同じ場合、リクエストの送信元は正当であるとみなされ、そうでない場合、リクエストは拒否されます。
リファラー検証はシンプルで効果的ですが、一定の制限もあることに注意してください。一部のブラウザやセキュリティ ソフトウェアでは、Referer ヘッダー情報が無効になったり改ざんされたりして、検証が失敗する可能性があります。したがって、Web アプリケーションのセキュリティを強化するために、さまざまな予防措置を講じることをお勧めします。
3. SameSite Cookie
SameSite Cookie は、新しい CSRF 攻撃防止手段です。つまり、Cookie を設定するときに、Cookie の SameSite 属性を Strict または Lax に指定して、Cookie のクロスサイト アクセスを制限します。具体的には、SameSite 属性には次の 2 つの値があります。
- 厳密: 同じサイトへのアクセスのみが許可され、サイトを越えたアクセスは禁止されます。
- Lax: リンク ジャンプなどのある程度のクロスサイト アクセスを許可しますが、一部の機密操作についてはクロスサイト アクセスを禁止します。
SameSite 属性を設定すると、ユーザーの Cookie を使用して悪意のある操作を実行する CSRF、リンク内でリクエストを偽造する攻撃など、一般的な CSRF 攻撃を回避できます。
以下は、PHP SameSite Cookie 設定のコード例です。
<?php
// 设置 SameSite Cookie
session_set_cookie_params([
'lifetime' => 3600,
'path' => '/',
'domain' => '.example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]);
session_start();
?>
上記のサンプル コードでは、session_set_cookie_params()
関数を使用してセッション Cookie のパラメータ (Cookie の有効期間、パス、ドメイン名、セキュリティ フラグ、HttpOnly フラグ、SameSite 属性など) を設定します。その中で、SameSite プロパティを Strict に設定して、クロスサイト アクセスを禁止します。
SameSite 属性は CSRF 攻撃を完全に解決できるわけではなく、他の予防策が必要な攻撃シナリオが依然として存在することに注意してください。さらに、一部の古いブラウザでは SameSite 属性がサポートされていない可能性があるため、Web アプリケーションのセキュリティを強化するには、他の予防策を組み合わせる必要があります。
要約する
CSRF 攻撃は、ユーザーのログイン ID を使用してターゲット Web サイトに悪意のあるリクエストを送信することで攻撃の目的を達成できる一般的な Web 攻撃です。CSRF 攻撃を回避するために、開発者はランダム トークン、リファラー検証、SameSite Cookie などの予防措置を講じる必要があります。Web アプリケーションのセキュリティを強化するには、いくつかの予防策が推奨されます。