「htmlspecialchars
($_GET['text']);」を読む

2008/03/16 第2回PHP懇親会
岩本隆史<hello@iwamot.com>

まずは自己紹介

会社では

個人では

PHPが好きみたい…

現在の興味

さて本題

Matzいわく

htmlspecialchars($_GET['text']);

とかを普通にやっちゃう(しかも、それがゆえに初心者に優しいとかされてる)環境で安全なソフトウェアを書くのは、他の言語に比べて大変困難であろう。(Matzにっき(2008-01-29)

これに対し

はてブでの反応・その1

id:fuktommy
何が問題なのか、わからん。

はてブでの反応・その2

id:rna
なにがまずいのかわからない。/バイナリ食わすとヤバイって話?/入出力を安易に直結しやすいのが問題?

想像ですが

Matzの問題意識(想像)

taintされた文字列をそのまま出力するなんて、考えられへん!

taint?

Matzにっき」より

RubyやPerlでは外部から入力された文字列にtaint(汚染)と呼ばれるマークがつく。taintされた文字列から加工された文字列にもtaintがつく。これをチェックすることで外部からの入力をチェック(サニタイズ)しないまま危険な操作(ファイル名にする、systemを呼び出す、HTML/SQLに埋めこむ、など)を禁止することができる。

なるほど

だから

Matzの問題意識(想像)

外部から入力された$_GET['text']を チェックしないままhtmlspecialcharsで出力するのは危険。考えられへん!

というわけですね

ところで

素朴な質問ですが

何をチェックするの?

答え

不正文字エンコーディング

こうする

<?php
if (!mb_check_encoding($var, $encoding)) {
    throw new Exception('invalid encoding');
}
?>
<p><?php echo htmlspecialchars($var); ?></p>

質問

他にチェックすべき点は?

答え

ありません!

もちろん

URL出力時には、「http://」または「https://」で始まることをチェックする必要があります(『安全なウェブサイトの作り方 改訂第3版』23頁)。

ほかにも

script要素イベントハンドラstyle要素/属性などの内容も動的出力を避けるべきです(完全なエスケープが難しいため)。

でもそれは

taintとは無関係です!

taintとは無関係

外部から入力された文字列だろうが、自分で組み立てた文字列だろうが、たとえばURL出力時にはスキームのチェックが必要なはずです。

taintとは無関係

それは、不正文字エンコーディングのチェックについても同じです。taint か untaint かを問わず、行われなければなりません。

結論

PHP taint support?

(゚⊿゚)イラネ

以上

ありがとうございました!