Webアプリケーションの脆弱性の解説&体験ページ

マスタリングTCP/IP 情報セキュリティ編 8章で取り扱う攻撃を体験できる脆弱サイトの解説ページです。

脆弱サイト

はじめに、脆弱サイトの概要を説明します。このサイトは、データベースに登録された会員情報を検索するサービスを提供しています。

参考書マスタリングTCP/IP 情報セキュリティ編 8章 Webセキュリティ pp.205〜

脆弱サイトの機能と仕組み

1.
ユーザはログイン後、登録された検索したい会員名を、Webアプリケーションサーバーで検索します。会員名は、以下に示すHTMLファイルのFormにある変数unameに格納して送信されます。
<form action="NotSecureSearchServlet" method="post">
  検索したい会員の名前を入れて下さい(脆弱):<input type="text" name="uname" />
  <input type="submit" value="検索" />
</form>
例えば、AIUEOという会員名で検索する場合に、Webブラウザから送信される値の一部を以下に示します。
uname=AIUEO
2.
Webアプリケーションサーバーは、Webブラウザから受け取った変数unameの値を用いてSQL文を構成します。構成されるSQL文を以下に示します。また、Webアプリケーションサーバーは、構成したSQL文をDBMSに送信します。
SELECT * FROM user WHERE id='AIUEO'

このSQL文は、氏名(id)がAIUEOである会員の、すべての属性を射影します。

3.
DBMSは、Webアプリケーションサーバーから受け取ったSQL文を実行し、検索結果をWebアプリケーションサーバーに送信します。
4.
Webアプリケーションサーバーは、DBMSから受け取った検索結果を表示するためのページを作成し、Webブラウザに送信します。Webブラウザは、受け取ったページを表示します。

データベースの内容

データベースには、右の表のように会員情報が登録されています。テーブル名は「user」です。

テーブル名:user

会員番号氏名(id)電話番号
1ueto1001
2saito1002
3goriki1003
4shina1004
5hamasaki9999

脆弱サイトの利用法

1.
脆弱サイトには、次のユーザ名とパスワードを使ってログインします。

ユーザ名:ueto

パスワード:aya

2.
ログインが成功すると、会員検索のためのテキストボックスが2つ表示されます。いずれかのテキストボックスに検索したい会員名を入力して、検索ボタンを押します(検索するテキストボックスは2つありますが、どちらでも構いません)。例えば、uetoで検索すると、右の図のように表示されます。
3.
データベースに登録されていない会員名で検索した場合、データベースに登録されていない旨を伝えるページが表示されます。 例えば、miuraで検索すると右の図のように表示されます。

フォーム(preparedstatementの利用)を利用した場合はユーザが入力した会員名が表示されませんが、フォーム(脆弱)を利用した場合はユーザが入力した会員名が表示されるようになっています。

フォーム(preparedstatementの利用)を利用した場合

フォーム(脆弱)を利用した場合

4.
ログアウトボタンを押して、会員サイトのページからログアウトします。

参考8.3 XSS攻撃とその対策 pp.220〜

XSS攻撃の例

注意

XSS攻撃の確認は Firefox でお試し下さい。

ChromeやSafariにはXSS Auditor、IE 8以上にはXSSフィルターという、XSS攻撃を検知してブロックする機能があり、ここでの実験ができません。

攻撃例

フォーム(脆弱)のテキストボックスに、下に示すXSS攻撃用のJavaScriptコードを会員名として入力し、検索を押して下さい。すると、右の図のようなダイアログが表示され、JavaScriptコードが実行されていることが確認できます。

ueto<script>alert(document.cookie);</script>

XSS攻撃用のJavaScriptコード

解説

上に示した、検索したい会員名としてのJavaScriptコードはデータベースに登録されていないので、Webアプリケーションサーバーは登録されていない旨を伝えるページを作成しようとします。今回の例では、下に示すページが作成されます。Webブラウザは、ueto以降のscriptタグ内(赤色の部分)をJavaScriptコードとして解釈し、alert(document.cookie);を実行します。

<html>
  <body>
    検索結果:ueto<script>alert(document.cookie);</script> について該当するデータがございません。
  </body>
</html>

フォーム(脆弱)を利用した場合の結果ページ

一方、フォーム(preparedstatementの利用)、正確には、Servlet(preparedstatementの利用)を利用する場合は、Webアプリケーションサーバーは会員名をページに出力しないように設計されているので、XSS攻撃は成功しません。preparedstatementについては、SQLインジェクションの章で説明します。

<html>
  <body>
    検索結果:該当するデータがございません。
  </body>
</html>

フォーム(preparedstatementの利用)を利用した場合の結果ページ

結果

参考8.4 SQLインジェクションとその対策 pp.226〜

SQLインジェクションの仕組み

攻撃例

フォーム(脆弱)のテキストボックスに、下に示す攻撃のための文字列を会員名として入力し、検索を押して下さい。

aiueo' or 'A'='A

攻撃のための文字列

すると、右の図のような表が表示されます。これは、データベースからすべての会員情報を不正に取得できてしまうことを示しています。

一方、フォーム(preparedstatementの利用)を利用する場合はプリペアドステートメントを利用しているので攻撃は成功せず、「該当するデータがございません。」となります。

解説

フォーム(脆弱)を利用した場合

Webアプリケーションサーバー(Servlet)は、(ユーザが会員名として入力した)攻撃のための文字列をWebブラウザから受け取ると、下の(Javaの)文を実行します。

String sql = "SELECT * FROM user WHERE id = '" + id + "'";

" + id + "に攻撃のための文字列が代入された場合、変数sqlの値として、下のSQL文が構成されます。

SELECT * FROM user WHERE id='aiueo' or 'A'='A'

このSQL文の、WHERE句に注目すると、検索条件は「id(データベース中の氏名)が'aiueo'と同値、もしくは、'A'が'A'と同値かどうか」です。idがどんな値でも、'A'と'A'は常に同値なので、検索条件は常に真となります。そのため、データベース内の全ての行で検索条件が真となり、全ての行が選択されてしまいます。

フォーム(preparedstatementの利用)を利用した場合

Webアプリケーションサーバーは、ユーザが会員名として入力した攻撃のための文字列をWebブラウザから受け取ると、下の文を実行します。

// SQL文の用意. ?がプレースホルダです
String sql = "SELECT * FROM user WHERE id = ?";

// プリペアドステートメントオブジェクトの用意
PreparedStatement ps = conn.prepareStatement(sql);

// SQL文の1番目の?を、id(ユーザから受け取った攻撃のための文字列)に置き換え
ps.setString(1, id);

この結果、データベースの氏名(id)が「攻撃のための文字列」である会員が存在しないので、攻撃が成立せず、単に、「該当するデータがございません。」と出ます。

参考8.5 CSRFの攻撃とその対策 pp.230〜

CSRF攻撃の仕組み

前提

脆弱サイトは、cookieを利用してセッション管理をしています。そのため、ログアウトボタンを押してログアウトをしなければ、Webブラウザを閉じた後に、もう一度アクセスした場合でも、ログイン状態になるように設計されています。確認してみて下さい。

次に、ユーザがログアウトボタンを押した時の動作を説明します。ユーザがログアウトボタンを押すと、WebブラウザがWebアプリケーションサーバーに対して下に示すリクエストを送信します。

http://www.saitolab.org/samples/LoginServlet?logout=true

このリクエストには、logout=trueというパラメータが記述されています。Webアプリケーションサーバーは、このパラメータを受け取るとログアウト処理を行う設計になっています。

攻撃例

まず、脆弱サイトにログインして下さい。その状態で、悪友のmiuraちゃんから右に示すメールが届いたとします。あなたがメールに記載されているリンクをクリックすると、ログアウトしていないにもかかわらず、脆弱サイトから強制的にログアウトさせられてしまいます。確認してみて下さい。

解説

メールに記載されているリンク(幸せのページ)のコードを抜粋し、下に示します。このリンクをクリックすると、前提で示したリクエストと同じリクエスト(赤色の部分)が、Webアプリケーションサーバーに送信されます。送信するのは脆弱サイトにログインしているユーザ(あなた)なので、あなたのログアウト処理が行われてしまいます。より正確には、あなたがログインした状態の情報を持つcookieを、そのリクエスト時に送信することにより、logout=trueというパラメータが、Webアプリケーションサーバーで解釈されます。

<a href="http://www.saitolab.org/samples/LoginServlet?logout=true">幸せのページ</a>

一緒に幸せになりましょう。下のリンクをクリックして下さい。(はーと

幸せのページ

メール内容