utsuroi access control labs Lab 05 / 5 — Practitioner
05

クライアント側のみの権限判定

UI-only authorization checks

うつろい EC のマイページには、ユーザロールによって表示される機能が変わる UI がある。一般会員には「会員退会」ボタンだけ表示、管理者には「他ユーザを削除」ボタンも表示される。

フロントエンドは v-if="user.role === 'admin'" 等で表示制御している。しかしサーバ側の POST /api/admin/delete-user エンドポイントには認可チェックが無い。一般会員でも、開発者ツールから API を直接呼べば実行できてしまう。

一般会員(UI には削除ボタンが表示されない)として、API を直接呼んで他ユーザを削除してください。

マイページ — user_a として表示

会員情報を編集
会員退会

↑ 一般会員のあなたには「他ユーザを削除」ボタンは表示されません。これは UI 上だけの制御。

ブラウザの開発者ツールで JS を実行する想定。ボタンを押すと、UI を介さずに API リクエストを送信できます。

POST /api/admin/delete-user
サーバ応答
(まだ呼び出していません)
脆弱なフロント + サーバ
// フロント (Vue) — UI 制御だけで認可を実装したつもり
<button v-if="user.role === 'admin'" @click="deleteUser(targetId)">
  削除
</button>

// サーバ (Express) — 認可チェックなし
app.post('/api/admin/delete-user', (req, res) => {
  if (!req.session.user) return res.status(401).end();
  // ★ admin かどうかのチェックがない
  User.deleteById(req.body.user_id);
  res.json({ status: 'ok' });
});

フロントエンドのコードはユーザのブラウザで動くので、攻撃者は完全に制御できる。UI 制御は UX 改善のためのものであって、セキュリティ機構ではない。サーバ側で必ず認可を実装する必要があります。

正解(ネタバレ)

「直接 API 呼び出し」を押すだけで成功します。サーバ側のエンドポイントは認可チェックを行っていないため、一般会員のセッションでも管理者専用 API が実行できてしまいます。

これは Lab 02 と並ぶ「縦の認可」不備の典型例。フレームワークの認可ミドルウェアを使えば自動的にチェックされる場面で、開発者が「フロントで隠したから大丈夫」と省略してしまうケースが多い。