サニタイズ言うなキャンペーンというのがある。しかし,このキャンペーンは有効に働いていないように思える。分かりにくいからである。分かりにくい原因はサニタイズの定義がきちんとなされていないからである。
高木さんが2005年の暮から「サニタイズ言うなキャンペーン」を行っている(高木浩光@自宅の日記 - 「サニタイズ言うなキャンペーン」とは何か)。Web のプログラミングにおける注意の喚起である。しかし,分かりにくい。全文を読まなければならず,要点がつかみにくいのである。どうやら分かりにくいという意見があったらしく,要約版が出た(高木浩光@自宅の日記 - 「要約版:「サニタイズ言うなキャンペーン」とは)。要約版には,分かりやすいようにとの配慮から「結論」が最初に書いてあるが,これでも分からない。それならば,「サニタイズせよと言うな」と表現してはどうかという意見が出たが(「サニタイズ言うなキャンペーンがわかりにくい理由」@水無月ばけらのえび日記),その言い方では有効なキャンペーン効果は得られそうにない
というのだ(高木浩光@自宅の日記 - 続・「サニタイズ言うなキャンペーン」とは)。ますます分からない。分かりにくさの一因は,例外を含めたすべてのことについて説明しようとしていることにある。
この記事の目的は,サニタイズとは何かを知り,キャンペーンを理解することである。
インターネット上にあるサニタイズに関する間違った説明に対しては,辛口のコメントがつけられている(はてなブックマーク - HiromitsuTakagiのブックマーク)。「キャンペーン誤読」の指摘があるが,何が誤読なのかも分からない。私が自分で理解できていないからである。そして,いつ自分にダメ出しが来るだろうかと思い,ドキドキして眠れなくなった。「サニタイズ言うな地獄」である。やっと眠れたと思ったら夢に出てきた。
セキュリティを考慮することは大切である。しかし,必要以上に心配することはない。無駄にドキドキする必要はないはずである。何とかできないものか。
最近,また高木さんがサニタイジングに関する記事を出した(高木浩光@自宅の日記 - WASF Times版「サニタイズ言うな!」)。それでようやく分かってきた。何が原因で「サニタイズ言うな」が分かりにくかったかが分かってきたのである。それは「サニタイズ」という用語がきちんと定義されていないからである。高木さんはサニタイズの再定義をやろうとして一度断念しているが(高木浩光@自宅の日記 - 続・「サニタイズ言うなキャンペーン」とは),そう言わずに,きちんとした再定義をお願いしたい。人は認識したものでなければ捨てられないからだ(nlog(n): 差別語が含まれている魚)。定義してから捨てればよい。そうすれば,「すでに理解している人にとっては繰り返しでウンザリで,理解していない人にとっては何度言われても分からない」という状況から脱け出すことができるのではないかと思うのだ。
何とかこの悪夢から解放されたい。そこで,私なりにサニタイジングに関する要点をまとめてみることにした。すこし冗長だが,次の5点である。
1 がサニタイズすることの定義である。しかし,定義であるにも関わらず「入力を消毒」という曖昧な表現になってしまっている。これは専門家にお任せしたい点である。2 は補助的な定義で,出力に関しては使わないことを強調している。3 が「サニタイズ言うなキャンペーン」の主張である。1 と 3 から,「サニタイズする」ことは間違いであり,正しいプログラムにはサニタイズという用語は適さないことが導かれるのである。入力を消毒してはいけない。「消毒する」には,「消毒して使う」というニュアンスが含まれてしまう。使ってはいけないのだ。4 は処理を続行するのを諦めて,例外処理にまわすことを意味する(高木浩光@自宅の日記 - 「要約版:「サニタイズ言うなキャンペーン」とは)。5 では,入力時ではなく出力時にメタ文字のエスケープを行うことを言っている(高木浩光@自宅の日記 - WASF Times版「サニタイズ言うな!」)。
ここでのポイントは,サニタイズの意味を狭い範囲に限定し,拡大解釈を捨てたことにある。それだけでかなり明確になる。単純でなければ把握できないからだ。把握できなければキャンペーンにならない。
次に,PHP プログラムでの実例を見ていくことにする。私は以前,一般の HTML ページに PukiWiki 風のコメント欄をつけるためのスクリプト Very Simple Shoutbox in PHP v1.0 を書いた(nlog(n): Picasa の Web エクスポートに PukiWiki 風のコメント欄をつける)。PHP で書いた初めてのスクリプトだったので,忘れないようにメモも残した(nlog(n): Very Simple Shoutbox 1.0 解説)。以下に引用してみよう。
サニタイジング関数部
function clean($name, $maxlen) {
$name = ereg_replace("[[:space:]]", " ", $name);
$name = mb_strimwidth($name, 0, $maxlen);
$name = htmlspecialchars($name, ENT_QUOTES);
return $name;
}POST された投稿者の名前とメッセージは,サニタイジング用関数で無害化する。まず,タブや改行をスペースに変換する。メッセージ用データファイルは区切り文字をタブにしているからである。
mb_strimwidth() はマルチバイト対応の関数で,指定した文字数で文字列をカットする(PHP: mb_strimwidth - Manual)。マルチバイト対応でない関数 (substr 等) を使うと,2バイト日本語文字が文字の中間で切られる可能性があり,文字化けの原因になる。
最後に htmlspecialchars() で,HTML タグで使う文字を実体参照文字に変換している。HTML タグが入力されても,変なことが起こらないようにしている。htmlspecialchars() 関数は,前の mb_strimwidth() より後ろでなければならない。前に使うと,mt_strimwidth() が実体参照の途中で切ってしまうことがあるからである。
やってしまっている。私も「入力時にサニタイジング」だと思っていたからだ。不適切な点は次の通り。
たかだか50行のスクリプトだが,修正した方がよさそうだ。それは別の機会に。
本当は,気づかれないうちにそっと書き直してしまおうかと思ったのだが,正しい姿勢ではないような気がしたのでやめた。悪い事例として残すことには意味がある。
この記事が高木さんの主張と同じであるかは,実は確信がない。しかし,上記5点の「サニタイジングをしないための要点」を踏まえれば,高木さんの一連の記事が安心して読めるようになることは確かだ。
次の2つの表現「サニタイズとは入力の際に行うパラメタ洗浄の処理のことを言います」「入力の際にサニタイズでパラメタ洗浄するのが正しい処理です」は非常に似ている(同じ単語を使って作文してみた)。しかし,似て非なるものである。前者は正しく,後者は間違っているのだ。これも上記「要点」を踏まえれば判断できる。
細かいことだが,sanitize は動詞なので,日本語にするときは「する」をつけて「サニタイズする」,名詞で使うときは「サニタイジング」と表現するのが,私は好きだ。高木さんが「サニタイズ」で統一しているのは,「サニタイズ」で検索したときや,タグ付けへの配慮からだと思われる(これ想像)。
サニタイジングの悪夢から逃れた後は,CSRF にうなされそうだ。皮のジャケットを着たレイザーラモン HG が,腋毛をジェリジェリやりながらフォ〜ッ! と叫んでいる姿を想像してしまったからだ。CSRF とは,クロスサイトリクエストフォージェリというものらしい(まだよく分かっていない)。
Posted by n at 2007-02-07 23:16 | Edit | Comments (0) | Trackback(0)
Master Archive Index
Total Entry Count: 1957