[PHP-dev 1482] Re: mb_ereg_replace

Moriyoshi Koizumi mozo @ mozo.jp
2009年 5月 16日 (土) 05:06:19 JST


小泉です。

この件だいぶ前に知っていたのですが。

そうですね、論点としては

1. 脆弱性と見なせるかどうか。
2. 現在の仕様のまま、これを実践的に、安全に利用することが可能かかどうか。
3. もし仕様を変更するとして、変更後の仕様が下位互換性を満たせるかどうか。
4. 下位互換性が満たせないとして、どのような代替案があるか。

があると思います。

1. については、本来的には仕様であると言えるので、厳密な意味では脆弱ではないと考えます。そもそも、preg_replace() にも同様の問題があります。

<?php var_dump(preg_replace("/.*/e", "\\0", "`sh`")); ?>

mbregex でだけこの問題を取り上げることは正しいことなのでしょうか?

2. について、ユーザが、正規表現の置換文字列を PHP
のスクリプトを評価した結果としたいという状況下では、そのスクリプトのパラメータに置換対象文字列を指定することはごく自然です。安全に実践的に利用しようとすると、例えば特定文字列を乱数に置き換える、といった限定された問題領域にしか適用できなくなります。

また、eオプション自体は Perl の正規表現演算子が発祥であると考えられますが、Perl
ではバックリファレンスを変数で表すので、プレイスホルダによって発生するような脆弱性はありません。ユーザが類推によって、この動作の違いに気づかずに当該機能を利用してしまう可能性は低くありません。

3. について、e オプションが有効なときに、バックリファレンスを一時的に変数に格納し、バックリファレンスを表す文字列を変数を表す文字列に適宜置換してから
eval するという実装が考えられます。しかし、これでは次のような呼び出しを行うスクリプトの動作が変わってしまいます。

mb_ereg_replace(".*", "'***\\0***'", '$a', 'e');

したがって、4. を考えるわけですが、3. の挙動を指定する新しいオプション文字列 (E) を導入し、旧来の方法は deprecated
とする、などが一案として考えられます。

2009/5/15 Yasuo Ohgaki <yohgaki @ ohgaki.net>:
> 大垣です。
>
> PHP_5_2ブランチを見た限りまだ修正が入っていないようなので
> メールします。
>
> http://www.milw0rm.com/exploits/8641
>
> この件、何方か作業されていますでしょうか?
>
> バックリファレンスで関数が実行できてしまう、という脆弱性なの
> ですがSJISとかあるのでpregの様にエスケープする訳には行かない
> です。
>
> --
> Yasuo Ohgaki
> yohgaki @ ohgaki.net
> _______________________________________________
> PHP-dev mailing list
> PHP-dev @ php.gr.jp
> http://ml.php.gr.jp/mailman/listinfo/php-dev
>


PHP-dev メーリングリストの案内