令和4年度 春期 情報処理安全確保支援士試験 午後Ⅰ 問1|「他人のプロジェクトが丸見え」——情報処理安全確保支援士で学ぶアクセス制御不備のセキュリティインシデント事例
この記事で扱うセキュリティ事例
- 試験区分: 情報処理安全確保支援士
- 出典: 令和4年度 春期 情報処理安全確保支援士試験 午後Ⅰ 問1
- 主なテーマ: アクセス制御(認可)の設計上の考慮不足と実装不備による情報流出、セキュアコーディング、HTTPヘッダインジェクション、SQLインジェクション、メールヘッダインジェクション、プレースホルダとPreparedStatement
この記事は「情報処理安全確保支援士 午後問題 全70問」シリーズの1本です。→ 全70問の一覧・テーマ別索引はこちら
導入: なぜこの事例が重要なのか
「ログインさえできていれば、その人は信頼できる利用者だ」——システムを作るとき、私たちは無意識のうちにそう考えてしまいがちです。しかし、ログインできること(認証)と、その人にこの情報を見せてよいかどうか(認可・アクセス制御)は、本来まったく別の問題です。この区別が曖昧なまま設計を進めると、正規の利用者が、本来見えてはいけない他人のデータをのぞけてしまう、という事故が起きます。
情報処理安全確保支援士試験の午後Ⅰで出題されたこの事例は、Webアプリケーションを開発する会社を舞台に、まさにその「認証はできているのに認可が甘い」という落とし穴を扱っています。派手なゼロデイ脆弱性や高度な攻撃技術は出てきません。むしろ怖いのは、ごく普通に設計したつもりのアクセス制御に、たった一つの考慮漏れがあっただけで、参加してもいないプロジェクトの情報が一覧に並んでしまった、という地味で現実的な失敗だという点です。
この記事を読むと、「外部から渡された値をそのまま信じて使う」ことがなぜ危険なのか、認可の判断材料を「利用者が自由にいじれる場所」に置くとどうなるのか、そしてそれをどう直すのかが、ストーリーとして見えてきます。あわせて、HTTPヘッダインジェクションやSQLインジェクション、メールヘッダインジェクションといった、Webアプリ開発で必ず押さえておくべき脆弱性検査の考え方も一通り整理します。受験対策としてはもちろん、システムを発注・開発する立場の方にとっても「安全なアプリを作るとはどういうことか」を考える教材になるはずです。
インシデントの概要
舞台は、H社というWebアプリケーションプログラム(以下、Webアプリ。ブラウザを通して使うソフトウェア)を開発する、従業員200名の会社です。H社では、開発部がWebアプリを開発し、別の部署である情報セキュリティ部が、できあがったプログラムに弱点がないかを調べる脆弱性検査を担当していました。作る人と、その安全性をチェックする人を分けている——この体制自体は、健全なものです。
H社には、開発部が自分たちで作って使っている「Sシステム」というWebシステムがありました。コーディングルール(プログラムの書き方の社内ルール)をはじめ、各種の情報を社内で共有するための仕組みです。利用者はSシステムにログインしたうえで、情報を投稿したり、投稿された情報を表示したりできます。投稿された情報はデータベース(情報をためておく倉庫のような仕組み)に格納されていました。
ログインから情報表示までの流れは、ごくありふれたものです。利用者がIDとパスワードを入力してログインに成功すると、メニュー画面が表示される。「情報の表示」を選ぶと、表示できる情報の一覧がプルダウン(クリックすると候補がずらりと出てくる選択メニュー)に並ぶ。たとえば「番号1001 コーディングルール」のように、情報番号と情報名がリストされます。そこから見たいものを選んで「表示」ボタンを押すと、その情報の中身が画面に出てくる。なお、ログイン後はセッションID(ログイン時に発行される、利用者を識別するための推測困難な文字列)を使って「いま操作しているのが誰なのか」を管理していました。
ここまでは、何の問題もないように見えます。インシデントの芽が生まれたのは、このSシステムを「改修」しようとしたときでした。
何が起きたのか

ある時期、開発部で新しいプロジェクトをいくつか立ち上げることになりました。それに伴い、各プロジェクト内での情報共有を強化したい、という要望が出ます。これまでSシステムで共有していたのは、誰もが見てよい社内ルールのような情報でした。しかしこれからは、各プロジェクトの計画書や設計情報といった、プロジェクト内の人だけに見せたい機微な情報も共有したい。そこで開発部は、こうした情報については「表示できる利用者を、その情報を作った人と同じプロジェクトに参加している人だけに限定する」という方針を立てました。
この改修を任されたのが、開発部のDさんです。Dさんは、利用者ごとのアクセス制御をこう設計しました。まず、プロジェクトを区別するための「プロジェクトID」を連番で割り振る。次に、利用者IDごとに、その人が参加しているプロジェクトのプロジェクトIDを登録しておく。さらに、Sシステムに格納する一つひとつの情報にも、作成者が参加しているプロジェクトを示すプロジェクトIDをあらかじめ付けておく。なお、開発部員は、ある時期には一つのプロジェクトにしか参加せず、同時に複数のプロジェクトに参加することはない、という前提がありました。こうしておけば、「この利用者のプロジェクトID」と「この情報のプロジェクトID」を突き合わせて、一致するものだけを見せればよい——理屈としては筋が通っています。
問題は、肝心の「プロジェクトIDをどこから取ってくるか」でした。Dさんが最初に採用した設計、すなわち方法1は次のようなものでした。利用者がログインしたとき、その利用者IDに登録されているプロジェクトIDをいったん取得する。そして、GETリクエスト(ブラウザがサーバに送る要求の一種)のクエリ文字列——URLの末尾に「?」に続けて付けるパラメータ部分——に、「id=プロジェクトID」という形でその値を埋め込む。情報を選ぶ画面(情報選択機能)は、そのクエリ文字列からプロジェクトIDを読み取って、表示できる情報を絞り込む。一見すると、ログイン時に正しいプロジェクトIDを取り出しているのだから、安全に思えます。
しかし、ここに致命的な見落としがありました。クエリ文字列は、利用者がブラウザのアドレスバーから自由に書き換えられる場所なのです。サーバが「id=2」という形でプロジェクトIDを渡しても、利用者はそれを「id=3」にでも「id=99」にでも、手で書き換えてアクセスし直すことができます。つまり、認可の判断材料であるプロジェクトIDを、よりによって「利用者が自由にいじれる場所」に置いてしまっていたのです。
改修後の脆弱性検査で、情報セキュリティ部はこの弱点をはっきりと突きました。あるプロジェクトに参加していない利用者が、クエリ文字列のidに、自分が参加していない別のプロジェクトのプロジェクトIDを指定する。すると情報選択機能は、そのIDを何のチェックもせずに受け取り、まるでその利用者がそのプロジェクトに参加しているかのように扱って、本来見えてはならないプロジェクトの情報番号と情報名を一覧に並べてしまったのです。攻撃と呼ぶには拍子抜けするほど単純で、特別なツールも知識も要りません。ただURLの数字を一つ書き換えるだけ。それだけで、他人のプロジェクトの情報がのぞけてしまう。情報セキュリティ部の指摘は明快でした——これは、情報選択機能が「クエリ文字列で受け取ったプロジェクトIDをチェックせずに利用している」ことに起因する脆弱性だ、と。
指摘を受けたDさんは、設計を見直します。提示したのが方法2です。今度は、情報選択機能を使うときに、クエリ文字列ではなくセッション情報——ログイン中の本人を管理するためにサーバ側で保持している情報——から利用者情報を取り出す。そして、その利用者情報からプロジェクトIDを取得する。こうすれば、プロジェクトIDの出どころが「利用者が外からいじれるクエリ文字列」から「利用者が書き換えられないサーバ側のセッション情報」へと移ります。利用者はもはやプロジェクトIDを外部から指定できなくなる。情報セキュリティ部は、この方法2によって方法1の脆弱性が確かに解決されることを確認しました。Dさんは、プロジェクトIDの取得方法を方法2に修正します。
ただし、話はこれで終わりではありませんでした。情報を選ぶ「情報選択機能」だけでなく、選んだ情報の中身を実際に表示する「情報表示機能」にも、同じ種類の弱点が潜んでいたのです。情報表示機能は、URLの「show?no=1001」のように、表示したい情報番号をクエリ文字列で受け取って中身を返す仕組みでした。ここでもし、情報番号だけを頼りにデータベースから中身を引いてしまうと、利用者は情報番号さえ別の値に書き換えれば、自分のプロジェクト以外の情報の中身まで読めてしまいます。一覧に出さないようにしただけでは不十分で、中身を取り出すときにも「この情報は、本当にあなたのプロジェクトのものか」を確かめなければ、流出は防げないのです。情報セキュリティ部はここも見逃さず、情報表示機能にも情報選択機能と同様の脆弱性があると指摘し、Dさんは同じ考え方で修正を行いました。
ここから先は

情報処理安全確保支援士(登録セキスペ)の午後問題、「読んでも頭に入らない」と感じていませんか?本シリーズでは、2017年〜2025年の過去…
この記事が気に入ったらチップで応援してみませんか?
