gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

validateとescapeは違う概念だと思うのだが…

先に。sanitizeについてはなんか定義が色々と怪しいので使いませんw
…とかいいつつ少しだけ書くと。


sanitizeって、基本的に「antidote(解毒)」って概念だと思うのですが。
問題は。現実の毒でもそうなのですが「実際の解毒法は毒の種類によって変わる」です。ゲームアイテムにあるような「毒消し草」は存在しないです。
ついでに「何を以て毒とするか」って定義も曖昧ですしね。人間に作用する毒が同じように鳥類に作用するとは限りません。
なので。
sanitizeという言葉は「概念」として用いる可能性はあったとしても「実装周り」に使える単語では、結局ないんじゃないかと思うです。
ついでに。sanitizeって単語、もう一つ「防毒*1」なのか「解毒*2」なのかも微妙ですしね。使われ方的に。


で、本題。


んと…セキュリティ系の文脈でよく出てくるのですが…もう一つ混ざってる気がしてならないvalidateとescape。
ちとこの概念をいい加減きちんと整理して使い分けたいなぁと思うです。


validateは「有効であるかどうかを検証する」という意味合いがあります。
例えば日本の郵便番号は、2008年現在とりあえず「アラビア数字で3桁と4桁」ってのが有効範囲なので。ここでアラビア数字以外の、例えばローマ数字を持ち込んだり英字をぶち込んだりすると、それは「無効(invalid)なデータ」って事になります。
誕生日であれば「日付が存在しうる月日」ですし。…これが年になると微妙なんですがね(苦笑
ここらあたり、いわゆる「valid(正統)な」データが判断しやすいところになります。


つぎに。
メールアドレス…の正当性(valid)を論じるのは大変に厄介である事は以前に何度か書いたのですが。
今回はまたちぃと別の切り口から。
んと。例えば hoge@foo.com ってのは、存在するかはともかくとして、とりあえずvalidなメアドです。
んで。
小美人<hoge@foo.com>(本当は半角)というアドレスもまた、これはちゃんとvalidなメアドになります。有効部分はhoge@foo.comだけですが。


さらに。
例えば「プログラムを語る掲示板」なんかだったりすると、当然ながら様々な文字が出てくるわけです。
とりあえず

string s = 'INSERT INTO bar(hogera,mugera) VALUES(?,?);';

なんて文字列を想定。
当然ながら掲示板ですし、データとしてはvalid。


ただ。
当然ながら。
HTMLに出力するときに、メールの<>はエスケープせにゃあきませんし、DBにぶち込む時に掲示板の’だの;だのはエスケープしなきゃ酷い事が起きます。
つまり、例題のデータのいくつかは「validではある」けれども「escape対象の文字を含みます」。


ここまでOKでしょうか?


さて。
まぁ結局のところ、発端は「“入力時のサニタイズ”やめれ」いう話からなのですが。
入力時のサニタイズ推奨派の皆様がいう単語の一つに「ちゃんとホワイトリストで云々間ぬん」とかいう発言があります。


ホワイトリストにせよブラックリストにせよ、基本的にこれらは「validate」というチェックに属するものになります。
つまり「ホワイトリストにあるもの以外をinvalidにするのか、ブラックリストに載っているものをinvalidにするのか」という感じですね。
一方で。セキュリティの文脈でXSSとかSQL-Injectionとかの文脈で語られるのは「エスケープ処理が出来ているか否か」という部分であります。


つまりですね。
エスケープ処理を論じるべきところで「ホワイトリスト云々」言われても「駄目だなぁ」と思ってしまうわけですよ。


validateは、もちろん「入力のタイミングで」チェックする事が可能です。なぜなら、validateは「そのデータ項目に紐付いた」属性だから。
でもescapeはそうじゃなくて。escapeは「出力先に紐付いた」属性を持っているので、だからこそ「出力先にあったescape方法が各種とりそろえられている」はず、なのです。


一番肝心なのは「validateとescapeは、意味も趣旨も全然違うんだ」ってところ。
この二つをまぜまぜすると…ちょっと危険な香りが漂います。
あなたは、ちゃんと使い分けて話ができますか?

*1:体内に入る前に防ぐ

*2:体内の毒を無毒化する