情報処理安全確保支援士試験 過去問 2025年(令和7年) 秋期 午後 問1
コンサルティング業務で利用するSaaSのセキュリティ
H社では、コンサルティング業務で利用するSaaS(以下、Sサービスという)を提供している。コンサルティング業務を行う企業50社程度がSサービスを利用しており、総利用者数は1,000名程度である。
Sサービスの概要
Sサービスでは、利用企業ごとに複数のプロジェクトを登録できる。Sサービスの利用者には2種類のロールがある。自社の全てのプロジェクトの情報にアクセスできる管理者と、自身に割り当てられているプロジェクトの情報だけにアクセスできる一般利用者である。
Sサービスには、プロジェクトを管理する機能(以下、プロジェクト管理機能という)のほか、利用者がプロジェクト内で特定の話題ごとに「スレッド」と呼ばれるページを作成する機能(以下、スレッド作成機能という)、スレッドに文章を投稿したりファイルをアップロードしたりする機能(以下、スレッド投稿機能という)などが設けられている。
Sサービスの主な機能を表1に示す。
| 機能名 | 機能概要 | 備考 |
|---|---|---|
| ログイン(省略) | (省略) | (省略) |
| 利用者管理 | 管理者が、利用者の登録及び変更を行う。 | 登録された利用者には、利用企業内で一意となる利用者IDが発行される。利用者IDの形式は次のとおりである。 "U"と数字8桁をつなげた文字列 |
| ロール管理 | 管理者が、利用者のロールを設定する。 | 処理の流れは次のとおりである。 1. ログイン後の画面からロール管理機能を選択すると、パス"/management/role"にリクエストがGETメソッドで送信される。csrf_tokenという一時的でランダムな文字列のトークンが発行され、ロール設定画面が表示される。 2. ロール設定画面で任意の利用者のロールを変更し、確定ボタンをクリックすると、パス"/management/roleset"に対して、パラメータcsrf_token、is_admin及びuser_idを含むリクエストがPOSTメソッドで送信される。パラメータis_adminは指定した利用者のロールに応じて次のいずれかが設定される。 - 管理者:is_admin=1 - 一般利用者:is_admin=0 |
| プロジェクト管理 | 管理者が、プロジェクトの登録及び変更を行う。また、プロジェクトに一般利用者を割り当てる。 | プロジェクトには、利用企業内で一意となるプロジェクトIDが発行される。プロジェクトIDの形式は次のとおりである。 "P"と数字8桁をつなげた文字列 |
| タスク管理 | 利用者が、プロジェクトのタスク管理画面からタスクを登録し、タスクの担当者を割り当てる。また、タスクの更新を行う。 | タスクには、次の項目を設定する。 ・タスク名 ・タスクの詳細説明 ・タスクの担当者 ・タスクの締切日 ・タスクの進捗状況 ・タスクの完了フラグ |
| スレッド作成 | 利用者が、スレッドを作成する。 | スレッドの作成時は、アクセスできる一般利用者を指定する。管理者は利用企業内の全てのスレッドにアクセスできる。 |
| スレッド投稿 | 利用者が、アクセスできるスレッドに投稿とファイルのアップロードを行う。アップロードされたファイルは、ファイル識別子が一意になるように変更されてからサーバに保存される。 | アップロードできるファイルの拡張子は、docx、xlsx、pptx、pdf、jpg、gif及びpngの7種類である。アップロードされたファイルは、スレッドにアクセスできる利用者だけがアクセスできる。ファイルの参照時及びダウンロード時のパスは次のとおりである。 /files/[一意のファイル識別子].[拡張子] |
| プロジェクト進捗管理 | 利用者が、プロジェクトの進捗を管理する。スケジュールの作成及び管理並びにタスクの進捗確認を行う。 | 未完了のタスクのうち締切日を過ぎたものは、プロジェクト進捗管理画面にそのタスク名と締切日からの経過日数が表示される。 |
Sサービスでは、半年ごと及び新機能リリース前に診断ツールXによる脆弱性診断を実施することにしている。診断ツールXは、送信したリクエストとそれに対するレスポンスから脆弱性を検出する。
SサービスではHTTPレスポンスヘッダーにContent Security Policy(CSP)を設定している。図1に、SサービスのHTTPレスポンスヘッダーの例を示す。
HTTP/1.1 200 OK Cache-Control: no-store Content-Encoding: gzip Content-Type: text/html; charset=UTF-8 Date: (省略) X-Frame-Options: SAMEORIGIN Strict-Transport-Security: max-age=31536000; includeSubDomains Set-Cookie: JSESSIONID=e962879ef251f21l7460cf0d5ce714e3; Secure; HttpOnly Content-Security-Policy: default-src 'self'; Content-Length: 31337
図1の設定では、リソースの読込みとスクリプトの実行に関する動作は次のようになる。
- Sサービス以外のドメインからのリソースの読込み:a
- scriptタグ内に直接記述されたスクリプトの実行:b
インシデントの発生とその調査
ある日、Sサービスを利用しているB社の管理者からH社に対して、「Sサービスの一般利用者であった元従業員Zのローカル PC上に、元従業員Zが割り当てられていなかったプロジェクトのファイルが保存されていたので、Sサービスに不具合がないか調査してほしい」との依頼があった。
Sサービスのシステム担当者であるUさんは、ログを確認することとともに、B社の許可を得た上で、B社の管理者の利用者IDを使ってログインし、幾つかの画面を確認した。そのうち、プロジェクト進捗管理画面のHTMLを図2に、そのHTMLが参照していたF1234567890.xlsxというファイルをテキストエディターで開いたときの内容を図3に示す。
<html>
<head>
<meta charset="UTF-8">
<title>プロジェクト進捗管理</title>
<link href="/static/css/style.css" rel="stylesheet" type="text/css">
<script src="/static/js/action.js"></script>
</head>
<body>
<h1>プロジェクト進捗管理(プロジェクトID:P00395000)</h1>
(省略)
<div name="alert">
<div name="alert-title">期限切れタスク一覧</div>
<div name="alert-description">
次のタスクが締切日を過ぎています。<br>
</div>
<ul className="delayed-task">
<li>G社のコンペ資料作成(締切日過ぎ1日)</li>
<li>G社の業界分析(締切日過ぎ4日)</li>
<li>個人タスク<script src="/files/F1234567890.xlsx"></script>(締切日過ぎ5日)</li>
</ul>
</div>
(省略)
</body>
</html>
(async function(){
const response = await fetch("/management/role");
const text = await response.text();
// 次の2行で csrf_token を取得
const tokenMatch = text.match(/id="csrf_token"[^>]+value="([^"]+)"/);
const csrfToken = tokenMatch[1];
await fetch("/management/roleset", {
method: "POST",
// POST メソッドのリクエスト body
body: new URLSearchParams({
"csrf_token": csrfToken,
"is_admin": "1",
"user_id": "U00331001"
})
})
})();
Uさんは、調査の結果、図4に示す攻撃が実行されていたことを確認した。
- 元従業員Zの利用者IDでアクセスできるスレッドに、F1234567890.xlsxをアップロードした。
- 当該利用者IDで、タスク管理画面からcに次の文字列を指定して、タスクを登録した。
文字列:d - その後、2で登録したタスクが次の条件を満たしたときに、eがプロジェクト進捗管理画面にアクセスした。
条件:未完了の状態で、かつ、f - 3の結果、図2のHTMLがeのWebブラウザに出力された。
- 4の結果、図3のスクリプトが実行された。
- 5の結果、元従業員Zの利用者IDであったU00331001に対して次の処理が行われた。
処理:g(省略) - 元従業員Zの利用者IDで、調査依頼の発端となったファイルをダウンロードした。
Uさんは、図4の項番2と類似した文字列が指定されたタスクが登録されていないかどうかを確認したところ、完了済みタスクの中に類似したものがあることを確認した。しかし、このタスクによる攻撃は、CSPの設定で防御できていた。
Uさんは、攻撃者がこの失敗の原因を分析し、失敗したときに使用した文字列に①工夫を加えることによって図4の項番2の文字列を作成し、攻撃を成功させたと推測した。
インシデントへの対応及び攻撃への対策
Uさんは、まず必要なインシデント対応を行った。その結果、図4以外に成功した攻撃はないことが分かった。Uさんは、結果をB社の管理者に報告した。また、ほかの利用企業で同様の攻撃がなかったかどうかを調査したところ、なかったことも分かった。
次に、図4と同様の攻撃を防止するために、次の対策を行った。
- 図4の項番1については、アップロードされたファイルが許可された拡張子であることのチェックに加えて、次の処理を追加する。
処理:h - 図4の項番4について、類似の問題がないかどうか、Sサービス全体を確認したところ、問題は1箇所だけだったので、表1の機能のうち、iについて、②必要な処理を追加する。なお、この処理が行われていないという脆弱性は、診断ツールXでは検知されない。
開発プロセスの見直し検討
Uさんは、図4の項番4の脆弱性のように診断ツールXで検知されないものであっても、検知できる可能性のある検査として、次の二つも実施するという開発プロセスの見直し案を作成した。
- SAST
- j
Uさんは、開発プロセスの見直し案について承認を得て、見直しに着手した。