[PHP] htmlspecialchars 関数の誤った使い方と正しい使い方

naohiro19
記事: 256
登録日時: 13年前
住所: 愛知県

[PHP] htmlspecialchars 関数の誤った使い方と正しい使い方

投稿記事 by naohiro19 » 6年前

【PHP, MySQL】日本語をデータベース格納する時に文字化けが起こる
というbonboさんのプログラムですが、以下のようなプログラムがあります。

CODE:

//エスケープしてから表示
$pen_name = htmlspecialchars($_POST["pen_name"]);
$mail = htmlspecialchars($_POST["mail"]);
$_pass_word = htmlspecialchars($_POST["_pass_word"]);
htmlspecialchars関数は HTMLタグをサニタイズしてくれる便利な関数です。例えば、フォームに入力されたデータが以下のようになっていたとします。

CODE:

alert('hello world!');
これを htmlspecialchars 関数に掛けると以下の文字列に変換されます。

CODE:

<script>alert('hello world!');</script>
ユーザーがJavaScriptの書き方で書いた場合データベースのパラメータに htmlspecialchars関数で変換された結果がデータベースに挿入することになります

ですのでhtmlspecialchars関数はHTMLに表示する場合に用いるための関数です。
ですのでユーザー入力を受け取る場合は filter_input関数を用いて以下のように入力データをきちんと受け取るようにするべきでしょう。

CODE:

$pen_name = (string)filter_input(INPUT_POST,'pen_name', FILTER_SANITIZE_STRING);
$mail = (string)filter_input(INPUT_POST,'mail',  FILTER_SANITIZE_STRING);
$_pass_word = (string)filter_input(INPUT_POST,'_pass_word', FILTER_SANITIZE_STRING);

YuO
記事: 947
登録日時: 13年前

RE: [PHP] htmlspecialchars 関数の誤った使い方と正しい使い方

投稿記事 by YuO » 6年前

naohiro19 さんが書きました:【PHP, MySQL】日本語をデータベース格納する時に文字化けが起こる
というbonboさんのプログラムですが、以下のようなプログラムがあります。

CODE:

//エスケープしてから表示
$pen_name = htmlspecialchars($_POST["pen_name"]);
$mail = htmlspecialchars($_POST["mail"]);
$_pass_word = htmlspecialchars($_POST["_pass_word"]);
(省略)
naohiro19 さんが書きました:ですのでhtmlspecialchars関数はHTMLに表示する場合に用いるための関数です。
ですのでユーザー入力を受け取る場合は filter_input関数を用いて以下のように入力データをきちんと受け取るようにするべきでしょう。

CODE:

$pen_name = (string)filter_input(INPUT_POST,'pen_name', FILTER_SANITIZE_STRING);
$mail = (string)filter_input(INPUT_POST,'mail',  FILTER_SANITIZE_STRING);
$_pass_word = (string)filter_input(INPUT_POST,'_pass_word', FILTER_SANITIZE_STRING);
言及されているbonboさんのトピックでもみけCATさんが指摘されていますが……。
$pen_nameなどが代入後にどこで使われているかというと,直後の
bonbo さんが書きました:

CODE:

        print("登録名「 ${pen_name} 」");
        print("メールアドレス「 ${mail} 」");
        print("パスワード「 ${_pass_word} 」です。");
のみで,データベースへの挿入するためのバインドパラメータには
bonbo さんが書きました:

CODE:

        //?の位置に値を割り当てる
        $stmt->bind_param('sss', $_POST["pen_name"], $_POST["mail"], $_POST["_pass_word"]);
と,送信された値をそのまま使っています。
つまり,htmlspecialcharsはその関数の目的にしか使われていません。

この投稿で, bonboさんのトピックを提示し,引用した意図はなんでしょうか。
タイトルが「htmlspecialchars 関数の誤った使い方と正しい使い方」という表現をしている日記の中で,bonboさんがhtmlspecialchars関数を利用している投稿を引用しているのですから,「bonboさんが誤った使い方をしている」という間違った印象を日記読者に与えるように思えます。
このような日記の構成にするのであれば,少なくとも「どこで使っているから誤った使い方なのか」も正しく指摘すべきでしょう。
誤った使い方をしていないのであれば,それを断った上で言及するか,そもそも言及しないかだと思います。
オフトピック
bonboさんのトピックの最初の投稿は確かに編集されていますが,現時点 (20171029T1110+0900) における最終編集日時は20170908T0906+0900であって,私の投稿その後の解決投稿の2つのみが編集以前の投稿です。
naohiro19さんの投稿は最終編集の3週間後ですから,「編集する前は間違っていた」という指摘をできるタイミングではありません。
なお,常に「FILTER_SANITIZE_STRING」を使うのは間違いです。
PHP: 除去フィルタにも,
タグを取り除きます。オプションで、 特殊文字を取り除いたりエンコードしたりします。
と書いてあるとおり,HTMLのタグと思われるものを入力から除去する,という動作を行うからです。
オフトピック
ソースコード上だと,filter_inputが入口で,関数ポインタを経由してfilter_input_stringを呼び出し,さらにphp_strip_tags_exを呼び出します。
php_strip_tags_exの内容を大雑把に書くならば,までを除去する,です。ステートマシンなので読むのは面倒臭いですが。
これが要件に合う場合はよいのですが,そうでない場合は正しくない動作になります。
言及されているプログラムでは,入力をhtmlspecialcharsに渡して出力しているのですから,FILTER_SANITIZE_STRINGを使うことが正しいとは思えません。
特にパスワード項目で勝手に文字を省けば大問題になります。