php 2-2250738585072011e-308 問題

追加

この問題を修正したphp 5.3.5 / 5.2.17 がすでにリリース済みなのでそれを使えば安全だと思います。
http://www.php.net/downloads.php

changelog
http://www.php.net/ChangeLog-5.php

概要

寝ようと思ったら、phpアレゲなバグがあったというツイートで目が覚めた。

なんか、場合によってリモートからphpをハングアップさせられるバグがあった様子。
ただし、環境によっては起きたり起きなかったりする。。。


http://modxcms.com/forums/index.php/topic,59421.msg338158.html#msg338158
http://bugs.php.net/bug.php?id=53632
http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/

うちだと、x64のVMで php5.3.2でセーフ。 x86VMでphp5.3.3でアウトだった。
ハングアップすると、 php or httpd が CPU をフルに食べてしまう状態になる。


上のサイトに詳しく書いてあるけど、この問題のコードを実行すると、、、

<?php $d = 2-2250738585072011e-308 ?>

今回は、ブラウザ経由で実行したので httpd が CPU 99%で張り付いてしまった。。。


で、問題なのが、これが外部からのパラメータとしても渡されてしまうというところ。
そして、 if文などの判定ルーチンでもバグを引き当ててしまうところ。


ブラウザから、 127.0.0.1/hogehoge.php?a=2-2250738585072011e-308 とかやって、以下の php を実行すると、、

//これもアウト
<?php if ( @$_REQUEST['a']  != '' ){ echo "11"; }  ?>
//これもアウト
<?php $a = @$_REQUEST['a'] != '' ? @$_REQUEST['a'] : 0 ; ?>
//これもアウト
<?php $a =  @$_REQUEST['a'] ; //代入までならセーフ。
      $a = $a + 1;            //演算はアウト。
?>


面白いことに、 int にキャストするとOK。

//セーフ
<?php if ( ((int)@$_REQUEST['a'])  != '' ){ echo "11"; }  ?>

対策

対策の追記

すでにphp本体で対応済みのモジュールが公開されています。こちらを使うのがより安全だと思います。
http://www.php.net/downloads.php
changelog
http://www.php.net/ChangeLog-5.php

コード上での対策

ここのブログの人が書いている コードを先頭にブチ込むととりあえずOK
http://modxcms.com/forums/index.php/topic,59421.msg338158.html#msg338158

対策コード
<?php
if (strstr(str_replace('.','',serialize($_REQUEST)), '22250738585072011')) {
  header('Status: 422 Unprocessable Entity'); die();
}
?>

こいつを、コードの一番上に差し込む。

<?php
if (strstr(str_replace('.','',serialize($_REQUEST)), '22250738585072011')) { //これ
  header('Status: 422 Unprocessable Entity'); die();                         //これ
}                                                                            //これ

if ( @$_REQUEST['a']  != '' ){ echo "11"; }  
?>

ようするに、ヤバげな数字がないか、文字列として比較するって感じ。
数字として比較してしまうと、バグを引き当てて死んでしまうので、文字列でフィルタを行う。

検証環境

問題が起きた方の環境。

#cat /etc/issue
CentOS release 5.5 (Final)

# uname -a
Linux XXXXXXXXXXXXX 2.6.18-194.17.1.el5 #1 SMP Wed Sep 29 12:51:33 EDT 2010 i686 i686 i386 GNU/Linux

//phpはちょい古めですね、、すいません。。。
# php -v
PHP 5.3.3 (cli) (built: Jul 22 2010 16:41:20)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies


もうひとつの問題がおきた環境

# cat /etc/issue
CentOS release 5.4 (Final)

#uname -a
Linux XXXXXXXXXXXXX 2.6.18-194.3.1.el5.028stab069.6 #1 SMP Wed May 26 18:31:05 MSD 2010 i686 i686 i386 GNU/Linux

# php -v
PHP 5.3.3 (cli) (built: Jul 22 2010 16:41:20)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies

問題が起きなかった方の環境

#cat /etc/issue
CentOS release 5.5 (Final)

#uname -a
Linux XXXXXXXXXXXXX 2.6.18-194.el5 #1 SMP Fri Apr 2 14:58:14 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux

php -v
PHP 5.3.2 (cli) (built: Sep 24 2010 23:06:34)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies


私の検証環境は、php のバージョンの細かな違いはあるので確証は何も無い、、、
他の人の動作報告求む。


個人的には 64bit / 32bit とかそこら辺?な気もするんだけど、どうなんだろう。
コンパイラの最適化によってバグを引き当ててしまうとかいろいろあるらしいけど、、、?


32bit onlyだったら、ほとんどのシステムを64bitに移行しているので私は一安心なんだけどw、、、、
その他のサイトの人は大変だろうな、、、ご愁傷さまです。


詳しくは、こんないい加減なサイトではなく、専門家のサイトとか、自分で動作確認をしてみればいいんぢゃないのー?ってことで。
それと、間違っても、自分のところではない、人様のサーバにうっちゃダメだYO。
サーバ落として、おかねとられて、おまわりさんに怒られても知らないよ。