月: 2006年8月

Zend FrameworkのZend_Db

このブログでZend Frameworkの事はほとんど書いていませんが、セキュリティ関係のところを少しだけ書きます。

Zend Frameworkはまだまだ作りかけ、と開発元が言っているだけあって、セキュリティに関係する部分も作りかけだったりします。

例えば、mysqliアダプタは適切にエスケープ処理されていますが、Oracleアダプタのエスケープ処理は全く行われていません。DB2のアダプタの場合、”でくくられるべき所がくくられていなかったりします。

Zend Frameworkとは関係ありませんが、PostgreSQLのPDOドライバは出来が悪いので事実上PostgreSQLでZend_Dbは使えません。
# 一見使えるように見えますがメモリ管理に問題がある
# らしく、はまる可能性があります。

PHPカンファレンスで「Zend Frameworkを使っている方?」と聞かれて、手を上げたのは私の他数名だったので大丈夫とは思いますが、実際のシステムに使うにはコードをよく読んでから使わないと思わない落とし穴にはまる事になります。

秋の1.0リリースかリリース候補では修正されていると思いますが、今のところこんな感じです。

PostgreSQLのプリペアードクエリとUnitテスト

PostgreSQLのプリペアードクエリを使ったプログラムのユニットテストを書いてユニットテストの書き方の問題に気がつきました。普通にユニットテストを書くと

relation with OID ##### does not exist

というPL/PgSQLで良く見かけるエラーが発生してしまう場合があります。

通常ユニットテストを書く場合、テストのセットアップ関数(メソッド)で

create table test (a text, i int);

テスト終了時に

drop table test;

と書きます。

プリペアードクエリの場合、コンパイルされたSQL文がバックエンドにキャッシュされるので「Web環境などで永続的な接続」を行っている環境でこの様な初期化、終了ルーチンを持つユニットテストでPostgreSQLのプリペアードクエリを実行するテストを「2回以上」行うと

relation with OID ##### does not exist

とエラーが表示されてしまいます。キャッシュされた(プリペアされた)SQL文に対応するテーブルが削除されてしまった後もクエリはキャッシュされているので削除されたの存在しないテーブルアクセスしようとしているので上記のエラーがでます。
# プリペアされたクエリは名前でなくOIDでテーブルにアクセスするので
# このエラーが発生します。

コマンドラインからのユニットテストの場合、接続の種類は影響しませんがPHPでWebサーバ上でユニットテストを実行する場合、pg_prepare, pg_execute を使ったプログラムのユニットテストにはpg_connectを使うほうが良いです。pg_connectを使っていても同じ接続を使っている間にテーブルの削除/作成を行ってもpg_pconnectを使っている場合と同じ理由でこのエラーが発生します。コマンドラインでもすべてのテストを実行するスクリプトを利用している場合は注意が必要だと思います。PL/PgSQLのエラーが何故発生するのか理解していれば直ぐに原因に気が付くと思いますが、そうでなければなかなか気が付かないかもしれません。

私も最初は何の事だか解らずググってもPL/PgSQLのエラーに関連するページが表示されていました。pg_prepare/pg_executeについては少なくとも上位には表示されなかったので書いておきます。

PostgreSQLのプリペアードクエリの実装(と言うか実際にOID参照しているもの)を詳しく調べてから書いていないので「実装と違う」という場合は是非指摘してください。

# Javaのユニットテストでこの問題が発生する、というページ
# も無かったような気がします。当り前すぎ(FAQ)だから?

# 問題を回避するもう別の方法にDEALLOCATEを使ってプリペアされた
# SQL文を削除しておく方法もあります。削除するのは面倒ですがこちら
# の方法ならどのような環境でも困らないと思います。

IEEEのセキュリティサイト

A Process for Performing Security Code Reviewsのような記事が公開されています。The State of Web Security等は何かプレゼンテーションを作る場合に役立ちそうです。

基本的にはブログのようになっているようです。しかし、ここの記事は時間が経つと買わないとならない(?)ようです。画面上部の”Contents”リンクをクリックすると有料コンテンツのリストが表示されます。Process for Performing Security Code Reviewsは$19だそうです。Adsenseでも何でも良いので広告を付けて無料にしてくれればありがたいのですが。# 日本語で書いていても何の効果もないでしょうけど。

リモートファイルの読み込みが可能なPHPアプリ多数

PHPには

require(‘http://example.com/script.php’);

と外部のURLからデータを読み取りローカルのスクリプトとして実行する機能があります。以下のようなスクリプトが致命的であることは以前にも書きました。

require($_REQUEST[‘type’].’.php’);

allow_url_fopen設定で読み取りの可否を変更できるようになっているのですが、ストリームのphp://inputは制限できないので、allow_url_fopenの設定に関わらずリモートスクリプトが実行できてしまう仕組みになっています。(「php://inputによりPHPスクリプトインジェクションが可能になる」とした方がより正しいですね)

最近、この不正なリモートスクリプトの読み取り・実行が行える脆弱性を調べている方がいるらしくCVEに何十ものリモートスクリプト実行脆弱性のエントリが作られています。見かけた事があるアプリケーション名にはmanbo、horde等があります。当たり前ですが利用中しているアプリのリリース情報はこまめに調べないと危ないです。

# しかし、こんなにたくさんリモートファイル実行
# に脆弱なアプリが在るとは….
# shopなんとかとか、cartなんとか、と明らか(?)に
# EC系のアプリにも問題が多く在るようです….

とは言っても

Successful exploitation requires that “register_globals” is enabled.

となっている物も多いようです。共有サーバなどではregister_globals=onのサイトもまだまだ多いでのしょう。スクリプトを公開する場合、

if (ini_get('register_globals')) {
  die('Turn off register_globals for security reasons');
} 

などを必ず入れておいた方が良いようです。

やはり難しいのかも?!

タイトルどおり「書かない日記」なっているので久しぶりに書きます。

先日のPHPカンファレンスで私のセッションを聞かれた方は「一応、問題はレポートしてあります」と話していた件、と言えば覚えていらっしゃると思います。この件、返信メールが来ていました。他のシングルバイト圏の方と話したときと同じかなと思いました。「これって問題なの?」と言う内容のメールでした。とりあえず「コミットしておいてください」と返信しておきましたがどうなることやら… 日本の開発者でも最初は「??」と思われる方も多いので仕方無いのでしょう。 

PHPカンファレンスの私のセッションのプレゼンテーションファイルをご希望の方、メールをください。このプレゼンテーションファイルは個人的に使うか出所が分からないように一部のみ使って頂けるようお願いします。