読者です 読者をやめる 読者になる 読者になる

チリペヂィア

リンクフリー。サンプルコードなどは関連記事内でライセンスについて明示されない限り商用利用なども自由に行って構いませんが、自己責任でお願いします。またこれら日記内容の著作権自体は放棄していません。引用部分については引用元の権利に従ってください。

構造的にもこれが原則のような気がする。

もう入力値検証はセキュリティ対策として *あてにしない* ようにしよう
http://tumblr.tokumaru.org/post/55393403591

今更なんですがkiriのクリームチーズが金属片混入で回収になったので思い出しました。これが結構面白いんですよ。

  • チーズがアルミ包装なので、包装後に金属検査できない
  • 金属検査後の包装プロセスで故障した機械から金属片混入

金属片の混入は機械で探知したわけで無く「壊れた機械の中から破片が見つからなかったから」判明と言うより類推されたようです。あーわかるわかる。で、ニュースでコメンテーターが「じゃあビニール包装にしたらプラ片混入は探知できるんだろうか」ってなかなか鋭い事を言う。出来ないことは無いでしょうが、きっとこれらを技術で強引にクリアする探知機は、そうでない機械よりお高いのでしょう(*1)。それはそれでチーズの価格が上がってしまう!

純粋理論(またはアルゴリズムマニア)の視点で最適化戦法、あるいは手抜き・安上がりの素晴らしさを訴えるなら、validationと完全性チェックの混成を発想するのは当然とも思うんですが、一方で工学の常識として「処理すれば悪いデータに化ける可能性は常に生じるんだから、どっちみち完全性チェックなんて最終フェーズ以外に置けない」んですよね。kiriの場合は「できるだけ後ろに置いたけど、残りの処理でトラブった」ケースですね。

話を戻して、完全性チェックとしてセキュリティ検査する場合、少なくとも最終フェーズにセキュリティ検査は必要です。時々は漏れても構わないセキュリティ検査なんてないでしょうし。

その上でさらにvalidationにプレ・セキュリティ検査をつけて複雑にすると仕様変更の時に大変です。最終セキュリティ検査部分の変更にあわせてvalidation部分のプレセキュリティ検査も整合性が壊れないように手を入れなくちゃいけません。メンテナンスコストが上がってしまいます(処理が長いほど作業はどんどんキツくなり、デグレードなバグの発生率は上がっていくでしょう)(*2)。

そもそもvalidationの検査処理は、完全性の担保ではなく、validationと最終検査の間に行う途中の処理のロジックを簡潔にするためじゃないでしょうか。

ファイルパスの例で言えば「あきらかに想定するファイルパスじゃない文字が出現するパターン」に対して、

  • 途中の処理もすべてその特殊パターンに対応するくらいならvalidationで蹴っちゃえばラク
  • べつに完全性を達成してるわけじゃない(そもそも最終処理で無ければ完全性の担保が難しい)

これさえ意識しとけば良いのでしょう。

フレームワークや言語が標準機能である程度やってくれるという話もありますが、かと言って常に万全というわけでもありません(*3)。もし書くとしても、理解が浅い場合は一見して「似てるけど本質的に目的が違う処理」までは読み解けないものなので、業務の場合は下手にvalidationにセキュリティ検査っぽい処理を書くのは指摘通りに誤読の危険が大きいでしょうね…。

*1:例えばビニール包装した上でx線検査を画像解析して怪しい奴を人間の目で再検査するとか…。うーん。コスト対効果だけで言えば完全性はトレードしてしまって、機械を修理してそのまま使い続け、出荷前に頻繁に機械を点検する方が安いかもしれません。

*2:あるいは仕様のスキマを突いて、validationで絶対に完全性が保証できるパターンがあったとしても、その仕様が変わるケースでは大変。

*3:例えば、validation後の加工処理を推測して行う攻撃:処理の結果、攻撃的データに置換される入力、に対して安全性は一般的には担保できません。このバックドアが成立し、発見されて、攻撃されて問題が表面化するのは天文学的な確率とは思いますが、成立しないことが証明できる理屈があるわけでもないので、フレームワークなど環境によるプレ処理サポートがあってもによって完全性が達成できるかは、結局、プログラムの個別の仕様に依存し続けるところでしょう(それに言語の標準ライブラリは処理負荷を前倒しする傾向が強い気がします…結局必要な処理なら初期化の時点で集中的に行い、後の処理を軽くするようなパターンが多い=出力の都度フックするような設計は珍しい、ような…確かにライブラリ屋さんも、「汎用性のために重くなるのは仕方ない」けれど「使うほどに重いライブラリを書くのはイヤ」なんじゃないかな…)。で、ソフトの設計が意識していない穴が表面化するかはどこまでいっても運です。この種の問題は常に「設計が穴を意識していない」ところから生じます。なのでフレームワークがどの段階でどういったフォローをするのか設計レベルで意識しなければ穴が無いとは言い切れません…それでも、フレームワーク+完全な記述パターンが確立すればだいぶ助かりますね。その時だけは手軽に完璧なコードが書けます。