【情報処理安全確保支援士試験 令和5年度 春期 午後1 問1 No.2】

情報処理安全確保支援士試験 令和5年度 春期 午後1 問1

【出典:情報処理安全確保支援士試験 令和5年度 春期 午後1 問1(一部、加工あり)】

[システムテスト]
 システムテストを開始したところ、注文情報照会機能において不具合が見つかった。この不具合は、ある得意先の利用者IDでログインして画面から注文番号を入力すると、別の得意先の注文情報が出力されるというものであった。なお、ログイン処理時に、ログインした利用者IDと、利用者IDにひも付く得意先コード及び得意先名はセッションオブジェクトに保存されている。
 注文情報照会機能には、業務処理を実行するクラス(以下、ビジネスロジッククラスという)及びリクエスト処理を実行するクラス(以下、サーブレットクラスという)が使用されている。注文情報照会機能が参照するデータベースのE-R図を図3に、Eさんが作成したビジネスロジッククラスのソースコードを図4に、サーブレットクラスのソースコードを図5に示す。

 D主任、Eさん、Fさんは、不具合の原因が特定できず、セキュアプログラミングに詳しい技術課のHさんに協力を要請した。
 Hさんはアプリケーションログ及びソースコードを解析し、不具合の原因を特定した。原因は、図4で変数(e)が(f)として宣言されていることである。この不具合は、①並列動作する複数の処理が同一のリソースに同時にアクセスしたとき、想定外の処理結果が生じるものである。
 原因を特定することができたので、Eさんは、Hさんの支援の下、次の4点を行った。

⑴図4の2行目から5行目までのソースコードを削除する。
⑵図4の6行目を、図6に示すソースコードに修正する。

⑶図5の4行目と5行目を、図7に示すソースコードに修正する。

⑷保険的な対策として、図4の10行目の抽出条件に、セッションオブジェクトに保存された(i)と注文ヘッダテーブルの(j)の完全一致の条件をAND条件として追加する。

 ソースコードの修正後、改めてシステムテストを実施した。システムテストの結果は良好であり、システムがリリースされた。

e:orderNo、f:static、下線①の不具合は何と呼ばれるか。15字以内で答えよ。:レースコンディション

原因は、図4で変数(e)が(f)として宣言されていることである。この不具合は、①並列動作する複数の処理が同一のリソースに同時にアクセスしたとき、想定外の処理結果が生じるものである。
 まず①の不具合のことをレースコンディションと言います
 Javaのクラス変数には以下の変数があります。

  • クラス変数:すべてのインスタンス共有される変数で、メソッド(関数)の外でstaticで宣言する
  • インスタンス変数:インスタンス毎に属する変数で、メソッドの外でstatic無しで宣言する
  • ローカル変数:メソッド内でのみ有効な変数で、メソッドの中で宣言する

 そして、レースコンディションの可能性があるのはクラス変数であり、インスタンスで共有されるため複数の処理が同時発生した場合に、意図しないタイミングで変数が書き変わってしまいます。
 対策としては、ローカル変数にすることで他のインスタンスの影響を受けないようになります。
 図4でクラス変数を宣言している2行目の「private static String orderNo; //注文番号」が該当箇所になります。

g:String orderNo、h:new、i:getOrderInfoBean(orderNo)

 「⑴図4の2行目から5行目までのソースコードを削除する。
 レースコンディションの可能性となるクラス変数を格納する処理の部分を削除します。

 「⑵図4の6行目を、図6に示すソースコードに修正する。

 修正前は「public static OrderInfoBean getOrderInfoBean(){」で、getOrderInfoBean関数がクラス変数orderNoに格納された注文番号を基にSQLを実行します。
 クラス変数を削除したため、getOrderInfoBean関数が注文番号を引数(ローカル変数)として定義する必要があり、getOrderInfoBean(String orderNo)となります。

⑶図5の4行目と5行目を、図7に示すソースコードに修正する。

 修正前は「OrderInfoBL.setOrderNo(orderNo);」「OrderInfoBean orderInfoBeanObj = OrderInfoBL.getOrderInfoBean();」で、同様にクラス変数に格納された注文番号を基にSQLを実行します。
 こちらもローカル変数で扱うようにして、OrderInfoBLクラスでインスタンスを新しく生成するために「OrderInfoBL orderInfoBLObj = new OrderInfoBL();」とし、getOrderInfoBean関数で注文番号(orderNo)を引数として設定します。

j:得意先コード

⑷保険的な対策として、図4の10行目の抽出条件に、セッションオブジェクトに保存された(i:getOrderInfoBean(orderNo))と注文ヘッダテーブルの(j)の完全一致の条件をAND条件として追加する。
 図4の10行目は「sql = SQL + “WHERE head.order_no = ?”; //抽出条件:注文ヘッダーテーブルの注文番号と画面から入力された注文番号との完全一致」です。
 そして、セッションオブジェクトについては、「なお、ログイン処理時に、ログインした利用者IDと、利用者IDにひも付く得意先コード及び得意先名はセッションオブジェクトに保存されている。」とあります。
 セッションオブジェクトと注文ヘッダーテーブルの両方にあるもを探すと、得意先コードであることが分かります。
 そもそもの今回の不具合は「この不具合は、ある得意先の利用者IDでログインして画面から注文番号を入力すると、別の得意先の注文情報が出力されるというものであった。」というものでしたので、得意先の情報を一致させればいいと想像できるかと思います。