Charset Mismatch

概要

  • 脆弱性の名前: Charset Mismatch (文字セットの不一致)
  • 問題の要点: HTTPレスポンスヘッダーとHTMLメタタグで指定された文字エンコーディングが一致しないため、ブラウザが文字を正しく解釈できず、セキュリティリスクや表示の不具合が発生する状態。
  • よくある発生シーン: 異なる設定ファイル間での文字エンコーディング設定の不整合、開発者がHTTPヘッダーとHTMLメタタグの両方を設定する際に誤りが発生しやすい。クラウド環境では、複数のサーバーやサービスが連携する際に、各設定の統一が不十分な場合に発生することがあります。

背景

文字エンコーディングは、テキストデータをコンピュータが理解できる形式に変換するための規則です。Webページでは、HTTPレスポンスヘッダーのContent-TypeとHTMLの<meta>タグで文字エンコーディングを指定します。
これらの設定が一致しない場合、ブラウザはどちらの設定を優先するかを判断する必要があります。この際、ブラウザが誤ったエンコーディングを選択すると、文字化けやセキュリティ上の問題が発生する可能性があります。
文字エンコーディングの不一致は、特に多言語対応のWebサイトや、異なるシステム間でデータをやり取りするWebアプリケーションで問題となりやすいです。

セキュリティ上のリスク

  • クロスサイトスクリプティング(XSS)攻撃の可能性増加: 文字エンコーディングの不一致により、XSSフィルターが回避される可能性があります。
  • 文字化けによる情報の誤表示: ユーザーがWebページの内容を正しく理解できなくなる可能性があります。
  • ブラウザの文字エンコード解釈の不一致: 異なるブラウザで表示が異なる場合があります。
  • 国際化対応の問題: 多言語Webサイトで文字が正しく表示されない場合があります。
  • クロスサイトスクリプティングフィルターの回避: 文字エンコーディングの不一致を利用して、XSSフィルターを回避する攻撃が可能です。

対処方法の具体例

Apache2

.htaccessファイルでの設定

# .htaccessファイル
AddDefaultCharset UTF-8
AddCharset UTF-8 .html .php

# または
<FilesMatch "\.(html|php)$">
    AddDefaultCharset UTF-8
    DefaultLanguage en-US
</FilesMatch>
  • AddDefaultCharset: サーバー全体のデフォルト文字セットを設定します。
  • AddCharset: 特定の拡張子を持つファイルに対して文字セットを設定します。
  • &lt;FilesMatch&gt;: 特定のファイルに対して設定を適用します。

Nginx

nginx.confでの設定

# nginx.conf
http {
    charset utf-8;
    charset_types text/html text/xml text/plain text/css application/javascript;
}
  • charset: サーバー全体の文字セットを設定します。
  • charset_types: 指定されたMIMEタイプに対して文字セットを適用します。

WordPress

functions.phpでの設定

<?php
// functions.phpに追加
add_action('init', function() {
    header('Content-Type: text/html; charset=UTF-8');
});

// wp-config.phpに追加
define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', 'utf8mb4_unicode_ci');
  • header(): HTTPヘッダーを設定します。
  • DB_CHARSET: データベースの文字セットを設定します。
  • DB_COLLATE: データベースの照合順序を設定します。

wp-config.phpでの設定

define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', 'utf8mb4_unicode_ci');

PHP

PHPコードでの設定

<?php
// HTTPヘッダーの設定
header('Content-Type: text/html; charset=UTF-8');

// HTMLメタタグの設定
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <!-- または -->
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
  • header(): HTTPヘッダーを設定します。
  • &lt;meta charset="UTF-8"&gt;: HTML5での文字セット指定。
  • &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;: HTML4での文字セット指定。

間違った設定例と正しい設定例

間違った設定例

<!-- HTML -->
<meta charset="ISO-8859-1">
<?php
// PHP
header('Content-Type: text/html; charset=UTF-8');
?>

この例では、HTMLメタタグとHTTPヘッダーで異なる文字セットが指定されています。

正しい設定例

<!-- HTML -->
<meta charset="UTF-8">
<?php
// PHP
header('Content-Type: text/html; charset=UTF-8');
?>

この例では、HTMLメタタグとHTTPヘッダーで同じ文字セット(UTF-8)が指定されています。

検出方法

OWASP ZAP での出力例

  • Alert 名: Charset Mismatch
  • リスク: Information
  • URL: 文字セットが一致しないURL
  • パラメータ: なし
  • 詳細: HTTPレスポンスヘッダーとHTMLメタタグで指定された文字セットが異なるという情報

手動再現例

  1. Webブラウザの開発者ツールを開き、Networkタブを選択します。
  2. Webサイトにアクセスし、HTTPレスポンスヘッダーのContent-TypeとHTMLの&lt;meta&gt;タグのcharset属性を確認します。
  3. curl コマンドを使用して、HTTPレスポンスヘッダーを確認します。
curl -I https://example.com

まとめ

  • CVSS 基本値: 2.6 (Low)
  • 運用チームや開発者が意識すべきポイント:
    • Webサイト全体でUTF-8などの一貫した文字エンコーディングを使用する。
    • HTTPヘッダーとHTMLメタタグで指定する文字エンコーディングを一致させる。
    • サーバー設定、アプリケーション設定、データベース設定など、すべての設定で文字エンコーディングを統一する。
    • 定期的にWebサイトの文字エンコーディングを監査する。
  • 再発防止:
    • 開発プロセス全体で文字エンコーディングに関するガイドラインを策定し、遵守する。
    • コードレビューを実施し、文字エンコーディングの設定が正しいことを確認する。
    • 自動脆弱性診断ツールを導入し、定期的にスキャンを行う。
    • 文字エンコーディングに関する設定をInfrastructure as Code(IaC)で管理し、一貫性を保つ。

補足資料・参考 URL

以上の対策と検出方法を活用して、Charset Mismatch のリスクを低減してください。