Hatena::ブログ(Diary)

ockeghem(徳丸浩)の日記 このページをアンテナに追加 RSSフィード

[PR]WAFの導入はHASHコンサルティング
 |  

2011-12-07

徳丸本をブロガーに差し上げちゃうキャンペーンのお知らせ 徳丸本をブロガーに差し上げちゃうキャンペーンのお知らせを含むブックマーク

「徳丸本」こと「体系的に学ぶ 安全なWebアプリケーションの作り方」は、このたび増刷(第5刷)が決定いたしました。皆様のご愛読に深く感謝申し上げます。増刷を記念して、徳丸本を買いたくてもまだ買えていなかった方々に、徳丸本を進呈するキャンペーンを企画いたしました。

私の手元に徳丸本第3刷の在庫が数冊あります。元々献本用や(HASHコンサルティングの)営業活動の贈呈用として購入していたものですが、思ったほど「差し上げる」機会がなくて、死蔵されているような格好でした(この在庫とは別に増刷ごとに何冊かずつ送付いただいているため)。そんなタイミングで第5刷が出ることになったので、これはいかん、在庫をなんとかしなければと思いました。

とはいえ、著者である私が、Yahoo!オークションやAmazonマーケットプレイスでこの在庫を販売することもためらわれました。

そこで、冒頭に書いたように、何冊かを進呈しようと思い立ちました。

キャンペーンの概要

以下の条件に該当する方で、応募いただいた中から、数名の方に徳丸本を進呈いたします。

必須条件(and条件)

  • 徳丸本を持っていない方
  • 継続してブログを書いておられる方
  • 当選後、感想などをブログに書いていただける方

できれば学生さんなど、収入の限られる方を応援したいと思っております。

また、感想は何でも率直な意見等を書いていただければ結構です。当方からは、特に制約はつけません。普段、他人様の書籍を酷評している立場ですので、自分の時だけ「ほめてね」とは、注文をつけるわけにいかないと思っております。

書籍費用と発送費用は徳丸が負担いたします。徳丸のサインをご希望の場合は、サインします。

また、前述のように、進呈する書籍は「徳丸本」第3刷です。その後の変更内容については、正誤表をご確認ください。

応募方法

以下のいずれかの方法で「徳丸本プレゼント応募」とご連絡ください。

  • twitter上でメンションいただく( @ockeghem )
  • メールする( 'or'1'='1'--@tokumaru.org )

いずれの場合でも、ブログURLを明記ください。また、当方から受信確認の返信を必ずしますので、もし返信がない場合は、恐れ入りますが再確認をお願いいたします。

締め切りはとくに設けません。応募いただいた中から不定期に選考させていただき、当選された方に連絡します。発送に先立ち、ブログにて「当選した」旨を発表ください。それを確認後に、書籍を発送いたします。また、在庫のうち何冊を進呈するかは特に決めていません。

選考は、徳丸の独断と偏見で行いますので、あらかじめご了承ください。ブログの内容が高度であるとか、読者が多い必要はまったくありません。ただし、徳丸本の読者層に当てはまっているかどうかは見させていただく可能性があります(徳丸本は元々は初心者向けとして企画されました)。「応募した」旨のエントリにて決意のほどを表明いただければ、当選の可能性は高まると思います。

また、キャンペーンで不明なことがあれば、twitter上のメンションで質問してください。適宜、回答をこのエントリに追記したいと思います。

それでは、皆様のご応募をお待ちしております。

2011/12/17 15:00追記

キャンペーンの申し込みは締め切りました。18名の方にご応募頂きました。活発なご応募に感謝します。現在、当選者の方に連絡しております。

[PR]

安全なWebアプリケーションの作り方DRMフリーのPDFによる電子版もあります。

2011-12-03

何が正しいのかを考える際は、正しさの基準が必要 何が正しいのかを考える際は、正しさの基準が必要を含むブックマーク

 大垣さんの寄稿記事「第44回 セキュリティ対策が確実に実施されない2つの理由:なぜPHPアプリにセキュリティホールが多いのか?|gihyo.jp … 技術評論社」のまとめにて、『最後に「何が正しいのか?」常に考えるようにしてください』と書かれています。この部分は、私への反論のようですので、このエントリで返答したいと思います。

大垣さんの主張

 先にも述べたように、大垣さんはこのエントリの「まとめ」として以下のように書かれています。

最後に「何が正しいのか?」常に考えるようにしてください。

http://gihyo.jp/dev/serial/01/php-security/0044?page=2

 この主張自体には私も大賛成です。大垣さんの記事は以下のように続きます。

例えば,SQL文を作成する場合にリテラルパラメータ)を文字列としてエスケープすると浮動小数点型のデータが正しく処理されないデータベースがあります。これは,SQLインジェクション対策の基本の1つである「すべてのリテラル文字列として処理」することが間違っているのでしょうか? それとも「文字列として渡された浮動小数リテラルを正しく処理できない」処理系が間違っているのでしょうか?

http://gihyo.jp/dev/serial/01/php-security/0044?page=2

 私は、「(数値も含めて)すべてのリテラル文字列として処理」に対して一貫して反対してきました。たとえば下記の記事です。そのため、大垣さんの記事は私への反論なのでしょう。

 1番目のエントリで私は、MySQL文字列リテラルを数値に「暗黙の型変換」すると、結果は浮動小数点数になり、予期しない動作となる例を紹介しています。厳密に言うと、この動作と、大垣さんの指摘された「SQL文を作成する場合にリテラルパラメータ)を文字列としてエスケープすると浮動小数点型のデータが正しく処理されないデータベースがあります」は、内容は異なります。私の主張は「浮動小数点数でないはずの数値まで浮動小数点数として扱われる」ことが問題だとしているからです。しかし、今は、細かい表現上の違いは気にしないことにしましょう。

 以下、大垣さんの主張の要点である「(数値も含めて)すべてのリテラル文字列として処理」することの是非について、「何が正しいのか?」という視点から検討します。

議論の前提:数値を文字列リテラルとして扱うと「暗黙の型変換」が問題に

 大垣さんの主張、すなわち「(数値も含めて)すべてのリテラル文字列として処理」すると、必然的に「暗黙の型変換」が出てきます。以下のSQL文を用いて説明します。

SELECT * FROM employee WHERE age = '30'

この例では、年齢を示す30を文字列リテラルとして与えています。数値列ageとの比較において、文字列'30'は「暗黙に」数値 30 に変換されることを期待したSQLです。私は、この「暗黙の型変換」が問題だと考えます。

正しいことの判断基準は何か

 ここで、「何が正しいのか」を検討するにあたり、「正しいとは何か」ということを考えてみたいと思います。正しいか、正しくないかを論じるためには、判断基準が必要です。

 現在議論しているのは、「SQL文を作成する場合」の話ですから、大前提として作成されたSQL文が正しくなければならないはずです。それでは、SQL文が正しいとはどういう状態でしょうか。

 これも色々な条件があるはずですが、正しいSQL文の基本条件の一つとして、SQL規格や実際に使うSQL処理系の文法に従っていることが必要と考えます。たとえば、PostgreSQLを使う場合は、以下が必要です。

  • 原則としてISO/JISの規格に従ったSQL文であること
  • その上で、使用するSQL処理系(この場合はPostgreSQL)の方言や制限にあわせるための調整をしていること

 この基準に従い、暗黙の型変換を伴うSQL文の「正しさ」について検討しましょう。

ISO/JIS規格のSQLでは、文字列から数値への暗黙の型変換は定義されていない

 ISO/JIS規格のSQLでは、文字列から数値への「暗黙の型変換」はどのように規定されているでしょうか。

 実は「規定されていない」が正解です。それをISO SQLのドキュメントから追ってみましょう。

 ISOSQL規格には、SQL製品の規格準拠度を調べるためのチェックリストがあります。Annex F「SQL feature and package taxonomy」がそれです。PostgreSQLOracleなどSQL製品は、このリストへの準拠をチェックリストの形で公開しています。まず、以下は、Annex FのE011-06「数値データ型間の暗黙の型キャスト」の引用です。

f:id:ockeghem:20111203003357p:image

 ISOの標準をお持ちの方は少ないと思いますが、幸いなことに、Annex Fは各SQL製品のリファレンスマニュアルに引用されています。以下に、PostgreSQL9.1の該当箇所を紹介します。

http://www.postgresql.jp/document/9.1/html/features-sql-standard.html

これを読むと、暗黙の型変換については以下の記述が見つかります。

  • E011-06 コア 数値データ型間の暗黙キャスト
  • E021-10 コア 文字列型間の暗黙的キャスト

 数値型同士、文字列型同士の「暗黙の型変換」については、ISO規格の要求があることが分かります。しかし、文字列型から数値データへの暗黙の型変換については、記載がありません。このことから、ISO SQLでは、文字列から数値への暗黙の型変換は規定されていないと考えられます。

製品の実装はどうか

 現実には多くのSQL製品で、文字列から数値への「暗黙の型変換」は実装されています。しかし、規格にない動作をどのような仕様で実装しているのでしょうか。私の調べた範囲では、以下の実装があります。

  • 文字列から数値への「暗黙の型変換」は許可せず、エラーにする(DB2 9.5まで)
  • 文字列から数値への「暗黙の型変換」の結果は浮動小数点数になる(MySQL)
  • 文字列から数値への「暗黙の型変換」は比較相手の型を見て「良きに計らう」(Oracle等)

 詳しくは「[SQLインジェクション][SQL]: SQLの暗黙の型変換はワナがいっぱい - 徳丸浩の日記(2009-09-24)」を参照ください。

 このように、文字列から数値への「暗黙の型変換」は、多くの処理系で規格への拡張機能として提供されていますが、その仕様はバラバラです。規格に規定されていない機能を実装したことによる当然の結果と言えます。

「何が正しいのか」を考えるには基準が必要

 このように、文字列から数値への暗黙の型変換は規格による規定がないために、実装により仕様がまちまちです。極端な場合、同一製品でもバージョンにより挙動が変わる場合があります。DB2は前述のようにVer9.5までは文字列から数値への暗黙の型変換をエラーにしていましたが、Ver9.7にて、Oracleに近い仕様になりました。おそらくIBMは、SQLの本家としてのプライドを捨て、SQLの王者であるOracleの仕様にすりよったのでしょう。国際標準に規定されていないと言うことは、そのような大胆な仕様変更もあり得るということです。

 このように「暗黙の型変換」は規格化されていないことにより仕様が非常に不安定です。ある場合はエラーとなり、ある場合は浮動小数点数になるが故に不可解な動作をします。こういう不安定なものを選択することが、果たして「何が正しいのか」を考えた結果でしょうか。

 私はそうは考えません。正しい処理方法を考える上では、守るべき基準として、ISO/JIS/ANSI/ECMAの規格、RFCなどがあり、その上でプログラミング上の良い習慣などに従うべきだと考えます。

 このような根拠から、私は、「(数値も含めて)すべてのリテラル文字列として処理」することは間違いだと考えます。たまたま特定の処理系(例えばPostgreSQL)でうまく動くからと言って、普遍的な真理であるかのように説明することはおかしい。『「何が正しいのか?」常に考えるようにしてください』という言葉は、そっくりそのまま大垣さんにお返しします。

参考

[PR]

安全なWebアプリケーションの作り方DRMフリーのPDFによる電子版もあります。

masa141421356masa141421356 2011/12/03 09:44 いつも疑問なのは、なぜ明示的な型変換関数を使うという選択肢を考えないで話を進めようとするのかというところですね。

トラックバック - http://d.hatena.ne.jp/ockeghem/20111203

2011-11-14

11月24日(木)トレンドマイクロ&KCCS共催セミナーで講演します 11月24日(木)トレンドマイクロ&KCCS共催セミナーで講演しますを含むブックマーク

トレンドマイクロとKCCSが共催するセミナーで基調講演することになりました。テーマはインターネットからのサーバー(主にWebサイト)を如何に防御するかについてですが、海外に関連会社を多数持つ企業のWebサイトガバナンスの事例についても触れます。といっても、特殊な話ではなくて、どの企業・団体でも考えなければならない内容だと思います。

来週の開催ですが、まだお席があるようですので、興味のある方はお申し込みください。


日時:2011年11月24日(木) 14:30〜17:00(受付開始 14:00)
場所:トレンドマイクロセミナールーム 新宿マインズタワー12F
費用:無料


プログラム詳細、お申し込みはこちら https://trendmicro-partner.jp/partnerseminar/cyberattack/

2011-11-09

SQLインジェクション対策」でGoogle検索して上位15記事を検証した 「SQLインジェクション対策」でGoogle検索して上位15記事を検証したを含むブックマーク

このエントリでは、ネット上で「SQLインジェクション対策」でGoogle検索した結果の上位15エントリを検証した結果を報告します。

SQLインジェクション脆弱性の対策は、既に「安全なSQLの呼び出し方」にファイナルアンサー(後述)を示していますが、まだこの文書を知らない人が多いだろうことと、やや上級者向けの文書であることから、まだ十分に実践されてはいないと思います。

この状況で、セキュリティのことをよく知らない人がSQLインジェクション対策しようとした場合の行動を予測してみると、かなりの割合の人がGoogle等で検索して対処方法を調べると思われます。そこで、以下のURLSQLインジェクション対策方法を検索した結果の上位のエントリを検証してみようと思い立ちました。

どこまで調べるかですが、以前NHKスペシャル“グーグル革命”の衝撃が放送された際に話題になった印象的な言葉「グーグル検索で…上位15位に入らなければこの世に存在しないのと同じです」にならい、少し多いですが「この世に存在する」上位15位までを調べてみました。

検索順位は変動するものなので、11月5日の朝に調べた結果のスクリーンショットevernoteの公開ページに保存しておきました。

それでは始めます。

1位: Security&Trust ウォッチ(42):今夜分かるSQLインジェクション対策 - @IT

また上野宣か」の名文句が生まれるきっかけになった有名な記事です。この記事への問題意識がきっかけとなって、安全なSQLの呼び出し方が生まれたという説もあります。このあたりの経緯については、上野宣氏が高木浩光氏にインタビューした「 Security&Trust ウォッチ(60):今夜こそわかる安全なSQLの呼び出し方 〜 高木浩光氏に聞いてみた - @IT」をご覧下さい。

さて、この記事ではWebアプリケーション側のSQLインジェクション対策として以下の記述があります。

http://www.atmarkit.co.jp/fsecurity/column/ueno/42.html

本当に箇条書きだけなんですね。これらの優先順位もなければ、andなのかorなのかも分からないので、高木浩光氏に「駄目な技術文書の見分け方」と書かれたのも仕方ない気もします。上野氏は友人なので叩かれ方が気の毒な気がしますが、これはライターとして気をつけなければ、という教訓にしたいと思います。


2位:SQL インジェクション攻撃とその対策

マイクロソフト社のtechnetの文書の1つですね。マイクロソフトの技術文書は非常に充実しているのですが、この文書はイマイチです。「攻撃とその対策」と題されている割には、対策については以下の記述があるだけです。

"SQL インジェクション攻撃" の対策方法には、お客様が開発・導入した Web アプリケーション、またはデータベース上のストアドプロシージャ等を改修し、意図しない SQL 文を受け入れないようにする必要があります。

http://technet.microsoft.com/ja-jp/library/dd362952.aspx

間違ってはないですが、「意図しない SQL 文を受け入れないようにする」ために何をすべきかは書いておらず、別のドキュメントにリンクされているだけです。

それでも、気を取り直して、リンク先の文書を読みましたがあまり良くありません。

Microsoft Security Advisory 954462

この文書の対策編は、ツールの紹介になっていますが、その筆頭に紹介されているHP Scrawlrが403エラーで参照できなくなっています(一種のリンク切れ)。

リンク切れはさておくとしても、SQLインジェクション対策としては、まずは正しいアプリケーションの書き方が先に来るべきと考えます。

第 2 回 SQL インジェクション その攻撃と対処

NECラーニングの講習会資料のようです。対策としては以下が書かれているのですが。

1.パラメータクエリまたはストアド プロシージャを使用

2.特殊文字のエスケープ処理

ただし、すべての特殊文字をエスケープすることは困難

パラメータクエリ」というのはプレースホルダのことですが、日本ではあまり普及していないいい方ですね。また「ストアド プロシージャを使用」というのは誤りです。ストアドプロシージャの呼び出し方が間違っていると、SQLインジェクション脆弱性になる場合があるからです。ひょっとすると、「パラメータ化…ストアドプロシージャ」と言いたかった可能性はあります。Parameterized stored procedureという英語表記はあるからです。しかし、この読み方は「ウルトラC」という感じですので、たとえそうだとしても日本語としてよくありません。

また、特殊文字のエスケープについて「すべての特殊文字をエスケープすることは困難」と書いてあるのは意味不明ですね。これについては、11位のところで言及します。


SQL インジェクション

この文書は、対策について量的に詳しく書かれていますが内容がよくありません。

書いてあることは基本的に入力値検証なのですが、入力値の検証ではSQLインジェクションの対策にはなりません。

また、「可能であれば、次の文字を含む入力は受け入れないでください。」とありますが、シングルクォート以外は対策として無意味です。詳しくは、このエントリを参照下さい。

; ' -- /* ... */ xp_

リンク先はまだあるのですが、もうよいでしょう。読者はリンク先を読んでいるうちに混乱して、訳が分からなくなりそうです。

この文書の問題点については、このエントリに先立ち日本マイクロソフトの高橋正和氏に連絡したところ、改善を検討して下さるとのことです。加えて、「それはそれとして、公開しているものは、公開している責任があるので、ズバッと行ってください!(そういうものだと思います)」というお言葉をいただきました。高橋さんのお人柄がにじみ出ていますね。ということで、改善についてはしばらく待ちたいと思います。


3位:SQLインジェクションの対策 | Think IT(シンクイット)

この記事は以前、「SQLのバインド機構は「エスケープ処理された値」をはめ込むのか - ockeghem(徳丸浩)の日記」や「続:SQLのバインド機構は「エスケープ処理された値」をはめ込むのか - ockeghem(徳丸浩)の日記」で批判しました。詳しくはそちらをお読みいただくとして、要は、元々「バインド値はエスケープ処理した後にプレースホルダにはめ込む」となっていた表現がおかしいと思って調べたら、安全なウェブサイトの作り方 改訂第3版の「バインド値はエスケープ処理されてプレースホルダにはめ込まれる」という表現を(ほぼ)丸写ししたものと判明したものです。その後、私の批判記事の一部を拾って「SQL文のひな型とバインド値は個別にデータベースに送られ、構文解析される」と修正されました。

「安全なウェブサイトの作り方」の方は、その後改訂第5版で以下のように改訂されています。少し長くなりますが、該当の項を引用します。

 SQLには通常、プレースホルダを用いてSQL文を組み立てる仕組みがあります。SQL文の雛形の中に変数の場所を示す記号(プレースホルダ)を置いて、後に、そこに実際の値を機械的な処理で割り当てるものです。ウェブアプリケーションで直接、文字列連結処理によってSQL文を組み立てる方法に比べて、プレースホルダでは、機械的な処理でSQL文が組み立てられるので、SQLインジェクション脆弱性を解消できます。

 プレースホルダに実際の値を割り当てる処理をバインドと呼びます。バインドの方式には、プレースホルダのままSQL文をコンパイルしておき、データベースエンジン側で値を割り当てる方式(静的プレースホルダ)と、アプリケーション側のデータベース接続ライブラリ内で値をエスケープ処理してプレースホルダにはめ込む方式(動的プレースホルダ)があります。静的プレースホルダは、SQLISO/JIS規格では、準備された文(Prepared Statement)と呼ばれます。

 どちらを用いてもSQLインジェクション脆弱性を解消できますが、原理的にSQLインジェクション脆弱性の可能性がなくなるという点で、静的プレースホルダの方が優ります。詳しくは本書別冊の「安全なSQLの呼び出し方」のプレースホルダの項(3.2節)を参照してください。

ということで、妙なコピペのドキュメントではなくて、「安全なSQLの呼び出し方」を参照して下さい。

4位:no title

NRIセキュアテクノロジーの矢野さんの記事です。8ページにわたる長い記事ですが、対策は6ページに書かれています。このページの表1に対策が列記されています。しかし、この表1には、9項目も列挙されているので、どれが本質的な解決策で、どれが保険的な対策なのかが分かりにくいですね。答えを書くと、2番目の「バインド・メカニズムの利用」が本質的な解決策、それ以外はすべて保険的対策です。そうはっきり書いてくれればよいのに、はっきりとは書いていないのです。

また、対策が9項目もあるのに、それだけではまだ足りないようで、以下の記述もあります。

表1で挙げただけでなく、さらにWebシステム全般のセキュリティ・レベルを上げたいのであれば、WAF(Web Application Firewall)の導入も検討すべきであろう。

が、対策する側の立場に立つと、ゴージャスな対策に過ぎ、「とてもこんなにはできない」と思ってしまいそうです。著者もそう感じたのか、7ページにはコラムとして「しかし、現実の問題として、ここに記載している対策をすべて実施しようとすると、かなり大変である。」とも書いてあります。

全体としては面白いコラムですが、対策に関しては焦点が定まっていない印象を受けます。


5位:SQLインジェクション対策について

IPAプレゼンテーション資料です。「安全なウェブサイトの作り方」を元にしているので大きな問題はありませんが、バインド機構のことを「エスケープの一種」と説明しているのが気になります。しかし、これは3位のところで説明したように、「安全なウェブサイトの作り方」が元々そういう説明になっていたことに由来しています。


6位:SQLインジェクション - Wikipedia

Wikipediaの解説です。間違ったことは書いていませんが、辞書的な記述で特に分かりやすいわけでもありません。これを参考にSQLインジェクション対策する人はあまりいないと思うのでこれくらいにとどめます。


7位:第42回 PostgreSQL 9.0に見るSQLインジェクション対策:なぜPHPアプリにセキュリティホールが多いのか?|gihyo.jp … 技術評論社

大垣さんの記事です。ブックマークコメントも参照ください。

この記事で、大垣さんは「SQLインジェクション対策の4原則」として以下を提示されています。

1. すべてのパラメータ文字列としてエスケープする

2. すべてのパラメータをプリペアードクエリパラメータとして処理する

3. 文字エンコーディングの設定をAPIで行う

4. パラメータとして処理できない文字列はバリデーションを行う

原則1と原則2は重複して適用する必要はありません。どちらかを行います。

このうち、原則1(数値も文字列として扱う)には異論があります。詳しくは「数値項目に対するSQLインジェクション対策のまとめ」および「SQLの暗黙の型変換はワナがいっぱい」を参照下さい。

大垣さんは、「プリペアードクエリの功罪」という節の中で、「多くの開発者はプリペアードクエリさえ利用していれば大丈夫であるとしてエスケープ処理を軽んじてきました」と指摘しています。この文脈でのエスケープ処理とは、列名のエスケープを指しているようですが、それはともかく、確かに、プリペアードクエリプレースホルダ)さえ使えばSQLインジェクションは発生しないと言い切ってしまうと、誤解を招く可能性があります。

誤解されないためには、以下のように言わなければなりません。

  • SQL文を動的に(文字列連結などで)組み立てない

SQL文を動的に組み立てないとすると、パラメータを渡す際にはプレースホルダを使うしかありません。そして、SQL文を動的に組み立てなければ、SQLインジェクション脆弱性の余地はありません。

 単にプレースホルダを使うというだけでは、例えば以下のようなケースが問題になります。

$sql = "select * from $table where id=?";

この例は、テーブル名を外部から指定できるという想定ですが、$table = 'mytable; drop table mytable --'; などとすることで、任意のSQL文を追加できる場合があります。MS SQL ServerPostgreSQLの場合に、攻撃が成功する可能性が高くなります。

SQL文を動的に組み立てようとする場合、前提条件により対処が変わります。

Webアプリケーションの初心者が書いてしまった場合

Webアプリケーションの初心者の場合、そもそもテーブル名を外部から指定できる仕様を見直すべきでしょう。例えば、組み立て後のSQL文が何種類かに限定できる場合、固定のSQL文を切り替えて使うなどの対処が考えられます。

アプリケーションフレームワーク等を作成している場合

この場合、テーブル名を指定したい動機はあり得ますが、その場合でも任意テーブル名を指定できる必要はないはずで、安全にテーブル名を指定する仕組みを考える必要があります。

phpMyAdminのようなデータベース管理ツールを作成している場合

phpMyAdminのようなツールを開発している場合、元々任意のSQL文を利用者が実行できるわけで、その場合はSQLインジェクションによる「攻撃」のシナリオを考慮する必要はありません。しかし、ツールが生成したSQL文にエラーがないことは必須条件なので、テーブル名等に記号などを許容している場合は、SQLの文法に従ってテーブル名をエスケープする必要があります。

ということで、アプリケーションプログラマの従うべき原則としては、「SQL文を動的に(文字列連結などで)組み立てない」に従うことをお勧めします。O/Rマッパーやアプリケーションフレームワークを開発するような人は上級者だと思うので、自己責任SQL文を安全に組み立てる方法を考えてくださいw


8位:漢(オトコ)のコンピュータ道: SQLインジェクションとは何か?その正体とクラッキング対策。

奥野さんのブログ記事です。MySQLエキスパートですね。対策としては以下のように書かれています。

SQLインジェクションの最も確実で根本的な対策は、プリペアードステートメントを利用することである。問題は、SQLを組み立てる過程にあるので、動的にSQLを組み立てなければ原理的にはSQLインジェクションは発生しない。Webのフォームから受け取った値は、パラメータとしてプリペアードステートメントに渡せばいいわけである。ただし、プリペアードステートメント自身を動的に組み立ててしまうと元の木阿弥なので注意しよう!

完璧ですね。付け加えることはありません。


9位:IPAがまとめたSQLインジェクション対策マニュアル

「安全なSQLの呼び出し方」を紹介してくださっているブログ記事です。ありがとうございます。付け加えることはありません。


10位:SQLエスケープにおける「¥」の取り扱い

私のブログ記事です。「SQLのエスケープ再考」の続編なのですが、SEO上は続編の方が上位に出ています。

どうも、これらの記事が高木浩光さんの目にとまって2008年のWASForumでの講演依頼をいただいたようです。高木浩光さんの日記には以下のように書かれています。

SQLインジェクション対策については、HASHコンサルティングの徳丸さんにお願いしました。今やSQLインジェクションの対策方法は広く理解されているはずのようにも思えますが、どうもそうでもないようです。いまだに「サニタイズ」的な対策を挙げる検査業者、コンサル業者がいるようで、しばしば、そういった業者がはてなブックマークで血祭りにあげられている事例も散見されるところです。blogで「SQLのエスケープ再考」といったエントリを書かれている徳丸さんに、このあたりのことについて結論を出していただきます

http://takagi-hiromitsu.jp/diary/20080620.html

これを読んだ私のプレッシャーを察していただけるでしょうか。

但し、このWASForumの場では結論までは出ず、その後私自身がIPAに召還されて、高木さんやIPAのスタッフとともに「安全なSQLの呼び出し方」を執筆して、ファイナルアンサーに至りました。


11位:今週のSecurity Check - 被害が続くSQLインジェクション攻撃,もう一度対策を見直そう:ITpro

ITpro日本IBMの菅野さんが書かれた寄稿記事です。2008年春というと、MS SQL Serverを狙ったSQLインジェクション攻撃が頻繁に発生していた時期にあたります。記事の前半は攻撃手法に関する説明で興味深く価値の高い内容だと思いますが、問題は後半の対策手法です。

「最も重要なのはWebアプリケーションでの対策」という見出しはとても正しいのですが、その次の見出し「不審な入力値は無効な文字列に変換」を見るに、身構えてしまいますね。そして、予想通り、いや、予想をはるかに上回る内容が続きます。

今回の攻撃では,WebアプリケーションにPOSTされる文字列の中にDECLARE文やEXEC関数が含まれていた。このような本来入力値として渡される可能性がない入力値や文字列を厳格にチェックし,無効化すれば脅威は回避できる。

http://itpro.nikkeibp.co.jp/article/COLUMN/20080514/301660/?P=2

DECLARE文やEXEC関数が「本来入力値として渡される可能性がない入力値」なんて軽々しく言って欲しくないですね。それに、DECLAREやEXECなどのキーワードによるブラックリスト検査は、攻撃者により回避されやすいという問題があります。この種の検査はWAFに任せておけばよく、アプリケーション側では本質的な対策に専念すればよいでしょう。

次には以下の表があります。

【入力の例】
DECLARE%20@S%20NVARCHAR(4000);SET%20@S=hogehoge EXEC(@S);

  ↓          ・特殊文字を文字として扱うために「\」を挿入  / 「;」は削除

【入力値チェックの結果】
DECLARE\%20@S\%20NVARCHAR\(4000\)SET\%20@S\=hogehoge EXEC\(@S\)

ここでの指摘は以下の通りです。

ということで、この記事の著者はSQLもWebアプリケーションもまったく分かっていないようです。このような記事を参考にしてはいけません。


12位:ページが見つかりません | Let's Postgres

第四企画の坂井さんがLet's Postgresの記事として寄稿されたものです。

この記事は素晴らしい。PostgreSQLをエスケープ手法によりSQLインジェクション対策する際の技術的な注意点が正確きわまりなく書かれています。細部に至るまで、この内容に同意します。PostgreSQLを深く知りたい方すべてにお勧めです。また、MySQL界隈の方はぜひ、MySQL向けのこのように優れた文書がないことに切歯扼腕して、MySQL向けの優れた解説を書いてください。私が知らないだけであれば教えてください。

しかしながら、この記事の冒頭に「プレースホルダを用いてより効果的な対策を行うケースに関してはプレースホルダ編を参照してください」とあるように、対策の本命はプレースホルダを使ったものです。というわけで、実用的にはこの記事の姉妹編である「PHPでのSQLインジェクション対策 - プレースホルダ編 | Let's Postgres」を参照してください。こちらも素晴らしい内容です。


13位:MySQLとPHPにおけるSQLインジェクション対策について

表題通りの内容ですが、記事中に「今回は基本的な方法のご紹介でしたが、これらを施すだけでもSQLインジェクションに関する脆弱性はかなり軽減することと思われます」と控えめなコメントがあるのが、必ずしも謙遜ではないと思われます。不正確な内容なので、読まない方がよいでしょう。


14位:無料で使えるSQLインジェクション対策スキャナ トップ15*ホームページを作る人のネタ帳

SQLインジェクション対策スキャナの海外の紹介記事を翻訳(トップ15のうち上位4つのみ)した記事ですが、2007年という少し古い記事であること、元記事は既に削除されて読めないこと、紹介者自身も試していないと思われることなどから、読まなくて良い記事だと思います。


15位:SQLインジェクションを考える

Webサイト側ではなく、サイト利用者の側でのSQLインジェクション対策について検討した記事です。

面白い着眼点ですが、結論としては、マルウェア感染の脅威については最新のパッチ適用ウイルス対策ソフトの導入、個人情報漏洩については決定打はないということで、特別目新しい内容はありません。

結局どうすればよいか

冒頭に記した通り、SQLインジェクション対策には既にファイナルアンサーがあります。それは「安全なSQLの呼び出し方」に書いた内容ですが、まとめると以下の通りです。

この2つを守っている限り、アプリケーションSQL呼び出しライブラリなどにバグがあっても、原理的にSQLインジェクション脆弱性は発生しません。

もしもSQLを動的に組み立てている場合、アプリケーションバグがあると、SQLインジェクション脆弱性になります。

静的プレースホルダではなく動的プレースホルダを使っている場合、SQL呼び出しライブラリバグがあると、SQLインジェクション脆弱性が生じる場合があります。具体手例としては、 JavaとMySQLの組み合わせでUnicodeのU+00A5を用いたSQLインジェクションの可能性 - 徳丸浩の日記(2008-12-22) ぼくがPDOを採用しなかったわけ(Shift_JISによるSQLインジェクション) - 徳丸浩の日記(2010-07-01)を参考にして下さい。この2例は既にライブラリ側で改修済みです。安全なSQLの呼び出し方でも説明しています。


まとめ

SQLインジェクション対策」でGoogle検索した上位15件の内容を検証しました。

ここまで説明したように、上位15件の中には、SQLインジェクションの対策手法を説明した上質の文書はあまりありません。12位の「ページが見つかりません | Let's Postgres」はとても良い解説ですが、初心者には少し難しいと思います。

初心向けの解説としては、VOYAGE GROUP須藤さんの素晴らしいブログ記事「Webアプリケーションとかの入門本みたいのを書く人への心からのお願い。」がおすすめです。現役バリバリのWebエンジニアがこれを書いたところに圧倒的な説得力があります。この記事は、次のように始まります。


SQLインジェクションについて書くときに以下のメッセージを必ず含めて欲しいです。

http://d.hatena.ne.jp/ajiyoshi/20100409/1270809525

素晴らしい。以上の引用をもって、本エントリ全体のまとめに代えたいと思います。


[PR]

安全なWebアプリケーションの作り方DRMフリーのPDFによる電子版もあります。

defiantdefiant 2011/11/10 15:14 こんにちわ.単なる脱字の指摘ですが,7位の所のサブセクションのタイトルで「Webアプリケーションの初心が書いてしまった場合」となっていますが「Webアプリケーションの初心者が書いてしまった場合」ですかねー.

ockeghemockeghem 2011/11/10 16:00 指摘ありがとうございます。修正しました

えむけいえむけい 2011/11/25 12:49 > SQLを動的に組み立てない
ユーザーの入力に応じて動的に個数が増減するような複数のIDをキーにテーブルを検索する場合(たとえば商品一覧からユーザーがチェックした商品についてのみ詳細情報を表示するとか)、"WHERE ITEM_ID IN (?,?,...,?)" のように ? の個数が増減するようなSQLを動的に組み立てて、プリペアードステートメントのパラメータの個数もそれに応じて増減させていたのですが、このような書き方はしてはいけないということですか? いけないとしたらどのように書くのが望ましいですか?
とりあえず「安全なSQLの呼び出し方」には書かれていないようでした。徳丸本を読めば書かれていますか?

ockeghemockeghem 2011/11/25 15:40 えむけいさん。いつもありがとうございます。
SQLそのものを条件にあわせて変更しなければならないケースは確かにありますね。「SQLを動的に組み立てない」というのは、初心者向けの原則であって、実際にはそうしなければならない状況は出てくると思います。ご指摘のように、安全なSQL…にはその記述はなく、徳丸本には記述があります。えむけいさんの指摘されているような方法ですので、新しい方法ということにはならないと思いますが。

2011-10-28

「徳丸本ができるまで」スライドを公開します 「徳丸本ができるまで」スライドを公開しますを含むブックマーク

まっちゃ445などで発表に使用した「徳丸本ができるまで」のスライドを公開します。
発表時の原稿の後半を少しカットして、最新の状況を加筆しました。


[PR]
体系的に学ぶ 安全なWebアプリケーションの作り方」のDRMフリーPDFによる電子版が販売開始しました。

 |  
Google