ハッキングというと・・・
- 黒い画面に白文字が流れる
- 高度なプログラミング知識が必要
- なんかスゴイことをしている
こういうイメージがあります。
一部のハッカーはそうかもですが、身近なハッキングだとJavaScript初心者でもできることがあります。(サーバー側で対策が取られていない場合)
そこでウェブサービスを開発する人やハッキングを学びたい人に向け、【XSS攻撃】の初歩的な手法&対策について紹介したいと思います。
このページの目次
まずはXSS攻撃の概要について
XSS攻撃とは何なのか・・・
その説明だけすると次の通りです。
▼ とりあえずWikipediaから引用
クロスサイトスクリプティング(英: cross site scripting)とは、Webアプリケーションの脆弱性[1]もしくはそれを利用した攻撃。脆弱性をツリー型に分類するCWEではこの攻撃を不適切な入力確認(CWE-20)によるインジェクション(CWE-74)のひとつとして分類している(CWE-79)[2]。略称はXSS。かつてはCSSという略称も使われていたが、Cascading Style Sheetsと紛らわしいのでこの略称はあまり使われなくなった[1]。
引用元 : クロスサイトスクリプティング
XSS = cross site scripting
Webアプリケーションだと入力フォームとか投稿フォームがあります。そこで悪意のあるコードが埋め込まれることによって、個人情報を引き抜いたり、悪意のあるサイトに飛ばすことが可能です。
とはいえ、これだけだと具体的なイメージが湧きにくいはず。そこで攻撃者側にとってどういうサーバーが好都合なのか、そして具体的なハッキング手法を次で紹介します。
XSS攻撃による具体的ハッキング手順
1.ハッキング対象のサーバーの脆弱性
例えば「6ch」という掲示板サイトがあるとします。
※ 実在のサイト・団体とは無関係
この 6ch には次の脆弱性が存在していました。
まずはデータべ―ス構成から
▼ 投稿を保存するテーブル構成
カラム名 | ID | nickname | content |
---|---|---|---|
説明 | 一意なID | 投稿者名 | 投稿本文 |
ものすごく簡易的な掲示板です。
スレッドとかも建てれません。
ただデータべ―スには問題なしです。
そして投稿は次の保存処理で実行しています。
▼ このようなPHPコードで投稿していた
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?php $nickname = $_POST['nickname']; $content = $_POST['content']; if (isset($nickname) && isset($content)) { $sql = " INSERT INTO posts ( nickname, content ) VALUES (?, ?); "; $stmt = $mysqli->prepare($sql); $stmt->bind_param( 'ss', $nickname, $content); $stmt->execute(); $stmt->close(); } ?> <html> <head> <title>6chへようこそ</title> </head> <body> <form action="" method="POST"> <div> <label>お名前 : </label> <input type="text" id="nickname" name="nickname"> </div> <textarea id="content" name="content"></textarea> <button type="submit">送信</button> </form> </body> </html> |
ここも問題ないですね。
データべ―スに投稿データを保存してるだけです。
問題があったのが 投稿の出力処理 でした・・・
▼ このように投稿一覧を表示してしまっていた
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?php $posts = []; $sql = " SELECT ( nickname, content ) FROM posts "; $stmt = $mysqli->prepare($sql); $stmt->execute(); $stmt->bind_result('ss', $nickname, $content); while($stmt->fetch()){ array_unshift($posts, [ 'nickname' => $nickname, 'content' => $content ]); } $stmt->close(); ?> <html> <head> <title>掲示板</title> </head> <body> <div class="container"> <?php foreach($posts as $post): ?> <div class="post"> <div class="nickname"> <?php echo $post->nickname; ?> </div> <div class="content"> <?php echo $post->content; ?> </div> </div> <?php endforeach; ?> </div> </body> </html> |
これはかなりヤバいコードです。
何がマズいかというと、 echo $post->nickname; みたいに直出力してることですね。もし投稿画面から悪意のあるデータを送れば、次のイタズラ・犯罪ができるって訳です。
- 悪意あるサイトに閲覧者を飛ばす
- 閲覧者の個人情報を抜き取る
- 不正ソフトをダウンロードさせる
ではこの架空の6chをハッキングしてみます。
2.XSS攻撃はJavaScript1行だけでもできる
その方法は驚くほど簡単です。
例えばウィルスサイトに閲覧者を飛ばすとします。
その場合、掲示板に次の内容を書き込むだけ
▼ 投稿本文に次を書いて送信
1 2 3 |
<script> location.href = "http://googkle.com/"; </script> |
▼ 実際はこういうイメージ
はい、たったこれだけです。
正直言ってJavaScript初心者でもできます。
普通、こんな初歩的なハッキング(XSS攻撃)は通用しないです。でも世の中探せば、こんな脆弱性たっぷりのサービスも案外あるかもしれませんね・・・(-_-;)
攻撃者側はセキュリティの強いサイト・サービスは狙わないらしいです。むしろ容易に突破できる安全意識の低い場所を狙うと思います。(自分がクラッカーだった場合)
XSS攻撃の基本対策は特殊文字エスケープ!
XSS攻撃の対策は難しくありません。
出力時にHTML特殊文字をエスケープするだけです。
PHPだとhtmlspecialchars関数が使えます。
▼ 公式リファレンスでの解説
htmlspecialchars ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get("default_charset") [, bool $double_encode = TRUE ]]] ) : string
文字の中には HTML において特殊な意味を持つものがあり、 それらの本来の値を表示したければ HTML の表現形式に変換してやらなければなりません。 この関数は、これらの変換を行った結果の文字列を返します。
引用元 : https://www.php.net/manual/ja/function.htmlspecialchars.php
▼ この関数の実用的な使い方
詳しくは上記事などをご覧ください。
XSS攻撃は出力時さえ気を付ければ大丈夫ですね。
以上、JS1行でできるハッキング手順&対策でした。