PR

Webシステムのセキュリティ対策

2018年9月26日(水)
棚橋 英之

はじめに

昨今、SNSやオンラインショッピング、インターネットバンキングなど、様々な形でWebシステムが活用されています。Webシステムは非常に便利かつ有用な仕組みですが、Webシステムの脆弱性を悪用されると、Webシステムの利用者がマルウェアに感染されたり、機密情報が漏洩したりと、様々な被害に遭う恐れがあります。そのため、Webシステムを公開する立場としてはそのWebシステムのセキュリティ対策を適切に行う必要があります。特に、多くのWebシステムではWebアプリケーションを用いており、Webアプリケーションの脆弱性に対する対策が非常に重要です。

過去の情報処理安全確保支援士試験では、代表的なWebアプリケーションの脆弱性に関する問題が午前/午後の双方で頻出されています。

今回はWebシステム、特にWebアプリケーションの脆弱性とその対策について解説します。

Webアプリケーションの脆弱性

例題として、情報処理安全確保支援士 平成29年春期 午前Ⅱ 問12を考えてみましょう。

問12 Webアプリケーションの脆弱性を悪用する攻撃手法のうち,Webページ上で入力した文字列がPerlのsystem関数やPHPのexec関数などに渡されることを利用し,不正にシェルスクリプトを実行させるものは, どれに分類されるか。

ア HTTPヘッダインジェクション
イ OSコマンドインジェクション
ウ クロスサイトリクエストフォージェリ
エ セッションハイジャック

情報処理安全確保支援士試験では、この問題と類似の問題がよく見られます。正解は(イ)ですが、各選択肢のキーワードは様々な形で出題されるため、正解を導くだけでなく、各選択肢について正しく理解することも重要です。

各選択肢について、それぞれ解説します。

(ア)HTTPヘッダインジェクション

HTTPヘッダインジェクションはユーザの入力値をHTTPレスポンスヘッダに含める際に発生する脆弱性です。攻撃者は入力値に改行コードを含めることにより、レスポンスに対して任意のヘッダフィールドやボディを追加できます。

HTTPヘッダインジェクションにより、任意のスクリプトの埋め込みや、任意のCookieが発行される場合があります。

HTTPヘッダインジェクションの主な対策を表1に示します。どちらも、攻撃者による改行コードを含ませないための対策です。

表1:HTTPヘッダインジェクションの主な対策

概要 詳細
ヘッダ出力用の専用APIを利用する プログラミング言語などに予め用意されている専用のヘッダ出力用APIなどライブラリ機能を用いる。
ただし、実行環境やライブラリによっては改行コードを適切に処理できないケースがあるため、次の対策との併用が推奨される
改行コードのチェックを行う 改行コードのチェックを行い、改行が含まれていたらエラーとみなして処理を停止したり、改行コード以降の文字を削除したりする

(イ)OSコマンドインジェクション

Webアプリケーション開発に用いる多くのプログラミング言語には、WebサーバのOSコマンド(Windowsのコマンドプロンプトで利用するコマンドやUNIX/Linuxのbashで利用するコマンドなど)を呼び出す機能があります。これらを悪用して不正にOSコマンドを実行する攻撃手法をOSコマンドインジェクションといいます。

また、Perlの場合はファイルを開くための関数としてopen()関数があります。open()関数は指定されたファイル名にパイプライン記号「|」が含まれているとシェル機能(OSコマンドを呼び出すためのインターフェース)を呼び出すことができます。

OSコマンドやシェル機能を呼び出すことのできる関数には、以下のようなものがあります。

  • Perl:exec()関数、system()関数、open()関数
  • PHP:exec()関数、system()関数

OSコマンドインジェクションにより、Webサーバ内にある非公開の重要なファイルの閲覧や、不正なプログラムの実行、マルウェアへの感染などが起こる場合があります。

OSコマンドインジェクションの主な対策を表2に示します。

表2:OSコマンドインジェクションの主な対策

概要 詳細
OSコマンドを呼び出す機能を利用しない OSコマンドの呼び出しを利用しない実装を選択する
シェル機能を呼び出す関数を利用しない open()関数の代わりにsysopen()関数を利用することでシェルを呼び出さずにファイルを開くことができる

(ウ) クロスサイトリクエストフォージェリ

クロスサイトリクエストフォージェリCSRF:Cross-Site Request Forgeries)は、利用者の意図しないリクエストを勝手に実行させられる脆弱性です。ログイン機能があるWebサイトにログインした状態でリクエストを送った場合、そのリクエストが利用者の意図したリクエストかを識別する手段が組み込まれていないWebサイトでは、攻撃者による不正なリクエストを受け取ってしまう場合があります。

CSRF攻撃は、ログイン状態で攻撃者の用意した罠サイトなどを経由することで発生します(図1)。

図1:CSRF攻撃

CSRF攻撃により、パスワードの変更やアカウントの解約など、重要な処理を利用者の許可なく実行してしまう恐れがあります。

CSRFの対策を表3に示します。どちらも、正規の利用者のリクエストであるかを確認することが肝要です。

表3:CSRFの主な対策

概要 詳細
第三者が知り得ない秘密情報(トークン)の埋め込み 第三者が知り得ない秘密情報をトークンと呼び、重要な処理を行うページではトークンを要求し、正しいトークンを受け取った場合のみ処理することで不正なリクエストを判別できるようになる。
トークンは第三者に推測されにくくなるように暗号論的疑似乱数生成器を用いた乱数を用いる
処理を実行する直前で再度パスワードの入力を求める 本人にしか知り得ないパスワードによる認証を事前に行うことで、リクエストを正規の利用者が送信したことを確認できるようにする

(エ) セッションハイジャック

Webアプリケーションでは、ログイン状態を維持するなどクライアントとサーバ間の状態を維持するためにセッション管理機能が活用されています。セッション管理機能では、利用者を識別する仕組みとしてセッションIDを発行します。このセッションIDの管理に不備があるとセッションIDを不正に取得され、攻撃者により正規の利用者になりすまされる恐れがあります。このようなセッションIDを不正に取得する攻撃手法をセッションハイジャックといいます。

セッションハイジャックには、表4に示すような様々な手法があります。

表4:セッションハイジャックの手法

分類 手法
セッションIDの推測 セッションIDの生成規則をつきとめ、セッションIDを推測する
セッションIDの盗用 クロスサイトスクリプティングやネットワークの盗聴などでセッションIDを盗む
セッションIDの固定化 攻撃者が取得したセッションIDを利用者に強制的に使用させる。
このような手法をセッションフィクセーション(セッションIDの固定化攻撃)という

また、セッションハイジャックの主な対策を表5に示します。

表5:セッションハイジャックの主な対策

分類 対策
セッションIDの推測 セッションIDのアルゴリズムを予測困難なものにする
セッションIDの盗用
  • URLパラメータにセッションIDを格納するとRefererの機能により第三者にセッションIDが漏洩する場合があるため、セッションIDはCookieやPOSTメソッドのhiddenパラメータに保存して受け渡すようにする
  • HTTPによる平文の通信ではCookieが盗聴される恐れがあるため、HTTPSによる暗号化通信でCookieを送信する必要がある。Cookiesecure属性を設定することで、CookieをHTTPS通信のみで利用できるようになる
セッションIDの固定化 利用者がログインする前にセッションIDを発行するWebアプリケーションの場合、攻撃者が前もって取得したセッションIDを正規の利用者が強制的に使用させられる恐れがある。この時、攻撃者は利用者が利用するセッションIDを把握しているため、なりすましが成功してしまう。ログインが成功した時点で新しいセッションIDを発行し、既存のセッションIDを無効化することで攻撃者の把握していないセッションIDを利用できるようになる

午後Ⅰ問題を解いてみよう!

続いて、午後Ⅰ問題の過去問題を解いてみましょう。今回は平成29年度春期試験 午後Ⅰ問題 問2を解説します。必要に応じて、IPAが公開している本問題の解答採点講評も確認してください。

以下の解説では、問題文中のページ数を「Pxx」、図や表を「問題文中の図x、表x」と記します。

概要

  • E社はWebサイトαを利用して、飲食店情報提供サービスを行っている。
  • 利用者L氏が急にログアウトさせられ、その後ログインできなくなったという問い合わせがあった。
  • L氏がログインできなくなった日には不正ログインはされていないと結論づけた。
  • L氏はログインできなくなる前に、サイトα内の掲示板に投稿していた人のプロフィール画面を見て、そこに記載されていたリンクをクリックした。
  • サイトαの脆弱性検査を行い、脆弱性1、脆弱性2が検出された。
  • 対策をベンダに依頼し、対策後問題がないことを確認した。

設問1

不正ログインされたかは、本人の行動とシステムの記録が一致しているかを確認することでわかります。P10の下線部①より、「L氏のアカウントは少なくとも今日は不正ログインされていないとの結論に至った。」であることを確認するには、L氏がこの日にログインした時刻や回数を確認し、システムのログイン記録と一致するかを確認します。

従って、解答例は次のようになります。

L氏に確認した内容 L氏が今日ログインしたと言っている時刻や回数
ログイン記録 L氏の利用者IDを用いた今日のログイン時刻や回数

設問2(1)

P11の[脆弱性1について]より、問題文中の図2のようなHTMLで書かれたリンクを利用者がクリックしたことで、利用者の知らないうちに強制的な退会処理が行われています。このように利用者の意図しない不正な処理を正規の処理であると見せかけて強制的に実行させる攻撃が生じる脆弱性クロスサイトリクエストフォージェリCSRF:Cross-Site Request Forgeries)といいます。

設問2(2)

P12の問題文中の図2は、強制的に退会処理を行わせてしまうHTMLです。

P11の問題文中の表2では、画面遷移(え)(お)の手順が記述されています。これはP8の問題文中の図1から読み取れるように、「退会処理~退会完了」において脆弱性1を確認した手順です。P11の問題文中の表2において退会処理が成功するケースは項番1または項番3であるため、ここに着目してみます。

P10の問題文中の表1の画面遷移(え)(お)の行を確認してみましょう。

(え) 操作例:退会理由(例:特になし)を入力し, 退会確認ボタンを押す。
URL:https://www.e-sha.co.jp/member/taikai
POSTデータ:action_id=confirm&taikai_message=%E7%89%B9%E3%81%AB%E3%81%AA%E3%81%97
  • taikai_messageに入力された値がセッションオブジェクトに格納され, 次画面が表示される。
    taikai_token(例:B582DF03524FBB9DBCCE0BA0610F2EA1)が生成されてセッションオブジェクトに格納され, 退会確認画面のhiddenに格納される。
(お) 操作例:退会ボタンを押す。
URL:https://www.e-sha.co.jp/member/taikai
POSTデータ:action_id=submit&taikai_token=B582DF03524FBB9DBCCE0BA0610F2EA1
  • taikai_tokenの値がセッションオブジェクト内の値と同じ場合, 退会処理が行われ, 次画面が表示される。違う場合, 退会処理が行われず, エラー画面が表示される。
  • 退会処理時にセッションIDとセッションオブジェクトが無効にされ, ログアウトされる。

画面遷移(え)では、画面遷移時のパラメータに「action_id=confirm」と「taikai_message=ユーザが入力した値」を付与します。また、この時点で「taikai_token=乱数」という値のセッションオブジェクトが生成されます。

画面遷移(お)では、画面遷移時のパラメータに「action_id=submit」と「taikai_token=乱数」という値を付与します。この時、「taikai_token」の値は画面遷移(え)で生成された値を用います。

これらが成り立った時に退会処理が行われ、次画面が表示されます。

しかし、P11の問題文中の表2によると、項番1では上記の通りの手順を試みて退会処理を行っていますが、項番3では上記とは異なり、「taikai_tokenの値を指定していないにも関わらず退会が完了しています。これが本来有り得てはいけない、脆弱性による誤った処理過程と考えられます。

さらに、P12の問題文中の図2を確認してみます。

図2:問題文中の図2「退会処理が行われてしまうHTML」

このHTMLでは、17行目のスクリプトにより8~12行目の1つ目のフォーム(図中の赤で囲まれた部分)が呼び出されます。また、18行目のスクリプトにより13~16行目の2つ目のフォーム(図中の青で囲まれた部分)が1つ目のフォームの1秒(1000ミリ秒)後に呼び出されます。
setTimeout(関数, 時間指定) は、「時間指定(ミリ秒)」後に「関数」を実行します。

8~12行目の1つ目のフォームでは、画面遷移時にパラメータとして「action_id=【  e   】」と「taikai_message=”OK”」を付与しています。これはP9の問題文中の表1から画面遷移(え)に相当する処理と考えられます。

また、13~16行目の2つ目のフォームでは、画面遷移時にパラメータとして「action_id=【  f  】」のみ付与しています。これはP8の問題文中の図1の画面遷移(え)の後に実行されていることと、P10の問題文中の表1から画面遷移(お)に相当する処理と考えられます。ただし、この処理では「taikai_tokenの指定がないため、問題文中の表2の項番3に相当する手順になります。

これらより、本文中の【 b 】に入れる項番は「3」です。

設問2(3)

パスワード変更画面に関する仕様のため、P9の問題文中の表1の画面遷移(い)を確認します。

画面遷移(い)では、「現在のパスワードと新しいパスワードを入力し, 変更ボタンを押す。」とあります。脆弱性1はCSRFであり、不正ログインとは異なり、攻撃者が知りえない現在のパスワードを入力することはできません

従って、本文中の【  c  】は「現在のパスワード」、【  d  】は「知り得ない」です。

本文中では語られていませんが、盗聴などによりパスワードが盗まれた場合は攻撃が成功してしまうため、本来であればパスワード管理を別途適切に行う必要があります。

設問2(4)

(2)で確認した通り、P12の問題文中の図2の8~12行目の1つ目のフォームは、画面遷移(え)に相当する処理です。従って、action_idに入る値は「confirm」です。

また、13~16行目の2つ目のフォームは画面遷移(お)に相当し、P11の問題文中の表2の項番3に相当するため、action_idに入る値は「submit」です。

従って、本文中の【  e  】は「confirm」、【  f  】は「submit」です。

設問3(1)

P12の[脆弱性2について]より、脆弱性2はクロスサイトスクリプティング(XSS:Cross-Site Scripting)です。XSSの一般的な対策として、ユーザの入出力にエスケープ処理を行いHTMLタグの利用を制限しますが、サイトαでは<b>タグなどの中に特定の属性を指定することでスクリプトの実行が可能です。

スクリプトが実行可能になる特定の属性にイベントハンドラがあります。イベントハンドラではonClick(マウスがクリックされた時)やonMouseOver(マウスカーソルがオブジェクトに重なった時)など、画面上で何かをした(起きた)時に行う処理を指定します。

選択肢でイベントハンドラに属するものは「(オ)onclick」と「(キ)onmouseover」です。選択肢においてこれら以外の属性にスクリプトを定義することはできません。

設問3(2)

ログイン状態を維持するためには、セッションIDなどの情報を保持する必要があり、多くの場合CookieにセッションIDを保存します。セッションIDが盗まれると利用者になりすまされてしまいます。セッションIDの情報が盗まれる(Cookieが盗まれる)ような攻撃のことをセッションハイジャックといいます。

従って、本文中の【  g  】は「セッションハイジャック」です。

設問3(3)

P12~13のK氏とXさんの会話から、HTMLの要素の制限を変えずに仕様変更でXSSの脆弱性対策を行う必要があります。

HTMLの要素は制限できないため、属性を制限することで不用意にスクリプトを実行させないような対策が必要です。

従って、解答例は「タグの中で利用できる属性を制限する」です。

おわりに

午後Ⅰ試験ではプログラミングに関する問題がほぼ毎回出題されていますが、選択問題のため敬遠される方も多いテーマです。ただし、午前問題、午後Ⅱ問題でもWebアプリケーションの脆弱性に関して出題されています。出題されるキーワードはそれほど多くないため、苦手意識をもたずに代表的な攻撃手法とその対策は確実に押さえておくことをお勧めします。

また、Webアプリケーションのセキュリティ対策として、「安全なウェブサイトの作り方」や「OWASP TOP10」は非常に参考になります。ぜひ目を通しておきましょう。

次回はいよいよ最終回です。試験直前対策について解説します。

NECマネジメントパートナー株式会社 人材開発サービス事業部
2009年日本電気株式会社入社。人材開発事業部門に所属し、Linuxシステム、Webプログラミング、セキュリティの教育を担当。近年では、官公庁や重要インフラ事業者へのCSIRT要員に対して、インシデント対応の演習を展開している。

連載バックナンバー

Think IT会員サービス無料登録受付中

Think ITでは、より付加価値の高いコンテンツを会員サービスとして提供しています。会員登録を済ませてThink ITのWebサイトにログインすることでさまざまな限定特典を入手できるようになります。

Think IT会員サービスの概要とメリットをチェック

他にもこの記事が読まれています