12件の指摘と、6つの型
セキュリティ診断の会社が、取引先のサイトを調べ、12件の指摘をまとめました。エラーページ、おかしなリンク、アドレスの中のファイル名。ばらばらに見えます。
経験のある診断者は、その一覧を6つの型に分けて読みます。型ごとに、原因が1つ、直し方が1つあります。このレッスンでは、指摘を型に分ける練習をします。
たった1つのルール
注意
攻撃してよいのは、自分専用のラボのコピーだけです。このラボは、わざと弱く作ったサイトで、インターネットにはつながっていません。許可のない他人のシステムを攻撃すると、不正アクセス禁止法に触れる犯罪になります。
このレッスンのゴール
メモ
弱いページを見て、どの型の弱点かを答えられる。
今日のキーワード
| ことば | いみ | れい |
|---|---|---|
| 弱点の型 | 同じ原因を持つ弱点の、ひとまとまりです。 | |
| インジェクション | 打ち込んだ文字が、命令やクエリの一部として読まれることです。 | |
| パストラバーサル | ファイル名で、決められたフォルダの外へ出ることです。 | ../ |
| オープンリダイレクト | 渡されたどんなアドレスへも、利用者を移すリンクです。 | |
| 入力 | 利用者が画面に打ち込む、または送る内容です。 | |
| 出口 | 値が、プログラムの中で最後に使われる場所です。 |
学生が入力するセルは、このプレビューでは空白です。
入力を出口まで追う
弱点の多くは、同じ流れでできています。値が、利用者から入ります。プログラムの中を通ります。そして 出口 で使われます。
弱点の型は、その出口で決まります。どのページにも、1つの問いが使えます。打った文字は、最後にどこへ行くのか。
例: 出口と型
| 値が行き着く場所 | 弱点の型 | 直し方を一言で |
|---|---|---|
| データベースのクエリの中 | SQLインジェクション | パラメータで渡す |
| ブラウザが描くページの中 | XSS | 出力でエスケープする |
| サーバーが開くファイル名の中 | パストラバーサル | 一覧にある名前だけ許す |
| サーバーが動かすコマンドの中 | コマンドインジェクション | 文字からコマンドを作らない |
| 利用者の移動先のアドレス | オープンリダイレクト | 自分のアドレスだけ許す |
| 持ち主の確認がないID | アクセス制御の不備 | 毎回、持ち主を確かめる |
学生が入力するセルは、このプレビューでは空白です。
リクエストに型の印が出る
リクエスト1件から、型が分かることがよくあります。ファイル名に ../ があれば、パストラバーサルを疑います。値にタグがあれば、XSS を疑います。redirect= に完全なアドレスが入っていれば、オープンリダイレクトです。
分けるのに、何かを実行する必要はありません。リクエストを読んで、その値が何に使われるかを考えます。
例: 作り話のリクエスト5件
| リクエスト | 型 |
|---|---|
| /view?file=../../etc/hosts | パストラバーサル |
| /greet?name=<i>Bo</i> | XSS |
| /go?redirect=http://other.example | オープンリダイレクト |
| /lookup?id=5 UNION SELECT 1 | SQLインジェクション |
| /tools?host=a.example; cat notes | コマンドインジェクション |
学生が入力するセルは、このプレビューでは空白です。
ラボのサイトを見る
ラボでは、わざと多くの弱点を持たせた Mutillidae が動いています。起動して、次の3つを順に実行しましょう。
1つ目は、ラボ用のアカウントでサインインし、その印をファイルに残します。2つ目は、そのアカウントを名前とパスワードで照会します。3つ目は、サイトにない名前を照会します。どれも、ふつうの使い方です。
ラボ用のアカウントでサインイン
curl -s -c jar -d "username=admin&password=adminpass&login-php-submit-button=Login" -o /dev/null -w "%{http_code} %{redirect_url}\n" "http://www/index.php?page=login.php"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
アカウントを1件照会
curl -s -b jar -c jar -G "http://www/index.php" --data-urlencode "page=user-info.php" --data-urlencode "username=admin" --data-urlencode "password=adminpass" --data-urlencode "user-info-php-submit-button=View Account Details" | grep -o "[0-9]* records found"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
サイトにない名前を照会
curl -s -b jar -c jar -G "http://www/index.php" --data-urlencode "page=user-info.php" --data-urlencode "username=nobody" --data-urlencode "password=nothing" --data-urlencode "user-info-php-submit-button=View Account Details" | grep -o "[0-9]* records found"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
3つの答えを読む
1つ目は 302 と、末尾が AU1 のアドレスを表示します。サイトがサインインを受け入れたのです。2つ目は 1 records found、3つ目は 0 records found を表示します。
このページは、クエリが返した行の数を数えています。つまり照会ページは1つの出口で、打った名前がデータベースのクエリに入ります。どの型を調べるべきでしょうか。上の表と照らして、答えを確かめましょう。
よくある間違い
注意
「禁止する語の一覧が1つあれば、すべての型を止められる」と考える人がいます。それは違います。型ごとに出口が違うので、直し方も、その出口に合うものが要ります。script を止める仕組みは、ファイル名には何もしません。出口ごとに直しましょう。
ほとんどの型は原因が1つ
インジェクション、XSS、パストラバーサルなどは、原因が同じです。プログラムが、データと命令を混ぜてしまい、次の層が見分けられないのです。
直し方の考え方も同じです。データを、別の道に分けます。パラメータ、エスケープ、許す語の一覧です。Mutillidae にはセキュリティレベル 0、1、5 があり、同じページを直す前と後で見比べられます。
さらに挑戦: 隠れたパストラバーサル
攻撃する人は、点を %2e と書くことがあります。すると ../ は %2e%2e/ になります。課題の決まりでは、/view?file=%2e%2e/secret は見逃され、"通常" と判定されます。
課題が通ったら、classify を自分のコードのブロックに写します。これを捕まえる置き換えを1つ足しましょう。そして、本物のサーバーが調べる前にアドレス全体を1回デコードするのはなぜかを、説明しましょう。