Cookieを使ったSQLインジェクション

最近Cookieを使ったSQLインジェクションが発見されたということでその手法の詳細記事がありました。前置きが長すぎてもっと簡潔にして欲しかったのですが問題点は以下のようになります。

  • メジャーな侵入検知システムはPOST/GETの検査を行うがCookieを見逃していた。
  • スクリプト側でPOST/GET等メソッドを明示的に区別してデータ取得していない。
  • スクリプト側で入力データの検査が出来ていない。

元記事には

ここまで聞くと、「うちのサイトではクッキーにデータベースに関連するような情報は格納していないから関係ない」と、早合点する人もいるかもしれない。それは間違いなので、もう少しお付き合いいただきたい。

なんて書いてるからよくよく読んでみましたがCookie使う以前の問題で仕事でウェブプログラミングしているならその会社のスキルを疑って良いレベルです。PGのスキル不足は常にあると仮定してもレビューせずに素通りかPLが無能。PMが放置主義って言ってる様なもので会社でレベルで恥かいてるぞ。私ならこんな杜撰なコード組む会社に2度目の外注はしない。

まずコードの品質を上げる前に侵入検知システム等に頼るのは気が進まないし費用のムダ。これの方法の恐いのは侵入検知システム自体に穴がある場合だけでなく、サーバー移設等環境が変わった場合にミスが起きやすい。ニュースで「サーバーの設定ミスで情報漏えい」というケースがこれ。

次にデータ取得においてメソッドを区別していないのはCookie以前の問題でGETしか想定していないスクリプトでPOSTで渡されてもスクリプトのみでは同じ問題が起きるので注意すること。昔Perlで外部ライブラリなしでコーディングしているときは非常に面倒だと思いつつもどうやってデータがウェブサーバに送られてくるのか勉強になりました。今時よく利用されるASPやPHPはその辺の面倒な処理を自動的にやってくれて組込関数グローバル変数から読み込めますがRequest系の実装は気持ち悪くて使えない。未だにRequestについてGET/POSTを気にせずどっちでも使えるから便利とか発言するPGを見かけるが変数名が重複したときの対処方法を考えていないのが大半。セキュリティはともかくバグの元になる事を想定できていない。そういう人に限ってデバッガ未経験だったりする。

あとニュース記事には書かれていませんがPHPの場合、Requestでなくても$_POSTや$_GETのみで変数を上書きできるから注意ですね。通常リスト構造のデータを受け取るときは配列型にしたほうが便利ですが、それをせず同じ変数名で並べて送ってくるフォームがありそれにも$_POSTや$_GETは対応できないのでPerlの時のように素の入力データから抽出しています。それと同じ方法で本来の変数を上書きされても発見できない場合がありますので注意です。

最後に入力されたデータを検査していないのは論外、今回のセキュリティホールもPOST/GETを想定した変数だとしてもスクリプト側で検査していれば問題になっていない。メソッドを明示していればCookie経由で上書きしようとした変数はその場でイジェクトできるし、Request受けていてもそのデータを検査できていれば良いのである。とは言っても現実はApacheエラーログを見ずに組む人が多い、サニタイズどころかValidateやisset検査すらせずにエラーログを汚しまくる奴もいる。指摘するとErrorじゃなくてWarningだから大丈夫だろうとか言葉を理解できていない人やErrorじゃ無いんだからサーバー側でログ出力止めろよ!と逆ギレする民度の低いPGも少なからず存在する。そういうのに限ってこれまたPHPはPerlと違ってセッション実装できているから凄いとか内部処理を知らずに自慢(それもPHP作った本人じゃないのに)していたことがあって呆れたこともあります。

以上で愚痴込みのまとめは終わりますが、元記事を見てハッと気付いた脅威が一つありました。
最低限の作業として送られてくるデータは特定して検査するように書いているつもりですが、セッション変数はサーバーに保存されているデータなのでそこまでは強制的に検査していませんでした。(ヒマがあればするけれど他人にまで強制していない)

これの何が原因かというと、一度送られたフォームデータ(特にショッピングカート等)は途中ページでの改ざんを防ぐ為にセッション変数として保持することがありますが、保存したセッション変数からデータを再取得するときに検査をしていない場合がありました。近年はCookieに値セットして使うことが無いので完全な見逃しですが、Cookieを改ざんされた時に$_SESSIONが自動的に汚染されないか確認したことが無かった・・・。これは週明け直ぐにでもチェックしてみます。

他にDBとの入出力に対しての検査も、最初はそこまでする必要あるのかな?と思っていましたが仕事で使う内に必須だと思うようになりました。セキュリティ的には外部と接触する部分で一斉検査すれば大体良いのですが、開発途中でDBのデータがいい加減に入力されているとか仕様外の構成になっていたりするとが多く、というかほぼ100%でデバッグの障害になってたりもします。これでPGとDBエンジニアが鶏が先か卵が先かみたいなケンカもします。そこでスクリプト側としてはDBとの入出力にも開発効率を上げるために検査を入れておいたほうが良いと思います。あとApache管理者の意見として、大量のUndefined indexでログを汚すなというのもあります。

またまた進化したSQLインジェクションの脅威 クッキーを悪用 セキュリティー-最新ニュース:IT-PLUS
http://it.nikkei.co.jp/security/news/index.aspx?n=MMIT2g000028102008&cp=1

ApacheModuleの作り方

C言語のCGIは速いと思っていましたが実は遅かったんですね。Servletみたいにプログラムがメモリに常駐されていればディスクアクセスが発生するCGIに勝ち目は無いのか・・・でもFastCGI組み込んだらどうなんだろ?

以下の記事はCGIをC言語で作るというより、Apacheモジュールの作り方に重点を置いています。Webシステムのモジュールをバイナリ形式で配布する際にとても参考になりそうです。

ApacheModuleでWebアプリケーションをつくろう:CodeZine
http://codezine.jp/a/article/aid/2502.aspx

最近PHPがフルボッコのようです

PHPが非難される流れは去年の後半あたりから把握してますが、PHP5以降は言語として特に非難される程のものもないような気がします。PHP本体のセキュリティホールとかは別ですが…。ただPHPプログラマーが訳も分からないまま叩かれているような気がしてちょっとかわいそう。

私も何故かここ3年程仕事で一番多く使った言語がダントツPHPで次がC++そしてPerlといった感じ。PHPが選ばれたのはクライアントや上流の決定による物ですが、理由は単純明快で「書くコード量が少なく開発効率が良いから」「誰にでも割り振れてアサインが楽だから」ということです。当然工数も費用も削減できて良いように思えますが正直コンピュータの動作や通信については理解の妨げになっているので学習者や初心者にはオススメしたくない言語です。あとVBでリストラになってPHP再チャレンジの人も同様です。

簡単であることと基礎的なものは別次元の内容なので学習の際にはこの部分を混同して欲しくない。PHP言語はウェブプログラミングする際に便利な組み込み関数や定義が容易されていて初心者でもすぐにある程度ちゃんとしたものが作れてしまう。だがそこにウェブプログラミングとしての基礎を学ぶことが出来ない。GETやPOSTをPHP言語上でどのように取得するか覚えても、HTTPプロトコル上でどのような形式で送信されていてプログラム内で切り抜き処理をしているかなんてPHPだけでは想像もつかないだろう。PerlやC言語であればそのへんも全部自分で考えて処理しなければならないので勉強になる。

数学に例えれば微分の公式覚えて、微分が出来るようになったけど微分の理論を全然理解してないと似ている。(というのが高校生時代の私…orz)

ゲーム制作スキルとなれば物理や数学の基礎からプログラミングの応用まで勉強すべき事があるのですが、RPGツクールやオーサリングツールだと簡単に作れてしまうみたいな。

だからPHPだけしかやってないと他の言語で同じ事を達成するにはコンピュータ理論や通信の基礎的な学習が必要だし、プログラミングに対しての理解の深さに差が出てきます。仕事で初めてプログラミングに触れてそれがPHPだった言う人も最近は多いのでこの機会にぜひPerlや他の言語にも挑戦してみてください。

最近は確かに学生時代までに趣味または専門授業でコンピュータ理論を勉強したことがなくこの業界にプログラマーとして就職している人も増えてきたので非難する前に勉強するチャンスをあげたほうが良いなと思いました。