PHPエンジニア必見!htmlspecialcharsを使いこなして安全なWebアプリケーション開発を


仕組み

HTML には、<, >, &, ", ' などの特殊文字が存在します。これらの文字は、HTML タグや属性を表すために使用されます。しかし、これらの文字をそのまま出力すると、意図しない動作を引き起こす可能性があります。

<p>ユーザーからの入力: "<h1>悪意のあるコード</h1>"</p>

上記の例では、ユーザーからの入力に <h1> タグが含まれています。これは、本来の表示とは異なる大きな見出しを表示させてしまう可能性があります。

htmlspecialchars を使用すると、このような特殊文字を安全なエンティティに変換することができます。

<p>ユーザーからの入力: &lt;h1&gt;悪意のあるコード&lt;/h1&gt;</p>

上記の例では、<h1> タグは &lt;h1&gt;&lt;/h1&gt; に変換されています。これにより、タグは本来の意味で解釈されなくなり、安全に表示されます。

使い方

$unsafe_string = "<p>ユーザーからの入力: \"<h1>悪意のあるコード</h1>\"</p>";
$safe_string = htmlspecialchars($unsafe_string);
echo $safe_string;

上記のコードは、$unsafe_string に含まれる特殊文字を $safe_string に安全なエンティティに変換し、それを出力します。

オプション

htmlspecialchars には、オプション引数を使用して変換の挙動を制御することができます。

  • $encoding: 文字エンコーディングを指定します。デフォルトは UTF-8 です。
  • $flags: クォートの扱いなどを指定します。デフォルトは ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 です。

htmlspecialchars_decode

htmlspecialchars_decode 関数は、htmlspecialchars で変換されたエンティティを元の文字に戻す関数です。

$safe_string = htmlspecialchars($unsafe_string);
$original_string = htmlspecialchars_decode($safe_string);
echo $original_string;


基本的な使い方

$unsafe_string = "<p>ユーザーからの入力: \"<h1>悪意のあるコード</h1>\"</p>";
$safe_string = htmlspecialchars($unsafe_string);
echo $safe_string;
&lt;p&gt;ユーザーからの入力: &quot;&lt;h1&gt;悪意のあるコード&lt;/h1&gt;&quot;&lt;/p&gt;

オプション引数の使用

$unsafe_string = "<p>ユーザーからの入力: \"<h1>悪意のあるコード</h1>\"</p>";
$safe_string = htmlspecialchars($unsafe_string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
echo $safe_string;

このコードは、以下の出力を生成します。

&lt;p&gt;ユーザーからの入力: &amp;quot;&lt;h1&gt;悪意のあるコード&lt;/h1&gt;&amp;quot;&lt;/p&gt;

上記のコードでは、ENT_QUOTES オプションを指定することで、シングルクォートとダブルクォートもエンティティに変換しています。また、ENT_SUBSTITUTE オプションを指定することで、無効な文字を ? に置き換えています。

$safe_string = htmlspecialchars($unsafe_string);
$original_string = htmlspecialchars_decode($safe_string);
echo $original_string;
<p>ユーザーからの入力: "<h1>悪意のあるコード</h1>"</p>

上記のコードでは、htmlspecialchars_decode 関数を使用して、safe_string に含まれるエンティティを元の文字に戻しています。

  • XML などのデータを出力する
  • データベースから取得した文字列を安全に出力する
  • フォームからの入力値を安全に出力する


代替方法

  1. htmlentities 関数

    "htmlentities" 関数は、"htmlspecialchars" 関数と似ていますが、すべての特殊文字をエンティティに変換します。つまり、"<", ">" などの記号だけでなく、"&", "ä", "ö" などの文字もエンティティに変換されます。

    $unsafe_string = "<p>ユーザーからの入力: \"<h1>悪意のあるコード</h1>\"</p>";
    $safe_string = htmlentities($unsafe_string);
    echo $safe_string;
    
    &lt;p&gt;ユーザーからの入力: &quot;&lt;h1&gt;悪意のあるコード&lt;/h1&gt;&quot;&lt;/p&gt;
    
  2. mb_convert_encoding 関数と html_entity_decode 関数の組み合わせ

    "mb_convert_encoding" 関数は、文字列のエンコーディングを変換することができます。この関数と "html_entity_decode" 関数を組み合わせることで、"htmlspecialchars" で変換されたエンティティを元の文字に戻すことができます。

    $unsafe_string = "<p>ユーザーからの入力: \"<h1>悪意のあるコード</h1>\"</p>";
    $safe_string = htmlspecialchars_decode($unsafe_string, ENT_QUOTES | ENT_SUBSTITUTE);
    $safe_string = mb_convert_encoding($safe_string, 'UTF-8', 'HTML-ENTITIES');
    echo $safe_string;
    
    <p>ユーザーからの入力: "<h1>悪意のあるコード</h1>"</p>
    
  3. ライブラリの使用

    "htmlspecialchars" の代替となるライブラリがいくつか存在します。例えば、"HTML Purifier" や "Twig" などのライブラリは、XSS 対策だけでなく、HTML の整形や検証などの機能も提供しています。

"htmlspecialchars" を使用するべき状況

  • XML などのデータを出力する場合
  • データベースから取得した文字列を出力する場合
  • ユーザーからの入力をそのまま出力する場合
  • より高度な機能が必要な場合
  • エンティティを元の文字に戻したい場合
  • 特定の文字のみをエンティティに変換したい場合