PR 本記事には広告(Amazonアソシエイト・もしもアフィリエイト・A8.net等)が含まれます。掲載情報の正確性には努めていますが、商品の詳細は必ずリンク先で最新情報をご確認ください。
CTF・セキュリティ学習

【プロフィール編集編】IDOR・マスアサインメント・保存型XSSの罠|CTF思考フレームワーク #07

かも次郎とアンペンが「プロフィール編集」を解説するマスコットイラスト
安全に生きたい編集部

こんにちは、アンペンです!

前回は、ファイルアップロードで「中身」と「置き場」の両方が大事という話をしました。

今回は、すでにログイン中の利用者が自分の情報を書き換える機能、プロフィール編集を見ていきます。「自分のページなんだから安全でしょ?」と感じる場所こそ、IDORやマスアサインメントの温床になりやすいテーマです。

自分のプロフィールを編集するだけだよね?何が危ないの?

『誰のプロフィールか』をサーバー側でチェックしていないと、他人のプロフィールも書き換えられることがあるんだ。

プロフィール編集って、ログインした自分の画面ですよね。だからつい『ここは安全地帯』と思いがち。でも実は、ここは“自分のものを触っているつもりが、他人のものまで触れてしまう”という、ちょっと怖い落とし穴が潜む場所なんです。今日はその仕組みを、会員票の窓口にたとえながらほどいていきましょう。読み終わるころには、『自分のページ=安全』が思い込みだったと分かるはずです。

まず結論

プロフィール編集は「誰が・どの項目を・どんな値で」更新するかをサーバー側で必ず確認しないと、IDORで他人を書き換えたり、マスアサインメントで管理者権限を奪われたり、保存型XSSで他者の画面が乗っ取られたりします。

この記事で分かること

  • IDOR・マスアサインメント・保存型XSSの3つの仕組み
  • 「自分のページだから安全」が成り立たない理由
  • 演習環境での観察方法と、守る側の基本対策
難易度:はじめて向け 所要時間:10分 体験:編集リクエストを観察する おすすめ:#06の後

📖 はじめてのWebセキュリティ #07|プロフィール編集編
「自分の情報を更新する画面」から、IDOR・マスアサインメント・保存型XSSの考え方を学びます。 シリーズ一覧を見る →

⚠️ 大事なお約束
この記事の確認は、CTF・公式ラボ・自分で作った検証環境だけで行ってください。実在するサービスで他人のIDに書き換えて送信する、隠しフィールドを改ざんして送る、といった行為は不正アクセス等に該当する可能性があります。

プロフィール編集は「誰が・どの項目を・どう保存するか」が全て

プロフィール編集の通信を見ると、たいてい「対象ユーザーのID」と「更新する項目の値」がセットで送られています。

このとき、サーバー側で「送信した人のセッション」と「対象ユーザーのID」が一致しているかを確認しないと、他人のIDに書き換えるだけで、別人のプロフィールを編集できてしまいます。

言いかえると、安全の分かれ目は『サーバーが本人確認をしているか』の一点に尽きます。送られてきた“宛名”をそのまま信じて処理してしまうのか、それとも「いまログインしているのは、本当にこの番号の人?」と毎回チェックするのか。たったこれだけの違いで、自分専用のはずの画面が、誰でも他人を書き換えられる画面に変わってしまうんです。

ふだん意識しませんが、プロフィールを保存するとき、ブラウザはこっそり『これは誰のデータか』という情報——たとえば user_id=123 のような番号——も一緒にサーバーへ送っています。画面には出てこないこの“宛名”が、実はカギ。もしこの番号を別人のもの(user_id=456)に書き換えて送ったら、サーバーはどう反応するでしょう?——そこを確かめないと、事故が起きます。

図解:自分の編集とIDORの違い

プロフィール編集画面で「user_id=123」(自分)と「user_id=456」(他人)を比較した図
サーバーで本人確認しないと、対象IDを書き換えるだけで他人のプロフィールも編集できてしまう。

普通の編集と、対象IDだけ書き換えた編集を比べると、サーバー側のチェックが甘いとどんなことが起きるかが見えます。

会員票の管理者専用欄に「役職」「割引率」が勝手に書き足されている様子のたとえ図
本来書けない欄に値を書き足される=マスアサインメント。サーバー側で更新を許す項目を限定する必要がある。
🪪 たとえるなら、会員票の書き換え

窓口で会員票を書き換えるとき、本人確認をせずに「会員番号」だけで提出を受け付けたら、他人の会員番号を書いた人にも書き換えを許してしまいます。さらに、会員票には本来書き込めない「役職」「割引率」などの欄が用意されていれば、悪意のある人はそこにも値を書き足そうとします。

ここで覚える用語:IDOR(アイドール)
Insecure Direct Object Reference の略です。URLや送信データに含まれる「対象のID」を書き換えるだけで、本来アクセスできないはずの他人のデータを操作できてしまう問題です。

IDORの怖さは、その手軽さにあります。特別な道具も高度な技術もいりません。URLや送信データの中の番号を「123」から「124」に一つずらすだけ。それで隣の人のデータが見えたり書き換えられたりするなら、攻撃者はただ番号を順に試していくだけでいい。鍵のかかっていないロッカーが、番号順にずらりと並んでいる——そんなイメージです。

プロフィール編集から狙われる3つの攻撃

この画面から狙われる攻撃は、大きく3つです。『他人になりすまして書き換える(IDOR)』『画面にない項目をこっそり送る(マスアサインメント)』『自己紹介欄に罠を仕込む(保存型XSS)』。バラバラに見えて、根っこは同じ。どれも“サーバーが、送られてきた値を無防備に信じてしまう”ことから起きています。

代表的な3つの攻撃パターン

IDOR・マスアサインメント・保存型XSSの3攻撃パターンを示したカード型インフォグラフィック
①IDOR ②マスアサインメント ③保存型XSS――守りの基本はサーバー側の認可と入力検証。
  • IDOR:対象ユーザーIDを他人のものに書き換えて、他人のプロフィールを編集する
  • マスアサインメント:画面に表示されていない「管理者フラグ」「権限」などの項目に値を追加して送信し、権限昇格を狙う
  • 保存型XSS:プロフィール欄(自己紹介など)にスクリプトを保存し、他の利用者が表示したときに実行させる

OWASP API Security Top 10 でも、API1(BOLA: Broken Object Level Authorization)とAPI3(Broken Object Property Level Authorization)として、IDORとマスアサインメントは上位に登場しています。

とくにイメージしづらいのが、真ん中の『マスアサインメント』かもしれません。仕組みはこうです。編集画面には名前とメールしか出ていなくても、攻撃者はリクエストに自分で「is_admin=true」のような“画面にない項目”を書き足して送れます。もしサーバーが「送られてきた項目を全部そのまま保存」する作りだと、ただのユーザーが一瞬で管理者に化けてしまう。そして3つ目の『保存型XSS』は、#04で見た反射型と違って、罠が“サーバーに保存される”のが厄介なところ。自己紹介欄に仕込んだスクリプトが、それを見た人みんなの画面で動いてしまうんです。

ここから先は『自分の目で確かめる』番ですが、大前提を必ず守ってください。実験は自分のテストアカウントか、CTF・演習環境の中だけ。他人のIDに書き換えて送る行為は、たとえ「画面が変わるか試すだけ」のつもりでも、不正アクセスにあたる可能性があります。安全な範囲で「リクエストに何が入っているか」を眺めるだけでも、十分すぎる学びになります。

CTFでやってみよう:編集リクエストを観察する

やってみよう / 演習環境限定

送信される項目を観察し、「誰の何を更新しているか」を読み解こう

目的は他人のアカウントを書き換えることではなく、編集リクエストに含まれる項目を理解することです。

  1. CTFや自分の検証環境で、プロフィール編集ページを開く
  2. ブラウザ開発者ツールのネットワークタブで、保存ボタンを押したときのリクエストを確認する
  3. 送信されている項目を一覧化し、「ユーザーID」「役割」「権限」などの隠し項目があるか確認する
  4. サーバーから戻る応答に、本来見えないはずの項目が含まれていないか観察する
  5. 同じリクエストで、送信していない項目を増やしてサーバーが受け入れるか調べる(自分のアカウントで)
他人のID・他人のアカウントで実験する、本物のサービスに送る、といった行為は絶対にやめてください。確認は自分のラボ・自分のテストアカウントの範囲だけです。

観察してみると、保存ボタン一つで意外なほど多くの項目が送られていることに気づくはずです。そしてもう一つ大事な発見が。『画面に入力欄がない=送れない』ではない、ということ。攻撃者はブラウザの画面ではなく、サーバーに届くリクエストを直接組み立ててくるからです。つまり、画面側のどんな制限も“飾り”にすぎません。本当の関所は、サーバー側にしか作れないんです。

じゃあ、編集する相手のIDも、画面から送らないほうがいいの?

鋭いね。いちばん安全なのは、IDを画面から受け取らず、『いまログインしている人』の情報をサーバー自身が握っているセッションから取り出すこと。そうすれば、そもそも他人のIDを指定しようがない。どうしても受け取らざるをえないときだけ、本人かどうかを毎回照合する——これが鉄則だよ。

守る側なら、サーバーで「誰の・どの項目を」を必ず確認しよう

守る側では、画面上の制限ではなく、サーバー側の認可チェックを中心に組み立てます。「画面に出ていないから安全」ではなく、「サーバーが受け取った値だけで判断できるか」を考えます。

守るための基本チェック
  • 編集対象のIDは、リクエストから受け取らず、セッションのログイン情報から取得する
  • どうしてもIDを受け取る必要があるときは、サーバー側で「ログイン中の本人か」を必ず照合する
  • 更新可能な項目はホワイトリストで指定し、入力に含まれていても保存しない項目を明示する
  • 「役割」「権限」「課金プラン」などの重要項目は、ユーザー向けAPIから一切更新できないようにする
  • プロフィール欄を画面に表示するときは、HTMLエスケープを必ず通し、保存型XSSを防ぐ
  • 変更履歴を保存し、不審な書き換えを後から追跡できるようにする

『画面に出ていない=送れない』とは限らないんだね。

そう。攻撃者はブラウザ画面より、サーバーに届くリクエストを直接組み立てるから、判断はサーバー側で完結させる必要があるよ。

ここまでをひと言で言うと、プロフィール編集の主役は『認可(オーソリゼーション)』です。認証(ログインできたか)とは別物で、「この人に、この操作を、この相手に対してやる資格があるか」を確かめること。ログインさえ通れば何でもできてしまう、では困るわけですね。認証は“入館証”、認可は“どの部屋に入れるか”——この2つは別だと覚えておくと、ぐっと整理がつきます。

まとめ:プロフィール編集は「サーバー側の認可」が主役

今回のポイント
  • IDOR・マスアサインメント・保存型XSSの3つの典型攻撃を意識する
  • 編集対象のIDは、リクエストよりもセッション情報から決めるのが基本
  • 更新可能な項目はサーバー側でホワイトリスト指定する
  • プロフィール欄の表示にはHTMLエスケープを必ず通す

今日の持ち帰りは『画面ではなく、サーバーで決める』。誰のデータか・どの項目を更新してよいか・表示は安全か——この3つをサーバー側でしっかり握っていれば、IDORもマスアサインメントも保存型XSSも、まとめて入口を塞げます。逆に画面の作り込みだけで守ろうとすると、必ずどこかをすり抜けられてしまう、というのが今日の教訓です。

次回は、利用者の身分証にあたるセッション・Cookieを扱います。奪われると一発で全部終わってしまうこの「身分証」を、なぜ守りきれないことがあるのかを見ていきましょう。

次に読みたい記事

参考資料

記事URLをコピーしました