Hatena::ブログ(Diary)

Memo

2008-04-11

[] Re:ENT_QUOTES脳?

突っ込み頂いたから返信します。

via 岩本隆史の日記帳 さん

「こんにちは」から始まる1行のみmain.phpに書かれているということだろう。

このコード、htmlspecialcharsの第2引数が「ENT_QUOTES」でなかったらどんな問題があるというのか。私にはまったく分からない。

「いや、問題がある」という方は、高木浩光さんの下記記事も批判してみてはどうか。

http://d.hatena.ne.jp/IwamotoTakashi/20080411/p1

こんな簡単なコードに一々 目くじら立てて、ENT_QUOTES 漏れを突っ込むなよって事でしょうか?

それなら「セキュリティを気にしましょうね」と啓蒙している web デザイナ向けの記事で、エスケープ漏れのあるコードを提示していることです。

これを読んだ PHP 初心者が htmlspecialchars に第二引数、第三引数を書かないダメコードを量産する可能性があるのが問題です。


タグの属性部分を出力するときは次のように書く。

    htmlout('日時文字列を入力してください。');
    htmlout_tag('<form>');
    htmlout_tag('<input type="text" name="strdate" value=');
    htmlout_quote($strdate);
    htmlout_tag('>');

使用した関数の定義はたとえばこんな感じだ。

function htmlout($str) {
    echo htmlspecialchars($str, ENT_NOQUOTES);
}
function htmlout_quote($str) {
    echo '"' . htmlspecialchars($str) . '"';
}
function htmlout_tag($str) {
    echo $str;
}
http://takagi-hiromitsu.jp/diary/20051227.html#p02

高木浩光さんの上記のコードだと、自分で出力を制限できるパターンですよね?

ENT_NOQUOTES とわざわざクォートしていないのはタグを正しく表示する為でしょう。

# $strDate がユーザが入力した値が格納されている変数かどうか判断できませんが・・・。

# もしユーザが入力できる値ならば問題ですね。

builder の記事はユーザが値を自由に入力できるから問題なのです。


HTML出力を書くときは、むしろタグを出力したいときの方が例外的であると考 えるのがよい。たとえば、echo を全面的に使用禁止として次のように書くの もよいだろう。――(E)

while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
    htmlout_tag('<p>');
    htmlout('No.' . $row["id"]);
    htmlout_tag('<br />');
    htmlout('題名:' . $row["title"]);
    htmlout_tag('<br />');
    htmlout('名前:' . $row["name"]);
    htmlout_tag('<br />');
    htmlout('日時:' . $row["postdate"]);
    htmlout_tag('<br />');
http://takagi-hiromitsu.jp/diary/20051227.html#p02

上記の例だとユーザが入力したであろうと想像できる $row["title"] や $row["name"] は ENT_NOQUOTES となってるのでマズいですね。

以下のように書かれているので、矛盾しています。

正しくは全ての変数をエスケープ対象とせよが基本であるし、変数だけじゃな くて式全体をエスケープの対象とするべきなのに、「サニタイズ」という言葉 で教育が行われていると、その考え方に至る機会が殺がれてしまう。

だから、「サニタイズ言うな」なのだ。

http://takagi-hiromitsu.jp/diary/20051227.html#p02

大垣さんも技評の記事で、以下のように書かれています。

出力する場合はエスケープした出力をデフォルトに設定

アプリケーションではechoやprint文など,文字列を直接出力する関数は利用しないようにします。簡単なラッパー関数を作成し,デフォルトではエスケープして出力するようにします。

http://gihyo.jp/dev/serial/01/php-security/0011

これはコードの書き方こそ違え、高木さんの言わんとしている事と同じようにサニタイズじゃなくてエスケープして当然という考えだと私には読めました。

で、折角エスケープするのなら、正しくエスケープしろよ・・って事です。


因に ENT_QUOTES をつい忘れちゃったという人の為に、id:masugata さんがいっその事 ENT_QUOTES をデフォルトにしちまえっていうようなポストもありました。

「PHP_SELF」は利用していないので別に構わないのですが、htmlentities関数とhtmspecialchars関数の(デフォルトの)挙動は確かに。。。

うっかりすると忘れてしまう時がありますね。

という訳でデフォルトの動作を「ENT_QUOTES」にするタコさんパッチ

http://d.hatena.ne.jp/masugata/20060228#p2

返す刀でバッサリ斬られる覚悟で書きました。


# 追記

あと何故 ENT_QUOTES を書かなくても問題ないと思われたのか是非教えて頂きたいです。

煽りでもなんでもなく、純粋に興味があります。

# 2008/4/13 12:55 追記

ずるい言い方ですが「問題ない」とは書いていません。「問題があるとされる理由が分からない」と書いたのです。

main.phpにおいて「'」が「'」に変換されないことでXSSの危険性が増すというなら、ぜひ攻撃例を教えていただきたい。

http://d.hatena.ne.jp/IwamotoTakashi/20080411/p1

あぁ、なるほど、そういう事でしたか。確かに XSS できませんね。


2008年04月12日  HiromitsuTakagi セキュリティ, 脆弱性, サニタイズ脳, ENT_QUOTES脳, XSS, 教育, 丸暗記式セキュア開発, PHP, bad 暗記式の啓発が裏目に出る事例。原理からの理解に達していないのに自己の無理解に気付かない。結果として先日のPHPSPOTの事例のようなミスを犯し得る →http://b.hatena.ne.jp/entry/http%3A//phpspot.org/blog/archives/2008/01/phphtmlspecialc.html

高木さんご本人からコメント頂いた。ご指摘ありがとうございます。

リンク先の事は知りませんでしたが、読みました。

なるほど・・安易に ENT_QUOTES で済ませば OK という考え方は危険ですね。

認識あらためます。


id:IwamotoTakashi さん、高木さんありがとうございました。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/heavenshell/20080411/1207941262