令和4年度春期 情報処理安全確保支援士試験(午後Ⅰ 問1)解説
テーマ: Webアプリケーションの脆弱性(HTTPヘッダインジェクション、SQLインジェクション、メールヘッダインジェクション)、アクセス制御の欠陥、Prepared Statement(プレースホルダ)
目次・設問ジャンプ
設問1 〔Webアプリケーションの各種脆弱性と対策〕について
1. (1) 下線①について
問題文からの引用
「利用者の入力を基にHTTPレスポンスヘッダを生成する処理において、①改行コードを意味する文字列を入力したときに、HTTPヘッダフィールドが追加されないことを確認する。」
着眼点・注目ポイント
HTTPレスポンスヘッダの区切り文字(改行コード)を表すURLエンコード表現(パーセントエンコーディング)を選択します。改行コードはCR(Carriage Return:\r)およびLF(Line Feed:\n)です。
- 正解: ア (%0D%0A)
選択肢の解説
-
ア (%0D%0A): 正解。 ASCIIコードで
%0DはCR(\r)、%0AはLF(\n)を表します。HTTPヘッダの改行(フィールド区切り)として使用されるため、HTTPヘッダインジェクションの検査では%0D%0Aを注入してヘッダの追加やレスポンス分割(HTTP Response Splitting)が可能かを確認します。 -
イ (%20): 不適切。ASCIIコードで
%20は「半角スペース(Space)」を表します。 - ウ (<br>): 不適切。HTML内で改行表示を行うための「HTMLタグ」であり、HTTPレスポンスヘッダの改行(プロトコルレベルの改行コード)ではありません。
2. (2) 下線②について
問題文からの引用
「SQL文の組立てにおいて、SQL文のひな形の中に②変数の場所を示す?記号を置く技法を利用する。」
着眼点・注目ポイント
SQLインジェクション対策において、SQLの雛形に値を直接埋め込まず、動的な値を代入する場所を示す記号(?など)を何と呼ぶかの専門用語が問われています。
- 正解: プレースホルダ
-
解説: SQL文の構文(骨組み)をあらかじめコンパイル・確定させ、変数が挿入される位置に置く記号(
?)のことを「プレースホルダ(Placeholder)」と呼びます。プレースホルダにバインドされた値は単なる「データ(文字列や数値)」として厳格に扱われ、SQL文の構造を変更する悪意あるSQL命令として実行されるのを防ぎます。
3. (3) 空欄 a について
問題文からの引用
「次のいずれかの対策を実施する。
(1) メールヘッダを固定値にする
(2) 外部からの入力を適切に処理するメール送信用APIを使用する
(3) 外部からの入力の全てについて[ a ]を削除する」
着眼点・注目ポイント
メールヘッダインジェクションは、攻撃者がフォーム入力値などに改行コードを注入し、任意のTo/Cc/Bccやヘッダフィールドを追加してスパムメールの送信台頭などに悪用する攻撃です。ヘッダに余分なフィールドを追加させないために外部入力値から削除すべき文字(データ区切り)を特定します。
- 正解: 改行コード
- 解説: メールヘッダインジェクション対策の基本は、ヘッダフィールドとして設定される文字列から「改行コード(CR/LF)」を無効化または削除することです。改行コードが含まれていると、それ以降の入力が新たなヘッダ行や本文(Body)として解釈されてしまうため、外部からの入力値に含まれる改行コードを全て除去することで脆弱性を防ぎます。
設問2 〔情報選択機能の脆弱性〕について
1. (1) 下線③について
問題文からの引用
「プロジェクトの情報番号と情報名を、そのプロジェクトには参加していない利用者が、③そのプロジェクトに参加しているかのように偽ってリスト可能であるという脆弱性を指摘した。」
着眼点・注目ポイント
[情報選択機能の脆弱性] の記述および【方法1】の仕様を読み解きます。問題文には次のように書かれています:
- 「方法1: ログイン時にその利用者IDに対して登録されているプロジェクトIDを取得し、GETリクエストのクエリ文字列に、“
id=プロジェクトID”の形式で指定する。」- 「これは、情報選択機能においてクエリ文字列で受け取ったプロジェクトIDをチェックせずに利用していることに起因していた。」
他人のプロジェクト情報を不正に参照(リスト化)するための具体的・攻撃的なWeb操作を記述します。
- 正解: クエリ文字列のidに未参加のプロジェクトのプロジェクトIDを指定する
-
解説: 方法1では、アクセス制御に必要な情報(
projectId)をクライアント(ブラウザ)のURLクエリ文字列(id=...)に持たせていました。しかし、クライアント側で生成・送信されるパラメータは容易に改変可能です。攻撃者は自身のブラウザのURLパラメータid=プロジェクトIDの値を、自身が参加していない他プロジェクトのID(例:id=102)に変更して送信することで、サーバ側のチェックをかいくぐり他プロジェクトの情報を一覧表示(リスト化)させることができます。
2. (2) 下線④について
問題文からの引用
「方法2: 情報選択機能の利用時に、セッション情報から利用者情報を取得する。情報選択機能は、当該利用者情報からプロジェクトIDを取得する。
情報セキュリティ部は、④方法1の脆弱性が方法2で解決されることを確認した。」
着眼点・注目ポイント
クライアント側で変更可能なパラメータ(方法1)から、サーバ側で安全に管理されているセッション情報(方法2)に変更したことによる効果を答えます。「なぜ偽装できなくなるのか」を明確にします。
-
正解: セッション情報からプロジェクトIDを取得するから
(別解: プロジェクトを示すパラメタを外部から指定できないから) - 解説: 方法2では、利用者の参加プロジェクトIDをクライアント(リクエストのクエリ文字列など)から受け取るのではなく、サーバ側で保持している安全な「セッション情報(利用者情報)」から直接参照・取得します。クエリ文字列などのパラメータとして外部(利用者側)からプロジェクトIDを指定・改変する余地がなくなるため、未参加プロジェクトへの成りすまし・偽装が不可能となり脆弱性が解決されます。
3. (3) 図2中及び図3中の b について
問題文からの引用
8: String sql = "SELECT 情報番号,情報名 FROM 情報管理テーブル WHERE プロジェクトID = ?"; 9: java.sql. [ b ] stmt = con.prepareStatement(sql); 10: stmt.setInt(1, projectId);
着眼点・注目ポイント
JavaのJDBC APIにおける型宣言の空欄です。con.prepareStatement(sql)メソッドが返却するオブジェクトのクラス/インタフェース型を選択します。
- 正解: ウ (PreparedStatement)
選択肢の解説
-
ア (Connection): 不適切。
conの型(java.sql.Connection)であり、データベース接続自体を表すインタフェースです。 -
イ (DriverManager): 不適切。JDBCドライバの管理やデータベース接続(
Connection)を確立するためのクラス(java.sql.DriverManager)です。 -
ウ (PreparedStatement): 正解。
con.prepareStatement(sql)の戻り値の型であり、事前コンパイルされたSQL文(プレースホルダ付SQL)を実行するためのインタフェースです。 - エ (Statement): 不適切。プレースホルダを持たない通常の静的SQLを実行するためのインタフェースです。
4. (4) 図2中の c について
問題文からの引用
9: java.sql.PreparedStatement stmt = con.prepareStatement(sql); 10: [ c ].setInt(1, projectId); 11: java.sql.ResultSet rs = stmt.executeQuery();
着眼点・注目ポイント
9行目で生成したPreparedStatementオブジェクトの変数名に対し、10行目で1番目のプレースホルダ(?)にprojectIdの値をセットするメソッド(setInt)を呼び出しているコードです。
- 正解: stmt
-
解説: 9行目で
java.sql.PreparedStatement型の変数としてstmtが宣言されています。10行目ではこの変数stmtに対してstmt.setInt(1, projectId)を呼び出し、SQL文の最初のプレースホルダ?にprojectId(整数字型)をバインド(代入)しています。
設問3 〔情報表示機能のアクセス制御とSQL文の修正〕について
問題文からの引用
- 「情報セキュリティ部は、情報表示機能にも情報選択機能と同様の脆弱性があることを指摘した。Dさんは、情報表示機能にも同様の修正を行った。」
- 図3の8行目:
8: String sql = "SELECT 情報番号,情報名,情報内容 FROM 情報管理テーブル WHERE [ d ]";
- 図1のE-R図より「情報管理テーブル」の属性:
情報番号(主キー)、プロジェクトID(外部キー)、情報名、情報内容
着眼点・注目ポイント
情報表示機能(ShowServlet)において、「指定された情報番号(documentNo)」を表示するだけでなく、「利用者の参加するプロジェクト(projectId)の情報であること」を同時にアクセス制御・判定するためのSQL文のWHERE句の条件式を組み立てます。図1の属性名を使用すること、およびプレースホルダ(?)を用いることが求められます。
-
正解: 情報番号 = ? AND プロジェクトID = ?
(順不同:プロジェクトID = ? AND 情報番号 = ?) -
解説:
修正前の情報表示機能では、利用者が指定した情報番号(no)だけで検索を行っていたため、他プロジェクトの情報番号を指定された場合にそのまま表示してしまう脆弱性がありました。アクセス制御を正しく行うには、検索条件(
WHERE句)において「指定された情報番号」と「利用者が所属するプロジェクトID」の両方が一致することを検証する必要があります。
プレースホルダ(?)を用いたSQL文の組み立てとしては以下のようになります:
WHERE 情報番号 = ? AND プロジェクトID = ?このSQLを実行することで、該当の情報が利用者の所属プロジェクトに属していない場合(
プロジェクトIDが不一致の場合)、検索結果が0件(ResultSetが空)となり、不正な情報参照を安全に防ぐことができます。