こんにちは!日々の開発やインフラの管理、本当にお疲れ様です。
新人のIT担当者や、これからセキュリティの勉強を始める方にとって、次々に出てくる専門用語を覚えるだけでも大変ですよね。
今回は、Webアプリケーションのセキュリティにおいて、とても重要かつ見落とされやすい「BFLA(Broken Function Level Authorization)」というテーマについて、一緒に一歩ずつ学んでいきましょう!
なんだか呪文のような難しい名前ですが、身近な「家の鍵」に例えると、すごくスッキリ理解できるようになりますよ。それでは、さっそく扉を開けていきましょう!
—
1. 身近な「家の鍵」で例えるBFLA(機能の権限不足)
セキュリティの世界では、「認証(Authentication)」と「認可(Authorization)」という、よく似た2つの言葉が登場します。これ、すごく混ざりやすいんですよね。
- 認証(Authentication): 「あなたは誰ですか?」を確認すること(合鍵を持っているか、本人確認をする)
- 認可(Authorization): 「あなたは何をしていい人ですか?」を確認すること(家に入ったあと、金庫を開けていい人か、リビングでテレビを見るだけの人か)
BFLAってどういう状態?
BFLA(Broken Function Level Authorization)を日本語にすると、「機能ごとのアクセスの決まりが壊れている(または設定されていない)」という意味になります。
これを家に例えてみましょう。
あなたは「普通のゲスト」として、友達の家に遊びに行きました。玄関の鍵(認証)をあけてもらい、リビングに入ることは許可されています。
しかし、この家の裏口や2階の書斎には、「本当は家族しか入れないはずの部屋」があるのに、なぜか「鍵がかかっていない」状態だったらどうでしょう?
ゲストであるあなたが、うっかり(あるいはわざと)その部屋のドアノブをガチャっと回したら、中に入れてしまいました。これがまさにBFLAの状態です。
システムで言えば、「一般ユーザーでログインしているのに、URLを直接ブラウザに入力したら、なぜか管理者専用の画面に入れてしまった!」という現象がこれに当たります。
—
2. なぜ攻撃者はここを狙うのか?(攻撃のメカニズム)
攻撃者(レッドチーム)は、システムの「表側のリンク」だけを見ていません。あちこちに隠されたドアノブを片っ端からガチャガチャと試していくようなアプローチをとります。
よくある落とし穴:画面がない=安全、ではない!
開発をしていると、「この管理者用のボタンは、一般ユーザーの画面には表示しないようにしよう!」と実装することがよくありますよね。
<!-- 一般ユーザー向けの画面のイメージ -->
<div>
<p>ようこそ、一般ユーザーさん!</p>
<!-- 管理者ボタンは画面上に表示しない(CSSで隠したり、HTMLを出力しない) -->
</div>
画面上でボタンを隠すのは、一般的なユーザービリティ(使いやすさ)としては正しいのですが、セキュリティの観点からは「隠しただけで、鍵をかけていない状態」になります。
攻撃者は、ブラウザの「開発者ツール」や、通信を覗き見・改ざんするツールを使って、次のようなURLやAPIを直接直叩き(じかばたき)します。
- 一般ユーザー用のURL:
https://example.com/api/user/profile - 隠された管理者用のURL:
https://example.com/api/admin/delete-user
もし、サーバー側で「このリクエストを送ってきた人は、本当に管理者権限を持っているか?」をチェックしていなかったらどうなるでしょうか?
攻撃者は一般ユーザーのままで、管理者専用の機能(ユーザー削除など)を自由自在に実行できてしまいます。これがBFLAによる権限昇格です。
—
3. HTTPメソッドの変更によるバイパス(ちょっとずるい手口)
さらに、BFLAの厄介なバリエーションとして、「HTTPメソッドの変更」を使ったバイパス手法があります。
Webの世界では、サーバーにお願いをする方法(HTTPメソッド)がいくつか決まっています。
GET: 情報を「見せて」くださいPOST: 新しく情報を「作って」くださいDELETE: 情報を「消して」ください
まじめな開発者が、「よし、ユーザー情報の変更画面(POST)には、ちゃんと管理者チェックを入れよう!」と実装したとします。しかし、同じデータにアクセスする別の方法(例えば GET や PUT など)のチェックをうっかり忘れていたらどうなるでしょうか?
攻撃者は、メソッドをこっそり POST から GET(あるいはその逆など)に変更してリクエストを送り、セキュリティの網の目をすり抜けようとします。これも現場でよく見つかる危ういポイントです。
—
4. 実務で使える!PHPによる「認可チェック」の具体例
では、どうすればこのBFLAを防ぐことができるのでしょうか?
答えはシンプルです。「画面で見せないようにするだけでなく、サーバー側で、リクエストが来るたびに厳しく身分証(権限)を確認する」ことです。
ここでは、PHPを例にとって、安全なコードと危ういコードを比較してみましょう。
❌ 危ういコード(BFLAの危険性あり)
以下のコードでは、「画面上のリンクがないから大丈夫だろう」と油断して、サーバー側での権限チェックをすっかり忘れています。
<?php
// 危うい実装:セッションにユーザーIDはあるが、管理者かどうかのチェックがない
session_start();
$userId = $_SESSION['user_id'] ?? null;
// リクエストされたユーザーを削除する処理
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$targetId = $_POST['target_id'];
// 誰でもこのURLにPOSTリクエストを送れば削除が実行されてしまう!
deleteUserFromDatabase($targetId);
echo "ユーザーを削除しました。";
}
?>
⭕ 安全なコード(しっかりと認可を検証)
こちらが、実務で実装すべき安全なコードです。処理を実行する前に、必ず「本当に管理者権限を持っているか?」をサーバー側で厳格にチェックします。
<?php
// 安全な実装:サーバー側で必ず権限(ロール)を検証する
session_start();
$userId = $_SESSION['user_id'] ?? null;
// 1. まずログインしているか確認
if (!$userId) {
http_response_code(401); // 認証エラー
exit("ログインしてください。");
}
// 2. データベース等からユーザーの権限をしっかり取得
$userRole = getUserRoleFromDatabase($userId);
// 3. 【重要】機能レベルの認可チェック(BFLA対策)
if ($userRole !== 'admin') {
// 管理者でなければ、ここで容赦なく弾く!
http_response_code(403); // 権限エラー(Forbidden)
exit("この操作を行う権限がありません。");
}
// 4. 権限確認が取れたので、安全に処理を実行
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$targetId = $_POST['target_id'] ?? null;
if ($targetId) {
deleteUserFromDatabase($targetId);
echo "管理者権限によってユーザーを削除しました。";
}
}
?>
このように、APIやデータの更新・削除を行うエンドポイントのすべての入り口で、$userRole !== 'admin' のようなチェックを徹底することが、BFLAを防ぐ一番の近道になります。
—
5. 一歩ずつ対策を学んでいきましょう!
BFLAの怖さと、その対策の基本(サーバー側での厳格な権限チェック)が見えてきましたか?
セキュリティの対策というと、「なんだか難しそう…」「全部完璧にやらないといけないのかな…」とプレッシャーに感じてしまうかもしれません。でも、大丈夫です!
最初は「画面で隠すだけじゃなくて、裏側のサーバーでもう一回『本当にこの人、管理者だっけ?』って確認するクセをつける」という意識を持つだけで、システムの安全性は劇的に向上します。
日々の開発の中で、APIやURLを作るたびに、
「この部屋の鍵、ちゃんと誰でも入れないように確認しているかな?」
と、家の防犯を思い出すように振り返ってみてくださいね。
皆さんの手で、安全で安心なWebの世界を作っていきましょう!応援しています!
コメント