情報処理安全確保支援士過去問題 令和5年春期 午後Ⅰ 問1

⇄問題PDFと解説を画面2分割で開く⇱問題PDF

設問1

解答入力欄

    • a:
    • b:
    • c:
    • d:

解答例・解答の要点

    • a:13
    • b:in
    • c:WHERE head.order_no = ?
    • d:PreparedStatement stmt = conn.prepareStatement(sql)
  • 解説

    • aについて〕
      ディレクトリトラバーサルは、ユーザーが入力したファイル名をパラメータとして受け取り、それをもとに処理を行うアプリケーションに対して行われる攻撃手法です。IPAの「安全なウェブサイトの作り方 改訂第7版」では、外部からのパラメータでファイル名を直接指定する実装を避けることが対策と紹介されています。

      表1項番2の指摘内容には「ファイルアクセスに用いるパス名の文字列作成で利用者が入力したデータを直接使用している」とあります。図1の13行目にて納品書PDFを参照するパスを文字列結合にて生成しています。これが指摘内容に該当します。〔受託したシステムの概要〕には「Y社とY社の得意先が注文番号を基に注文情報を照会する機能(中略)Y社とY社の得意先が納品書のPDFファイルをダウンロードする機能などがある」と記載されています。これにより、利用者が注文番号を入力して納品書PDFをダウンロードする操作を行うことが読み取れます。変数 inOrderNo にユーザーが入力した注文番号が格納されると考えられるので、指摘内容とも一致します。したがって、空欄aには「13」が入ります。

      a=13

    • bについて〕
      Javaではデータベース接続やファイルなどのメモリ以外のリソースはガーベジコレクションによって解放されません。リソースが解放されない状態が続くとメモリが枯渇するおそれがあります。リソースを解放するには、finally句にてcloseメソッドを用いて明示的に解放する方法があります。図1の14行目で納品書PDFに書き込むためのリソースを変数 in に格納していますが、他の箇所にcloseメソッドなどでリソースを解放するコードが見当たりません。したがって、空欄bには「in」が入ります。

      b=in

    • cについて〕
      SQLインジェクション攻撃は、利用者から入力情報を基にSQL文を組み立てる処理に問題がある場合、攻撃者が入力したSQLがデータベース上でそのまま実行されてしまい、データベースに蓄積された情報の改ざんや非公開情報の閲覧ができてしまう攻撃です。解決策として、IPAの「安全なウェブサイトの作り方 改訂第7版」では、SQL文の組み立てはすべてプレースホルダで実装する方法と、特別な意味を持つ記号文字(「`」や「¥」)をエスケープ処理する方法が紹介されています。プレースホルダとは、利用者入力部分に特殊文字(?など)を割り当てたSQLのひな形を用意し、特殊文字部分には実行時にエスケープ処理された値を割り当てる仕組みです。

      図1の8行目では、変数 inOrderNo を文字列結合してSQL文を生成しています。変数 inOrderNo にはエスケープされていない入力値が格納されているので、SQLインジェクションの脆弱性があります。よって、プレースホルダでSQL文を組み立てるコードに修正します。「WHERE head.order_no = 」までは書き写せば十分です。しかし、「inOrderNo」の値は実行時に決まるのでプレースホルダで置き換えます。したがって、空欄cは「WHERE head.order_no = ?」となります。

      c=WHERE head.order_no = ?

      dについて〕
      Javaでプリペアドステートメントを利用するには、java.sql.ConnectionのpreparedStatement メソッドを用いて PreparedStatement インタフェースのオブジェクトを生成します。引数にはプレースホルダを含むSQL文を指定します。したがって、空欄dは「PreparedStatement stmt = conn.preparedStatement(sql)」となります。

      d=PreparedStatement stmt = conn.prepareStatement(sql)

    設問2

    解答入力欄

      • e:
      • f:
      • g:
      • h:
      • i:
      • j:

    解答例・解答の要点

    • e:orderNo
    • f:static
    • レースコンディション
    • g:String orderNo
    • h:new
    • i:getOrderInfoBean(orderNo)
    • j:得意先コード
  • 解説

    • eについて〕
      空欄eの前に書かれている不具合の詳細を確認すると、「ある得意先の利用者IDでログインしてから注文番号を入力すると,別の得意先の注文情報が出力される」とあります。図4の注文番号から注文情報を選択するソースコードを変数に格納される値を意識しながら読んでいきます。
      • 変数 orderNo をクラス変数(後述)として宣言(2行目)
      • サーブレットクラスから受け取った注文番号を変数 orderNo に格納(4行目)
      • 注文情報を取得するSQLをプリペアドステートメントで組み立てる(8~10行目)
      • 10行目のプレースホルダに注文番号を当てはめて、注文ヘッダーテーブルの注文番号との完全一致で注文情報を取得(11~12行目)
      以上のことから、変数 orderNo が原因で異なる得意先の注文情報が取得されたことがわかります。念のために図3のE-R図を確認すると、注文番号が異なれば得意先コードも異なる可能性があることが読み取れます。したがって、空欄eには「orderNo」が入ります。

      e=orderNo

    • fについて〕
      変数 orderNo がどのような変数か答える問題です。Javaの変数は❶クラス変数、❷インスタンス変数、❸ローカル変数の3種類があります。
      クラス変数
      一つのクラスごとに値を共有する変数。staticキーワードをつけて宣言する
      インスタンス変数
      一つのインスタンスごとに値を保持する変数
      ローカル変数
      メソッド(関数)やブロック({ … })の内側でのみ利用できる変数
      3種類の変数のうち、クラス変数とインスタンス変数は複数のスレッド(プログラムの実行単位のこと)から同時に値が読み取られる可能性があります。ローカル変数はスレッドごとに固有の値を持つため、複数のスレッドから同時に読み取られることはありません。図4の変数 orderNo はクラス変数ですので、複数のスレッドから値を同時に読み取ることが可能です。したがって、空欄fには「static」が入ります。

      f=static

    • (1)の不具合のように、複数のスレッド(マルチスレッド)で動作するアプリケーションにて複数のスレッドが同じデータをほぼ同じに更新すると、(本来は予期しない)後続の処理が先行する処理の結果を上書きしてしまう現象が発生します。これを「レースコンディション」といいます。スレッド間でのリソースのアクセス順序が重要であり、実行のタイミングによって異なる結果が生じる場合にレースコンディションが発生します。

      ∴レースコンディション

    • gについて〕
      図6のソースコードでは注文情報を取得する getOrderInfoBean メソッドを修正しています。(2)の空欄fおよび(3)より、変数 orderNo をローカル変数に修正すればレースコンディションの脆弱性を回避できます。ローカル変数に修正するには、(1)の通りに2行目から5行目のソースコードを削除したのち、getOrderInfoBean メソッドを注文番号を引数とするメソッドに修正します。Javaでは引数は「引数の型 引数名」の形式で宣言します。引数の型は図5の3行目より String、引数名は図4の11行目より orderNo です。したがって、空欄gは「String orderNo」となります。

      g=String orderNo

      hについて〕
      空欄hを含むコードは OrderInfoBL クラスのインスタンスを生成するものです。Javaではインスタンスを生成する際には「new クラス名」の形式を使用します。したがって、空欄hには「new」が入ります。

      h=new

      iについて〕
      修正前の図5の5行目のコードでは、OrderInfoBL クラスのクラスメソッド getOrderInfoBean を利用して注文情報を取得しています。空欄gの解説で述べたように、修正後の getOrderInfoBean メソッドでは、注文番号を格納した変数を引数に指定します。getOrderInfoBean メソッドを呼び出すコードが書かれている図5を見ると、3行目と直後のコメントには、注文番号は変数 orderNo に格納されることが書かれていますので、この変数を引数に指定すればよいことがわかります。したがって、空欄iには「getOrderInfoBean(orderNo)」が入ります。

      i=getOrderInfoBean(orderNo)

    • jについて〕
      〔システムテスト〕によるとセッションオブジェクトには、利用者ID、得意先コード、得意先名が格納されています。また、注文ヘッダーテーブルのE-R図には「得意先コード」があります。よって、以下の流れで実装すれば(4)の保険的対策が可能です。
      • 10行目の抽出条件に、注文ヘッダーテーブルの得意先コードとの完全一致条件をAND条件として追加する。得意先コードの値が割り当てられる部分には10行目と同じくプレースホルダを指定する
      • 得意先コードをセッションオブジェクトから取り出して変数に格納する
      • psObj.setString(2, 得意先コードを格納した変数)のようにプレースホルダに得意先コードの値を割り当てる
      したがって「得意先コード」が正解です。なお、同じく注文ヘッダーテーブルのE-R図にある「注文番号」は図4の変数 orderNo に格納されて、10行目の抽出条件においてすでに使われているので対象外です。

      j=得意先コード
    © 2014-2024 情報処理安全確保支援士ドットコム All Rights Reserved.

    Pagetop