[PR]小規模ECサイトに最適なWAF、SiteGuard Lite
徳丸浩の日記
2007年09月09日 入力値検証について(2)
_ アプリケーションの先頭で行う入力値検証は業務要件により行うべし
前回のエントリ徳丸浩の日記 - そろそろ入力値検証に関して一言いっとくか - Webアプリケーション脆弱性対策としての入力値検証についての内容をもう少し突っ込んでみたい。
このエントリは、幸いにも何人かの人たちの建設的なコメントをいただくことができた。それにより、私自身の考えを整理し、深めることができたように思う。
T.Teradaの日記 - 2007-09-08
"週"記(2007-09-07)
今回は、入力値検証の中でも、特にアプリケーションの先頭で行う入力値検証として何をすべきかということに焦点を絞って議論を進めたいと思う。
その前に、まずHTTPの復習から。
HTTPリクエストは申請書にたとえると理解しやすい
この日記の読者の多くは先刻ご存知だと思うが、HTTPは非常にシンプルなプロトコルである。WebサーバはHTTPリクエストを受付け、HTTPレスポンスを返す。それを延々と繰り返す。HTTPリクエストには、ファイル名に加えて種々のパラメータをセットできる。このパラメータ類を「Webアプリケーションの入力」とここでは呼ぶことにしよう。具体的には、クエリ・ストリング、POSTパラメータ、Cookieなどである。
HTTPリクエストを発行する際には、通常はHTMLフォーム上で規定された形式に従うが、現実にはどのようなパラメータをどのようにセットすることも呼び出し側の勝手である。ここで、HTTPリクエストを申請書にたとえてみると、申請書の形式は一応HTMLフォームで規定されている。しかし、申請書記入者は、指定の申請書形式に従わずに、項目を勝手に追加したり、申請書指定の形式(文字種や文字数など)を無視して自由に項目を記述することができる。
アプリケーションが申請書を受け付けるかどうかは早期に決定したい
役所や銀行などで、申請書類を提出すると、まず窓口で、申請書が所定の書式に沿っているかをチェックされ、一箇所でも間違いがあると、つき返される。一方、書式に間違えがなければ、受理され、バックオフィスで処理されることになる。窓口での書式確認は、形式ばっているようにも見えるが、申請書の間違いにバックオフィス側で初めて気がついて、申請書が行ったり来たりする無駄を考えれば、一応の合理性がある。
これと似たことはアプリケーションにもある。HTTPリクエストに記載されたパラメータ類は、アプリケーションの期待する形式になっているかどうかは保証されていない。仮に、アプリケーションの処理が相当進んでから、たとえば必須項目が足りずに処理が継続できなければ、今までの処理をロールバックして「なかったこと」にしなければならない。場合によっていは、ロールバックができずに、オペレータの手作業により、リカバリーしなければならないケースもあるだろう。現実には、上記は相当低レベルな話であり、アプリケーションは以下のような入力値チェックを「処理に先立って」実施することになる。
・必須項目が揃っているか
・各項目は指定の書式(型、文字数など)に従っているか
・形式が決まっている場合のチェック(電話番号、メールアドレスなど)
これらのチェックが通れば、申請書は受理され、処理にまわることになる。さて、ここからが本題である。
申請書に相当するHTTPリクエストが受理される要件は、セキュリティ上の都合ではないはずである。例えば、以下のような会話はどうか。
役人:えーっと、中村さん、住所欄に「'」は使えませんよ。書き直してください。 中村:そう言われても、アパート名がこうなんだからどうしようもないでしょ。 役人:とにかく駄目なものは駄目です。別の文字にしてください(*1)。
(*1)うわ、サニタイズ言うな
すなわち、申請書が受理されるかどうかの条件は、原則として全て業務要件によって決まるはずである。通常、現実の申請書には、書式が詳しく説明してあり、その条件を満たしているにも関わらず返却されたら、申請者は相当ムカツクはずである。
ケーススタディ
さて、T.Teradaの日記には以下のコメントがあるが、
徳丸さんの日記は、ユーザがテキストボックスなどで自由に値を入力できる住所などのデータを主に対象としたものだと思う。
私は、ラジオボタン、チェックボックス、セレクトボックスなどの場合でも、業務要件として入力チェックをすべきだと思う。これは申請書のたとえで言えばこういうことである。
たとえば、申請書の「性別欄」には、「女」や「男」と文字で記述する場合もあるが、多いのは男の場合は「1」、女の場合は「2}と番号が記載してあって、番号に丸をつけるか、番号を記入欄に記載する。申請書にはその方法が指定されている。ヤカマシい役所であれば、「『男』と書かずに、1に丸をつけてください」と言われるかもしれない。
Webアプリケーションの場合で言えば、性別欄がラジオボタンになっていて、その値が男の場合は「M」、女の場合は「F」だとする。性別欄が「M」か「F」のいずれかでなければ処理を継続できないわけだから、この値チェックは業務要件として必要である。
一方、先のエントリで問題になった、任意列でソートできるテーブルの場合はどうか。
この場合、ユーザの入力は、ソート対象となる列指定である。列の指定方法はアプリケーションの実装として決めればよいわけで、列番号(1,2,3...)でも良いし、表の各項目の論理名であってもよいし、対応するDBの物理的な列名を採用することもできる(前回議論の対象になった方法はコレ)。私自身の好みでいえば、DBの列名を外部にさらすのは色々な意味で抵抗があるので、たとえば列番号を指定してもらって、アプリケーションの内部で列名に変換するようなロジックにするだろう。
いずれにせよ、「申請書」に書くべき内容はソート対象の列指定であるが、その書式はアプリケーションの要求として決まっているものであって、一種の業務要件としてチェックすべきだということである。列番号を指定するのであれば、整数であることや数値の範囲のチェックが必要であろうし、列の論理名あるいは物理名を指定するのであれば、名前のチェック(文字種ではなく、列名として存在するか)が必要である。これらはいずれもSQLインジェクション対策としては、そこまでやる必要はない。あくまで、アプリケーションを正常に動作させるために必要な条件である。
「システム起源のデータ」をどうするか
T.Teradaの日記には、Webアプリケーションには「システム起源のデータ」というものがあって、この場合は入力値検証をすべきであると指摘されている。現実のWebアプリケーションに「システム起源のデータ」が存在することを私も認めるものであるが、しかし、HTTPリクエストが必ずしもアプリケーションに制約されないという条件下では、「システム起源のデータ」をHTTPにより受け渡しすることは非常に危険だ。私は「システム起源のデータ」も(広い意味で)ユーザからの入力に限定すべきであると考える。先に述べたソート対象列の指定のその一例である。そして、ユーザからの入力であれば業務要件としてのチェックが可能であるが、そうでないもの(セッションIDなど)は、極力少なくするべきであると思う。この点についてはまた稿をあらためて説明したい。
まとめ
アプリケーションの先頭で行う「入力値検証」は、従来セキュアコーディングの文脈で語られることの多かったが、現実には業務要件として行うべきものである。そして、業務要件として受付可能なリクエストは、特別なことがない限り処理されるべきであり、逆に処理できないものは業務要件として、入力に制限が掛っているべきである。例えば、メールアドレスに改行が混ざってはいけないというのも、申請書(伝票)の書式として要求できるものであり、現実問題、改行の入ったメールアドレスには(セキュリティ以前に)処理できない。
さて、業務要件としての入力値検証を実施すれば、結果としてクロスサイト・スクリプティング(XSS)対策やSQLインジェクション対策にもなっているケースは多いが、これらインジェクション系脆弱性対策と、アプリケーションの先頭での入力値検証は別物として考えた方がよいと思う。アプリケーションにはバグはつきものであり、入力値検証が正しく実装されていない場合もある。また、アプリケーションの脆弱性検査や保守をする際に、入力値検査で「検査済み」の項目と、それ以外の項目(入力値でないものも含む)を明確に区別することが難しいことによる。入力値検証が業務要件チェックとして行われている以上、脆弱性対策はそれら値を使う時(出力時)にすべきものとした方が、考え方がシンプルになり、アプリケーションの開発ライフサイクルのトータルで考えれば結局は安上がりになると考える。
一般に、セキュアコーディングの基本として入力値の検証(Validation)をせよということになっていますが、これが変な方向に行くといわゆる「サニタイズ」のような手法になってしまいます。以前も指摘したように、アプリケーションとしてのValidationは仕様に従って行うべ
- http://www.tokumaru.org/ ×70
- http://d.hatena.ne.jp/ockeghem/20090307/p1 ×44
- https://www.google.co.jp/ ×31
- http://www.askapache.com/ ×3
- http://www.tokumaru.org/was/ ×2
- http://www.umontpellier.fr/agenda/semaine-de-linse... ×1
- http://www.tokumaru.org/bbs/bbs_backnumber_004.htm... ×1
- http://www.tokumaru.org/QA/ ×1
- http://www.sophia-it.com/content/Windows Server 20... ×1
- http://translate.googleusercontent.com/translate_c... ×1
- Windows7 アプリケーションの要件 検証 ×2 / 入力値 検証 ×1 / SQL 入力項目 チェック ×1 / POSTパラメータ 危険性 ×1 / webアプリ 入力チェック ×1 / 入力の検証はモデルで行う ×1 / ウェブアプリケーション 脆弱性確認方法 入力値 ×1 / 入力値チェック logic backingbean ×1 / +Java 入力値チェック 先頭 ×1
[PR]小規模ECサイトに最適なWAF、SiteGuard Lite
HASHコンサルティング株式会社
最近の記事
- 2011年08月30日
- 1. RSSフィードをリダイレクトします
- 2011年07月01日
- 1.
- 2011年03月29日
- 1. PDO/MySQL(Windows版)の文字エンコーディング指定の不具合原因
- 2011年03月22日
- 1. PHP5.3.6からPDOの文字エンコーディング指定が可能となったがWindows版では不具合(脆弱性)あり
- 2011年01月27日
- 1. CSRF対策のトークンをワンタイムにしたら意図に反して脆弱になった実装例
- 2011年01月04日
- 1. escapeshellcmdの危険な実例
- 2011年01月01日
- 1. PHPのescapeshellcmdの危険性
- 2010年10月03日
- 1. 問題点の概要
- 2010年09月27日
- 1. 文字コードに起因する脆弱性を防ぐ「やや安全な」php.ini設定
- 2010年07月25日
- 1. ツッコミSPAM対策で、ツッコミ抜きのRSSフィードを用意しました
- 2010年07月01日
- 1. ぼくがPDOを採用しなかったわけ(Shift_JISによるSQLインジェクション)
- 2010年04月06日
- 1. PROXY(プロキシ)経由でのDNSリバインディングと対策
- 2010年04月05日
- 1. JavaアプレットのDNSリバインディングはJRE側で対策済みだった
- 2010年03月29日
- 1. DNSリバインディングによる無線LANパスフレーズの読み出しに成功
- 2010年03月25日
- 1. DNSリバインディングによるルータへの侵入実験
- 2010年02月22日
- 1. ケータイtwitter(twtr.jp)においてDNS Rebinding攻撃に対する脆弱性を発見・通報し、即座に修正された
- 2010年02月12日
- 1. かんたんログイン手法の脆弱性に対する責任は誰にあるのか
- 2010年01月18日
- 1. iモードブラウザ2.0のXMLHttpRequestでPOSTデータの扱いが困難になった
- 2009年10月19日
- 1. quoteメソッドの数値データ対応を検証する
- 2009年10月14日
- 1. htmlspecialchars/htmlentitiesはBMP外の文字を正しく扱えない
- 2009年10月09日
- 1. htmlspecialcharsのShift_JISチェック漏れによるXSS回避策
- 2009年09月30日
- 1. htmlspecialcharsは不正な文字エンコーディングをどこまでチェックするか
- 2009年09月24日
- 1. SQLの暗黙の型変換はワナがいっぱい
- 2009年09月18日
- 1. 文字エンコーディングバリデーションは自動化が望ましい
- 2009年09月14日
- 1. 既にあたり前になりつつある文字エンコーディングバリデーション
- 2009年08月05日
- 1. 携帯JavaScriptとXSSの組み合わせによる「かんたんログイン」なりすましの可能性
- 2009年03月28日
- 1. IPAは脆弱性の呼び方を統一して欲しい
- 2009年03月27日
- 2009年03月11日
- 1. U+00A5を用いたXSSの可能性
- 2008年12月22日
- 1. JavaとMySQLの組み合わせでUnicodeのU+00A5を用いたSQLインジェクションの可能性