【実務・中級編】APIにおけるBroken Object Level Authorization (BOLA) の検知と対策 – アプリケーションセキュリティ & 安全な開発防御ガイド

なぜ「BOLA」は開発者の盲点になるのか?——ID連番の悪夢を断ち切る設計術

「ログインさえしていれば安全」と信じているエンジニアほど、実は危うい。

こんにちは。セキュリティチームのチーフとして、日々国内外の侵入テストやインシデント対応に奔走していると、現場で最もよく目にする「致命的なミス」があります。それが BOLA (Broken Object Level Authorization:オブジェクトレベルの認可不備) です。

SQLインジェクションやXSSは、今やWAFが自動的に弾いてくれる時代になりました。しかし、BOLAは違います。これは「機能としては正しく動いているが、アクセスしてはいけない他人のデータが見えてしまう」という、アプリケーションロジックの根幹に潜む悪魔だからです。

1. BOLAはなぜ防げないのか?(攻撃者の視点)

攻撃者は、あなたのAPIをまるで「宝探し」のようにスキャンします。

例えば、ユーザープロフィールを表示するAPIが以下のようなリクエストを送っているとしましょう。

GET /api/v1/users/12345/profile

攻撃者は、この 12345 という数字を 12346、12347 と書き換えるだけです。バックエンドが「現在ログインしているユーザー」のIDと、リクエストされたIDを突き合わせる処理を忘れていれば、他人の個人情報は丸見えになります。

PoCの現場感覚:
我々がペネトレーションテストを行う際、自動化ツールでIDをインクリメントさせ、レスポンスのHTTPステータスコードやデータ量を監視するだけで、数分で脆弱なAPIを特定できます。「認証(Authentication)」はできているのに、「認可(Authorization)」が抜けている。これがBOLAの正体です。

—

2. 「コピペ不可」な設計思想を捨てろ

よくある失敗は、コントローラーの先頭で「if ($user->id !== $requested_id)」と個別に書くことです。これでは、エンドポイントが増えるたびに必ず書き忘れる箇所が出てきます。

鉄則:認可は「ビジネスロジック層」で強制する。
コントローラーに処理を委ねるのではなく、リポジトリ層やサービス層の手前で、リソースの所有権を保証する設計(DecoratorパターンやMiddlewareの活用)を取り入れるべきです。

—

3. 実践:セキュアな実装サンプル(Node.js / Express)

「ユーザーが自分の注文履歴のみを取得できる」APIを例に、セキュアな実装を示します。

/

  • 認可ロジックを強制するミドルウェア
  • 「リソースID」と「ログインユーザー」が一致することをDBレベルで検証する

/
const authorizeOrderAccess = async (req, res, next) => {
const { orderId } = req.params;
const userId = req.user.id; // 認証済みトークンから取得

// 肝:単なるID比較ではなく、DBクエリで「所有者」を突き合わせる
const order = await db.orders.findOne({
where: {
id: orderId,
owner_id: userId // ここが最大の防壁。他人のIDを指定してもヒットしない
}
});

if (!order) {
// 404 Not Foundを返すことで、リソースの存在自体も隠蔽する
// 403 Forbiddenを返すと「そこにリソースがある」と攻撃者に教えることになる
return res.status(404).json({ error: “Order not found” });
}

req.order = order; // 取得したオブジェクトを後続の処理に渡す
next();
};

// ルート定義
app.get(‘/api/orders/:orderId’, authenticateToken, authorizeOrderAccess, (req, res) => {
// ここに来た時点で、そのユーザーの所有物であることが確定している
res.json(req.order);
});

4. WAFとインフラでできる「最後の砦」

アプリケーション側の改修が完了するまでの間、あるいは多層防御として、WAF(AWS WAFなど)によるリクエストのフィルタリングも有効ですが、BOLAはビジネスロジックに依存するため、WAFだけで完璧に防ぐことは困難です。

ただし、「IDの推測を困難にする」ことは重要です。

  • UUID v4の採用: 連番(1, 2, 3…)を廃止し、推測不能なID(550e8400-e29b-41d4-a716-446655440000)を公開IDとして使用してください。内部的なDBのプライマリキー(ID)と、外部公開用の公開ID(UUID)を分離する設計が、大規模システムでは標準です。

—

まとめ:チーフからのアドバイス

BOLAを防ぐためのチェックリストは以下の3点です。

1. IDは連番にするな: 推測可能なIDは脆弱性の入り口です。UUIDへの移行を検討してください。
2. 認可の「一元管理」: コントローラーに認可ロジックを散らばらせず、ミドルウェアやService層で強制的に所有権チェックを通す仕組みを作りなさい。
3. 404を賢く使う: 権限がない場合、可能な限り404を返し、リソースの存在すら攻撃者に悟らせないこと。

セキュリティは「完璧な製品」を買えば終わるものではありません。設計という名の「泥臭い一手間」の積み重ねが、顧客の信頼を守ります。今日から、君たちのAPIコードを見直してみてください。案外、簡単に他人のデータにアクセスできてしまうかもしれませんよ?

それでは、セキュアなコーディングを。

コメント

タイトルとURLをコピーしました