情報処理安全確保支援士試験 過去問 2020年(令和2年) 秋期 午後Ⅱ 問1
百貨店における Web サイトの統合
C 社は、半年ほど前に旧 A 社と旧 B 社が合併してできた会社である。旧 B 社が存続会社となり、旧 A 社の事業を承継した上で、C 社に改称した。C 社は、旧 A 社の 10 店舗の百貨店(以下、A 百貨店という)と、旧 B 社の 5 店舗の百貨店(以下、B 百貨店という)を運営している。
C 社は、旧 A 社が発行していたクレジットカードの会員向け Web サイト(以下、サイト P という)、A 百貨店の取扱商品を販売するオンラインストア Web サイト(以下、サイト Q という)、及び旧 B 社のポイントカードを保有する会員向け Web サイト(以下、サイト R という)を運営している。
合併後、旧 A 社クレジットカードの B 百貨店での利用を促進したり、旧 B 社ポイントカードの A 百貨店での利用を可能にしたりするなど、両社の顧客サービスの融合に力を入れている。表 1 は、サイト P、Q、R の概要である。
| サイト名 | 機能 | 利用者 ID |
|---|---|---|
| サイト P |
|
英数字 8〜16 字の文字列を利用者が設定する。 |
| サイト Q |
|
英数字 8〜16 字の文字列を利用者が設定する。 |
| サイト R |
|
ポイントカードに記載されている数字 8 桁の会員番号が割り当てられる。 |
機器の集約と運用作業の効率化
C 社では、運用作業を効率化するために、別々の場所に設置されていた各サイトを構成する機器を 1 か所のデータセンタに集約するとともに、これらの機器を管理する Web 管理課を新設した。機器集約後のネットワーク構成は図 1 のとおりである。
サイト P、Q、R は、それぞれ独立して運営されている。いずれのサイトも、アカウント情報はサイトごとに設置した LDAP サーバのユーザエントリとして管理しており、ログイン時の認証には、各 LDAP サーバのユーザエントリ内の利用者 ID とパスワードを利用している。
サイト間でのアカウントの共通利用
C 社では経営戦略の一環として、三つのサイトで収集した情報から顧客の購買傾向を分析することにした。そこで、サイト P、Q、R でクロス分析などの手法を用いて購買傾向を分析する上で、各サイト間で同一の顧客を特定するために、サイト P、Q、R 相互間でのアカウントの共通利用を実現することにした。
アカウントの共通利用では、次の三つの利用方法のいずれかを各顧客に選択してもらうことにした。
- サイト P のアカウントを親アカウントとし、サイト Q、R のアカウントを子アカウントとして、子アカウントを親アカウントに紐付ける。主に旧 A 社の顧客向けである。
- サイト R のアカウントを親アカウントとし、サイト P、Q のアカウントを子アカウントとして、子アカウントを親アカウントに紐付ける。主に旧 B 社の顧客向けである。
- アカウントの共通利用をしない。
顧客がアカウントの紐付けを設定すれば、子アカウントの代わりに親アカウントを用いて各サイトにログインできる。
アカウントの共通利用の設計
Web 管理課の J 主任は、アカウントの共通利用の設計を任された。J 主任は、アカウントの共通利用を実現するために、次の四つを行うことにした。
- サイト P、Q、R のログイン処理を変更する。
- LDAP-P、LDAP-R で管理するアカウント情報に、紐付け情報を保存する。具体的には、LDAP-P のユーザエントリに siteQid、siteRid 属性を追加して、当該アカウントに紐付けた子アカウントの利用者 ID を保存する。LDAP-R のユーザエントリには、sitePid、siteQid 属性を追加する。なお、紐付け前の sitePid、siteQid、siteRid には、空文字列が設定される。
- Web-P、Web-R の Web アプリケーションプログラム(以下、Web アプリケーションプログラムを Web アプリという)に、アカウントの紐付け機能を追加する。
- FW-P、Q、R のルールに対して必要な変更を行う。例えば、変更後の FW-P のルールは、表 2 のようになる。
サイト P のアカウントを親アカウントとし、サイト Q のアカウントを子アカウントとして紐付けるときのサイト P の画面と処理内容は図 2 のとおりである。
| 項番 | 送信元 | 宛先 | プロトコル | 動作 |
|---|---|---|---|---|
| 1 | 監視サーバ、管理コンソール、Web 管理課 LAN | Web-P、LDAP-P | 管理用プロトコル | 許可 |
| 2 | Web-Q、Web-R | LDAP-P | LDAP | 許可 |
| 3 | Web-P | a | b | 許可 |
| : | : | : | : | : |
| 15 | 全て | 全て | 全て | 拒否 |
注記1 FW-P は、ステートフルパケットインスペクション型である。
注記2 項番が小さいルールから順に、最初に合致したルールが適用される。
注記3 項番 4〜14 には、LDAP に関するルールは記述されていない。
個人情報の取扱い
J 主任は、C 社の法務担当の M さんに、アカウントの共通利用について説明し、個人情報の取扱いの観点から問題がないかどうか相談した。M さんは、合併前後の個人情報の利用目的の内容について確認した。
確認後、M さんは、アカウントの共通利用には、顧客に対して利用目的の変更を通知して、同意を得る必要があると指摘した。
指摘を受け、J 主任は、顧客がアカウントの共通利用を選択したときに、個人情報の利用目的の変更を通知するとともに、変更後の利用目的を明示して同意を得る機能を加えることにした。
コードレビュー
アカウントの共通利用の設計を終えた J 主任は、サイト P の Web アプリの改修に着手した。
図 3 及び図 4 は、サイト P のアカウントにサイト Q のアカウントを紐付ける場合のサイト P 上での紐付け処理の Java ソースコードである。
利用者が、サイト P にログイン後、図 2 の画面を操作し、「紐付け」ボタンをクリックした場合、図 4 の行番号 101 の siteID にサイトの識別文字列として "siteQ" が代入された状態で図 4 のコードの実行が開始される。図 4 のコードが正常に終了したら、紐付けが完了したことを表示する。
(省略) // パッケージ宣言、インポート宣言
// インポート宣言には、javax.naming.NamingException を含む。
1: public class AccountLink {
2: boolean childChecked; // 子アカウントの利用者 ID のチェック完了フラグ
3: String childSite; // 子アカウントのサイトの識別文字列
4: String childID; // 子アカウントの利用者 ID
5: String childPW; // 子アカウントのパスワード
6: String parentID; // 親アカウントの利用者 ID
7: public static final int NO_ERROR = 0; // 正常終了コード
8: public static final int ERROR_SITE_UNAVAILABLE = -101; // エラーコード
9: public static final int ERROR_ID_OR_PW = -102; // エラーコード
10: public static final int ERROR_LINK_FAILED = -103; // エラーコード
11: public AccountLink(String site, String id, String pw, String loginID) {
12: childChecked = false;
13: childSite = site;
14: childID = id;
15: childPW = pw;
16: parentID = loginID;
17: }
18: public int checkChild() throws NamingException {
// サイトの識別文字列のチェック
19: childChecked = childSite.equals("siteQ") || childSite.equals("siteR");
20: if (!childChecked) { // サイトの識別文字列が正当でなかった場合
21: return ERROR_SITE_UNAVAILABLE;
22: }
23: switch (childSite) {
24: case "siteQ":
25: try {
// 認証情報チェック
26: if (siteQAuth(childID, childPW) == NO_ERROR) {
27: childChecked = true; // 認証成功
28: } else {
29: childChecked = false; // 認証失敗
30: }
31: } catch (NamingException e) { // 認証が実行できなかった場合
32: throw e;
33: }
34: if (!childChecked) {
35: return ERROR_ID_OR_PW;
36: } else {
37: return NO_ERROR;
38: }
39: case "siteR":
(省略)// サイト R に対して認証を行い、結果に応じて ERROR_ID_OR_PW 又は
// NO_ERROR を返して終了する。
40: default:
(省略)// ERROR_SITE_UNAVAILABLE を返して終了する。
41: }
42: }
43: public int makeLink() throws NamingException {
(省略)// LDAP-P 上の parentID のユーザエントリの属性 siteQid 又は siteRid
// に childID を書き込む。
44: }
45: private int siteQAuth(String qID, String qPW) throws NamingException {
(省略)// 認証情報を確認し、認証成功なら NO_ERROR を、認証失敗なら NO_ERROR
// 以外の値を返す。必要な通信ができないなど、認証そのものが実行
// できない場合、例外 NamingException を投げる。
46: }
(省略)// その他のメソッドなどの定義
47: }
101: AccountLink idPair = new AccountLink(siteID, userID, userPassword, loginId);
// 各変数には次の内容が代入されている。
// siteID には、紐付けるアカウントのサイトの識別文字列
// userID には、紐付けるアカウントの利用者 ID
// userPassword には、紐付けるアカウントのパスワード
// loginId には、現在サイト P にログインしている利用者 ID
102: int result = AccountLink.NO_ERROR;
103: for (int retryCount = 1; retryCount < 4; retryCount++) {
104: try {
// サイトの識別文字列、利用者 ID/パスワードの組みを確認する。
105: result = idPair.checkChild();
106: if (result == AccountLink.NO_ERROR) {
107: break;
108: } else {
(省略)// result の値に従って適切な処理を実施する。
109: }
110: } catch (NamingException e) {
(省略)// 再試行のために、一定時間待つ。
111: }
112: }
113: if (!idPair.childChecked) {
114: return AccountLink.ERROR_LINK_FAILED;
115: }
116: try {
117: idPair.makeLink(); // アカウントの紐付けを実施する。
118: } catch (NamingException e) {
(省略)// 例外処理
119: }
J 主任は、情報処理安全確保支援士(登録セキスペ)の K 主任とともにコードレビューを実施した。K 主任は、次のような特定の状況では、サイト P のある利用者のアカウントに、サイト Q の他人のアカウントが紐付いてしまうと指摘した。
- 図 2 で、サイト Q の利用者 ID 欄に誤った利用者 ID を入力する。
- 図 4 のコードが呼び出され、cに誤った利用者 ID が代入されたまま、dが呼び出される。
- 何らかの理由で、d中の図 3 中の行番号eでfが発生し、結果としてdが再試行される。
- dが 3 回試行され、全て同じくfが発生すると、gの値は true なので、図 4 中の行番号hに進み、紐付けが行われる。
K 主任は、図 3 の 32 行目前後に着目し、iという修正案を提示した。
サイト R でのインシデント
リリースに向けて準備を進めていたところ、インシデント発生の報告があった。
発端は、ある顧客からの指摘で、その内容は、"サイト R のキャンペーン応募履歴を見たら、3 月のキャンペーンに応募したことになっているが、身に覚えがない。3 月にはサイト R に一度もアクセスしていないはずだ。"というものであった。
J 主任が、サイト R のアクセスログを確認したところ、次のことが分かった。
- 3 月 30 日に、当該顧客のアカウントでキャンペーンに応募していた。
- 応募の直前にパスワード失念時の処理を実行し、パスワードを電子メール(以下、メールという)で未登録のメールアドレスに送信した記録がある。
- 3 月 25 日から 3 月 31 日に掛けて、サイト R への通信量が増加傾向にあった。
図5は,サイトRのパスワード失念時の操作画面を示している。
J 主任は、攻撃者がパスワード失念時の処理を悪用して、会員番号及び誕生日を総当たりで入力し、たまたま合致した当該顧客のアカウントを乗っ取ったものと判断した。J 主任は、このインシデントについて Web 管理課の L 課長に報告した。L 課長は旧 A 社出身で、この報告でサイト R のパスワード失念時の操作を初めて知った。
次は、その報告の時の L 課長と J 主任の会話である。
L 課長: サイト R のパスワード失念時の処理には、三つの問題がある。一つ目は、本人であることを確認するための情報が少なすぎるという問題だ。そこは後で解決するとしよう。二つ目は、パスワードそのものをメールで送るという問題だ。三つ目は、jという問題だ。二つ目と三つ目の問題の解決には、kように改修すべきだ。この方法では、一部の利用者はパスワード失念時にログインできなくなるが、その場合はコールセンタで対応することにしよう。
J 主任: はい、分かりました。
L 課長: サイト R では、攻撃者がアカウントを乗っ取ったとしても、あまり経済的利益を得られないので、今回のような被害で済んだと考えられるが、直ちに改修を完了させてはいけない。もしもこれらの問題に気付かずにアカウントの共通利用を提供していたら、①利用者に更に大きな被害が発生するところだった。アカウントの共通利用の設計、及びリリースまでのスケジュールも見直してほしい。
アカウントの共通利用の設計の見直し
J 主任は、次のように全面的に設計を見直し、承認を得た。
- サイト S を立ち上げ、新たにサイト S のアカウントを発行して管理する。
- アカウントの共通利用に当たり、アカウントの紐付け時とサイト P、Q、R へのログイン時には、SAML プロトコルの Web Browser SSO Profile を用いる。サイト S が、IdP (Identity Provider) となり、サイト P、Q、R は、SP (Service Provider) となる。
- サイト Q には、サイト Q のアカウントでも、サイト Q のアカウントと紐付けたサイト S のアカウントでもログインできる。サイト P、R も同様である。
図 6 は、Web Browser SSO Profile の基本的な通信の流れである。
図 7 は、紐付け済みのサイト S のアカウントでサイト Q にログインするときの画面遷移図である。
図 8 は、サイト Q のアカウントとサイト S のアカウントを紐付けるときの画面遷移図である。
見直し後のアカウント共通利用の提供開始
C 社は、サイト P、Q、R の改修とサイト S の開発を完了して、アカウント共通利用の提供を開始し、順調に運用を続けた。サイト P、Q、R のアカウントの廃止、及びサイト S のアカウントへの統合を目指している。この統合が実現すれば、図 7 の (あ)や、図 8 の (え)、(お)などの画面は不要となり、より使いやすいサイトを実現できる。