コンテンツにスキップ

Cross-Site Scripting (XSS)

クロスサイトスクリプティング (XSS)

説明

Cross-Site Scripting(XSS)の脆弱性は、サニタイズされていないユーザー制御の入力がユーザーに提供される場合に発生します。

XSSの脆弱性は、Webセキュリティの基本原則であるSame-Origin Policy(SOP)をバイパスします。SOPは、http://evil.comからのページがhttp://bank.comからのページのコンテンツにアクセスできないように保証するものです。

XSSは一般的に3つのファミリーに分類されます。

  • Reflected: ユーザー制御の入力がページレスポンスに直接反映されます。
  • Stored: ユーザー制御の入力がサーバー側(データベースなど)に保存され、後でユーザーに返されます。
  • DOM-based: ユーザー制御の入力がクライアント側のDOMに挿入され、悪意のあるJavaScriptの実行を引き起こします。

XSSの脆弱性により、攻撃者はユーザーセッションやアカウント情報などの個人データの流出、ユーザーになりすましたアクションの実行など、さまざまな悪意のあるアクションを実行できます。

import javax.servlet.http.*;
import java.io.*;

public class VulnerableXSS extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String userInput = request.getParameter("input");
        String page = "<html><body><h2>User Input: " + userInput + "</h2></body></html>";

        PrintWriter out = response.getWriter();
        out.println(page);
    }
}
const express = require('express');
const app = express();

app.get('/vulnerable', (req, res) => {
  const userInput = req.query.input;
  res.send(`<html><body><h2>User Input: ${userInput}</h2></body></html>`);
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});
  <!DOCTYPE html>
  <html>
  <head>
      <title>XSS Vulnerability</title>
  </head>
  <body>
      <h1>Welcome to the Vulnerable Page</h1>
      <p>Search for a product:</p>
      <form action="/search">
          <input type="text" name="query" placeholder="Enter product name">
          <input type="submit" value="Search">
      </form>
      <p>Search results:</p>
      <div id="results">
          <!-- Display search results here -->
          <?php
              // Vulnerable code - directly echoing user input without sanitization
              $query = $_GET['query'];
              echo "<p>You searched for: " . $query . "</p>";
          ?>
      </div>
  </body>
  </html>

推奨事項

通常、XSSの脆弱性を防ぐには、2段階の保護が必要です。

  • 入力検証: ユーザー制御の入力は、許可されていないすべての文字を拒否するように検証する必要があります。たとえば、電話番号には数字のみを含めるようにし、名前にはアルファベット文字のみを含めるようにするなどです。
  • 出力エンコーディング: ユーザーに表示されるすべての入力は、実績のある標準APIを使用して正しくエンコードされます。出力エンコーディングをネイティブにサポートし、安全なデフォルト設定を備えた安全なテンプレートエンジンの使用を強くお勧めします。

import org.apache.commons.text.StringEscapeUtils;
import javax.servlet.http.*;
import java.io.*;

public class SecureXSSWithLibrary extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String userInput = request.getParameter("input");
        String sanitizedInput = StringEscapeUtils.escapeHtml4(userInput);
        String page = "<html><body><h2>User Input: " + sanitizedInput + "</h2></body></html>";

        PrintWriter out = response.getWriter();
        out.println(page);
    }
}
const express = require('express');
const app = express();
const { escape } = require('html-escaper'); // Using 'html-escaper' library

app.get('/secure', (req, res) => {
  const userInput = req.query.input;
  const sanitizedInput = escape(userInput);
  res.send(`<html><body><h2>User Input: ${sanitizedInput}</h2></body></html>`);
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});
  <!DOCTYPE html>
  <html>
  <head>
      <title>Secure Page</title>
  </head>
  <body>
      <h1>Welcome to the Secure Page</h1>
      <p>Search for a product:</p>
      <form action="/search">
          <input type="text" name="query" placeholder="Enter product name">
          <input type="submit" value="Search">
      </form>
      <p>Search results:</p>
      <div id="results">
          <!-- Display sanitized search results here -->
          <?php
              // Sanitizing user input before displaying
              $query = $_GET['query'];
              echo "<p>You searched for: " . htmlspecialchars($query, ENT_QUOTES, 'UTF-8') . "</p>";
          ?>
      </div>
  </body>
  </html>

リンク

標準

  • OWASP_ASVS_L1:
    • V5_2_1
    • V5_3_1
    • V13_1_1
  • OWASP_ASVS_L2:
    • V5_2_1
    • V1_5_4
    • V5_3_1
    • V13_1_1
  • OWASP_ASVS_L3:
    • V5_2_1
    • V1_5_4
    • V5_3_1
    • V13_1_1
  • PCI_STANDARDS:
    • REQ_2_2
    • REQ_6_2
    • REQ_6_3
    • REQ_6_4
    • REQ_11_3
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_4_1
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5
  • HIPAA_CONTROLS:
    • SECURITY212
    • SECURITY213
    • SECURITY255