セキュリティ

【XSS】クロスサイトスクリプティング脆弱性のテスト方法を紹介

お久しぶりです。サイバーセキュリティに関する記事を書こうと思っていたのですが、仕事が忙しく間が空いてしまいました。今回はタイトルの通りシステムにクロスサイトスクリプティングの脆弱性があるかどうかテストする方法について、実際に検証しながら解説していきたいと思います。途中分からないことが出てきた李前提知識に不安がある方は適宜他のWebサイトやオンライン講座でキャッチアップいただくか、本格的にホワイトハッカーや脆弱性診断士を目指したいのであれば以下の書籍を読むことをオススメします。

※本記事は開発者や脆弱性診断士、ペネトレーションテスターなどセキュリティの技術者に向けた記事です。悪用すると法律に問われる可能性があるため注意ください。

クロスサイトスクリプティングのテスト方法

クロスサイトスクリプティングの脆弱性があるかどうかを実験・検証する方法は掘り下げれば複雑になるため、ここでは最もベーシックな例に絞って解説していきます。

今回以下のようなクロスサイトスクリプティングの脆弱性がある問合せフォームを用意しました。各項目に内容を入力して「Submit」を押下すると確認画面に遷移するようになっています。この後のステップでは「問い合わせ内容:」の項目に検査用JavaScriptを埋め込んでいきますが、わかりやすいように関係のあるソースコードの箇所は赤の太字にしておきました。

※cssファイルを載せるとソースコードの量が多くなってしまうので載せていません。htmlだけをコピペして手元で検証することはできますが、デザインなどもある程度ちゃんとした方がテンションが上がるという方はChatGPTなどにコードを張り付けておしゃれなcssを書いてもらったり自分で書くなど、必要に応じて自分で対応してください。

今回検証する問合せフォーム(Submitを押下すると確認画面に遷移)

//問合せフォーム(inquiry_form.html)
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Inquiry Form</title>
  <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
  <div class="container">
    <h2>問合せフォーム</h2>
    <form action="confirmation.php" method="POST">
      <label for="name">お名前:</label>
      <input type="text" id="name" name="name" required>
      
      <label for="email">メールアドレス:</label>
      <input type="text" id="email" name="email" required>
      
      <label for="message">問い合わせ内容:</label>
      <textarea id="message" name="message" rows="5" required></textarea>
      
      <input type="submit" value="Submit">
    </form>
  </div>
  </body>
</body>
</html>
//確認画面(confirmation.php)
<?php
	if ($_SERVER["REQUEST_METHOD"] == "POST") {
        $name = $_POST["name"];
        $email = $_POST["email"];
        $message = $_POST["message"];
  }
?>
<!DOCTYPE html>
<html>
<head>
  <title>Confirmation Screen</title>
  <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
  <div class="container">
    <h2>確認画面</h2>
    <p><strong>Here is the information you provided:</strong></p>
    <ul>
      <li><strong>Name:</strong><?php echo $name; ?></li>
      <li><strong>Email:</strong><?php echo $email; ?></li>
      <li><strong>Message:</strong><?php echo $message; ?></li>
    </ul>
    <form action="submission_completed.html">
      <input type="button" value="Back" onclick="history.back();">
      <input type="submit" value="Confirm">
    </form>
  </div>
</body>
</html>

実際にテストしてみよう

検査する方法は簡単で問合せフォーム等の入力欄やパラメータに「<script>alert(0);</script>」という文字列を入れて処理を行うだけです。この文字列はクロスサイトスクリプティングの検査を行う際に使われる有名な文字列で、JavaScriptのalert(0);という構文が実行されダイアログが表示されると脆弱性が存在するということになります。

クロスサイトスクリプティングのテスト方法

「<script>alert(0);</script>」を入力欄に入れ処理を行う。

※これは基本を理解するための一例です。専門機関が提供しているような有料の脆弱性の有無を検査するサービスを脆弱性診断と言いますが、実際の脆弱性診断ではこの例に限らず様々な検査用スクリプトをあらゆるパラメータやURLパスに対して網羅的に入力し、脆弱性の有無を徹底的に検査します。

では確認してみましょう。
問い合わせフォームの「問い合わせ内容:」欄に「<script>alert(0);</script>」の文字列を入れました。

この状態で「Submit」を押下してみます。

「0」という値が記載されたダイアログが表示され、クロスサイトスクリプティングの脆弱性があることが確認できました。こんな感じで入力フォームやパラメータに順次検査用JavaScriptを入力していくことで脆弱性の有無を判定することが可能です。

なぜJavaScriptが実行されたのか?

これで脆弱性の存在は確認できたわけですが、JavaScriptが実行された理由を確認するためダイアログが表示された時のソースコードがどうなっているのか少しみてみましょう。確認画面の「confirmation.php」のソースコードをブラウザの開発者ツールから確認すると、ソースコード中に「<script>alert(0);</script>」という文字列が確認できます。一番下の例の「<?php echo $message; ?>」の$message変数には前の問合せフォームで入力した「<script>alert(0);</script>」が代入されるので、これがJavaScriptとして認識された結果、このようなダイアログが表示されたというわけですね。

//確認画面(confirmation.php)
~(略)~
<h2>確認画面</h2>
<p><strong>Here is the information you provided:</strong></p>
<ul>
  <li><strong>Name:</strong>test</li>
  <li><strong>Email:</strong>test</li>
  <li><strong>Message:</strong><script>alert(0);</script></li>
</ul>
~(略)~
//確認画面(confirmation.php)
//$messageには前の問合せ画面で入力された「<script>alert(0);</script>」の値が代入される。

<h2>確認画面</h2>
<p><strong>Here is the information you provided:</strong></p>
<ul>
  <li><strong>Name:</strong><?php echo $name; ?></li>
  <li><strong>Email:</strong><?php echo $email; ?></li>
  <li><strong>Message:</strong><?php echo $message; ?></li> 
</ul>

-セキュリティ