情報処理安全確保支援士試験

令和5年秋季 情報処理安全確保支援士試験 午後1 問1 現役セキュリティエンジニアが解いてみた(解説もあるよ!)

エンジニアです。技術力向上のため、安全確保支援士試験をたまに解いています。

出典:令和5年度 秋期 情報処理安全確保支援士試験 午後問題

問1

問題を読んでいきます。

Webアプリケーションプログラムについての問題が来ました。
Webアプリケーションのセキュリティは、WebブラウザとWebサーバ(APサーバ含む)によって実現しています。

ECサイトのドメイン名は”□□□.co.jp”であり、利用者はWebアプリQにHTTPSでアクセスします。
CORSやCookieのDomain属性に関する問題ではないかと想像します。
プロトコルはHTTPSのため、CookieはHttpsOnly属性などが絡んできそうです。あとは、HTTPSによるサーバ認証がかかわってきそうですね。

WebアプリQに、ECサイトの会員による商品レビュー機能を追加したとあります。
「会員」による「商品レビュー」機能です。XSSなどの脆弱性が問題となりそうです。

2. ログイン機能
会員IDとパスワードで会員を認証する。ログインした会員には、セッションIDをcookieとして払いだす。

JWTではありませんでした。やはり、Cookieに関連する問題のようです。

5. 商品レビュー機能
…(中略)
レビュータイトルとレビュー詳細の欄は自由記述が可能であり、それぞれ50字と300字の入力文字数制限を設けている

入力文字数制限は、XSSの対策になるケースがあります。何かありそうですね。

6.会員プロフィール機能
…(中略)クレジットカード情報を登録するページを提供する。
…(中略)アイコン画像のアップロードは、次をパラメータとして、”https://□□□.co.jp/user/upload”に対して行う。
・画像ファイル
・”https://□□□.co.jp/user/profile”にアクセスして払い出されたトークン


パラメータのトークンが、”https://□□□.co.jp/user/profile”にアクセスをして払い出されたものと一致したときは、アップロードが成功する。
この辺りは重要なポイントになりそうです。

図3
…(中略)
<div class=”review-title”>Good<script>xhr=new XMLHttpRequest();/*</div>
…(中略)
<div class=”review-title”>*/url1=”https://□□□.co.jp/user/profile”;/*</div>
…(中略)
<div class=”review-title”>*/xhr2.send(form);)<script></div>
…(中略)

非同期通信をするための、XMLHttpRequestオブジェクトが生成されています。複数行コメントアウト(/* */)を使って、何か怪しいことをやっていますね。

WebアプリQがCookieにHttpOnly属性を付与していないこと及びアップロードされた画像ファイルの形式をチェックしていないことも確認した。

XMLHttpRequestを使うことで、攻撃者のサーバにdocument.cookieでセッション値を送ることができてしまいますね。

答え合わせをしてみました。

文章の意図をつかめずかなり間違えた印象です。
私の回答と模範解答を見比べていきます。

設問1

(1)

私の回答:ウ [ 反射型XSS ]

模範解答:イ [ 格納型XSS ]

XSSの種類を意識することが多くないのでうかつにも間違えてしまいました。
DOM Based XSSの定義が特によくわかりませんでした。

GETメソッドによるリクエストでサイトへ副作用を起こす設計は、減ってきているため、 [ 反射型XSS ] 自体減っていそうな印象があります。

参考:

IPAテクニカルウォッチ「DOM Based XSS」に関するレポート

(2)

問題で質問されていることが、WebアプリQで今行われている対策なのか、今後必要な対策なのかがわかりませんでしたが、恐らく今後必要な対策を問われていると思い回答をしました。
文章内に書いているXSS脆弱性について質問をされているので、画像ファイルの形式チェックは含めないで回答しました。

私の回答:cookieにHttpOnly属性を付与する(23文字)
模範解答: レビュータイトルを出力する前にエスケープ処理を施す。

根本的な対策ではありませんが、私の回答は対応の一つにはなるので、部分点くらいはもらえるのではないかと思います。
cookieにHttpOnly属性を付与すれば、図4の13行目でのcookie変数に入るのは「undefined」になります。ただ、undefinedという文字列?が画像としてアップロードされるため、数か月後にアプリQでは、同じデータを持つバイナリデータのファイルが大量に発見されたという話を耳にしそうです。

問題文に書いている問題点を記載するのが、安パイだと思いましたが不適切でした。
根本的な対策と質問してくれていれば、回答できたのに…と思う次第です。

設問2

私の回答:複数のレビュータイトルにコメントアウトを使って、1つのスクリプトになるように埋め込んだ
模範解答:HTMLがコメントアウトされ一つのスクリプトになるような投稿を複数回に分けて行った。

似たようなことを記載しています。
回答時に、文字数上限についての記述があり、「なぜレビュー詳細にスクリプトを埋め込まなかったのか」と思いました。図2の会員Bが [ ( > _ < ) ] という文字を使ってしましたが、図3の [ (&gt;_&lt;) ] よりHTMLの特殊文字に変換されていることがわかりました。
これにかなりこだわってしまい、かなり時間をかけてしまいました。わかりにくい問題文でした。

スクリプト以外のタグをコメントアウトしない場合に、どのような動作になるのか疑問でしたので、検証結果を記載しています。

設問3

(1)

私の回答:レビューページ表示時、トークンを用いて、アクセスしたユーザのCookieを会員プロフィール画像としてアップロードする。

模範解答:XHRのレスポンスから取得したトークンとともに、アイコン画像としてセッションIDをアップロードする。

回答以上に読み込みと知識が必要な問題でした。
まず、XSRFを防ぐために、重要な処理をする場合にはトークンをWebサーバ側で照合をします。
トークンの埋め込みかたは、重要な処理を送信するページ(例:ログインページ)に埋め込みます。
図4の8行目では、トークンのオブジェクトをページが取得しているということです。

そのほかはバニラのJavaScriptを読むことができればおおよそ回答することができたと思います。

JavaScriptから画像データをアップロードするコードは書いたことがないため、セッションIDがどのような形式になっているのかが気になりますので、検証結果を記載しています。

(2)

私の回答:レビューページにアクセスし、各ユーザのicon.pngをa.pngに変更したファイルを取得する。

模範解答:会員のアイコン画像をダウンロードして、そこからセッションIDの文字列を取り出す。

a.pngをファイル名としてアップロードするため、a.pngとしてファイルがアップロードされると思いましたが、誤りでした。これは、アップロードする側の端末のファイル名であり、サーバに配置されるファイル名ではありませんでした。
JavaScriptで画像ファイルをアップしたことが多くないことが表出しました。

(3)

私の回答:セッションを奪い、被攻撃者のクレジットカードで攻撃者が商品を購入できる。

模範解答:ページVにアクセスした会員になりすまして、WebアプリQの機能を使う。

「なりすまし」という言葉が重要だと思われます。
具体的な攻撃手法を記述していますが、おそらく正答になると思われます。
ただ、会員がログアウトボタンを押してログアウトしている場合には、

設問4

私の回答:アクセスしたページと異なるオリジンからのレスポンスを受け取れない仕組み。

模範解答:スクリプトから別ドメインのURLに対してcookieが送られない仕組み

CORSポリシーについて聞かれたと思いましたが、読み違えていました。
ブラウザはCookieのDomain属性とPath属性によって指定されたスコープに合わせて、Cookieを送信します。

デフォルトの設定であれば、攻撃者が用意したサイトとサイトQではFQDNが異なるため、サイトQのCookieは送出されません。
まさか、このような初歩的な問題が出題されるとは思いませんでした。

気になったことの検証

設問2 スクリプトをコメントアウトしない場合にどうなるのか

scriptタグで閉じないHTMLソースを作成して、Webブラウザから開いてみます。

</script>以降はブラウザ側で補完をしています。この時、console.log(“aaaa”)は実行されません。

設問3 (1) 文字列を画像形式でアップロードした場合にどのように保存されるか

Cookieは文字列です。それを [ image/png ] 形式としてサーバへアップロードしていました。
利用者は意識をしませんが、Webブラウザへ入力して送信する情報は、ブラウザによって適切なエンコーディングをされています。
HTTPプロトコルでは、バイナリデータとASCII文字くらいしか送ることができません。そのため、日本語などの文字列はパーセントエンコーディングを使って、エンコードされています。

問題のように、HTMLの <form> を使用せずとも、JavaScriptを使ってHTTPリクエストを送ることができます。その時に、ブラウザの介入を受けてHTTPリクエストが送信されるのかがはっきりとしていなかったため、それを検証してみます。
問題を例にすると、特別にエンコード処理をせずとも、Cookieがバイナリ形式のエンコードされるのかを確認するということです。

問題文のコードでファイルをアップロードするとどのようにファイルがアップロードされるのか

問題文のコードを実行した場合に、どのようにファイルがアップロードされるのか確認してみます。
動作はGoogle Chromeの最新版で確認をしています。

下記はfileアップロードのコードです。

ファイルをアップロードしたときの通信内容を見ると下記の通りでした。

アップロードをしたファイルのContent-Typeは [ image/png ] としてアップされています。
アップされたファイルにアクセスしてみるとこのような結果になります。

ブラウザから対象のファイルにアクセスしてみても、 [ thisiscookie ] という文字列を取得するのは難しそうです。

curlを使うと、そのままデータを表示できるようで、このようにすればセッションCookieを取得できました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です