IIJ-SECT

IIJ

 

Security Diary

HOME > Security Diary > CVE-2012-1823 CVE-2012-2311 PHPのCGIモードにおける脆弱性について

CVE-2012-1823 CVE-2012-2311 PHPのCGIモードにおける脆弱性について

この脆弱性は2012年5月3日にリリースされたPHPバージョン5.3.12と5.4.2において 明らかになりました。CGIモードにて動作させている場合のみ影響を受けますが、 対象となる環境ではリモートからソースコード漏洩、任意コード実行を引き起こす攻撃が可能です。

以下のサイトに脆弱性の発見者による解説が公開されています。
Eindbazen PHP-CGI advisory (CVE-2012-1823)

該当するPHPのリリースノートは以下です。
PHP 5.3.12 and PHP 5.4.2 Released!
PHP 5.4.3 and PHP 5.3.13 Released!

既に攻撃も観測されているようです。
PHP-CGI Vulnerability Exploited in the Wild

この脆弱性に対してはCVE-2012-1823が割り当てられており、2012年5月3日のリリースと同時に修正と情報公開が完了するはずでした。 ですが、リリース後に修正が不十分であることが指摘され、残っていた脆弱性に対して、新たにCVE-2012-2311が割り当てられました。 2012年5月8日に不十分であった箇所を修正したPHPバージョン5.3.13と5.4.3が新たにリリースされて修正が完了しています。

対策等については既に多くのサイトで解説がされていますので、 今回の問題についての詳細を解説したいと思います。

以下の表は今回の脆弱性が公開される直前の最新版における検証結果です。 ディストリビューションの例として広く使われているCentOSを挙げています。

リリースバージョン PHPバージョン 影響
PHP 5.3.11 5.3.11
PHP 5.4.1 5.4.1
CentOS 5.8 php-5.1.6-32.el5
CentOS 5.8 php53-5.3.3-5.el5
CentOS 6.2 php-5.3.3-3.el6_2.6

CentOS 5.8のパッケージphp-5.1.6-32.el5のみ影響を受けていません。 入力パラメータの扱いという意味では、上記のバージョンはすべて同じ問題を抱えていますが、 オプションの処理に違いがあるため影響の有無が分かれています。

致命的な攻撃となるのは以下のオプションが使われた場合です。 任意コード実行の方が深刻度が高いのでこちらを詳細に解説します。

オプション 動作 悪用時の影響
-s ソースコードのハイライト ソースコード漏洩
-d 設定値の定義 任意コード実行

PHPのCGIモードにおいてオプションの処理(php_getopt)は複数箇所に分かれており、 CGI等の外部からの入力が想定される場合は、オプションの解析処理が無効になります。 今回の脆弱性はその判定処理が存在しない一番最初の箇所で発生しています。

まず、脆弱性の対象となるPHP5.4.1の該当箇所です。 外部から渡された引数(argv)をそのまま処理しています。 この部分には問題となるオプション-sと-dの処理が含まれています。

=== php-5.4.1/sapi/cgi/cgi_main.c
int main(int argc, char *argv[])
{
  ...
  while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
    switch (c) {
      case 'c':
        if (cgi_sapi_module.php_ini_path_override) {
          free(cgi_sapi_module.php_ini_path_override);
        }
        cgi_sapi_module.php_ini_path_override = strdup(php_optarg);
        break;
      case 'n':
        cgi_sapi_module.php_ini_ignore = 1;
        break;
      case 'd': {
        // 設定値の定義 (コード実行を誘発)
        /* define ini entries on command line */
        int len = strlen(php_optarg);
        char *val;
        ...
      /* if we're started on command line, check to see if
         we are being started as an 'external' fastcgi
         server by accepting a bindpath parameter. */
      case 'b':
        if (!fastcgi) {
          bindpath = strdup(php_optarg);
        }
        break;
      case 's': /* generate highlighted HTML from source */
        // ソースコードのハイライト (ソースコード漏洩を誘発)
        behavior = PHP_MODE_HIGHLIGHT;
        break;
    }
  ...

一方、影響を受けないphp-5.1.6-32.el5は以下の通りです。 問題となるオプションに対応する処理自体が存在しません。

=== php-5.1.6/sapi/cgi/cgi_main.c
int main(int argc, char *argv[])
{
  ...
  while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) {
    switch (c) {
      // 対象となる-sや-dの処理自体が存在しない
      case 'c':
        cgi_sapi_module.php_ini_path_override = strdup(php_optarg);
        break;
      case 'n':
        cgi_sapi_module.php_ini_ignore = 1;
        break;
#if PHP_FASTCGI
#ifndef PHP_WIN32
      /* if we're started on command line, check to see if
         we are being started as an 'external' fastcgi
         server by accepting a bindpath parameter. */
      case 'b':
        if (!fastcgi) {
          bindpath = strdup(php_optarg);
        }
        break;
#endif
#endif
    }
   ...

上記の違いによりphp-5.1.6-32.el5は影響を受けないと考えられます。 パッチの当たっていないPHPバージョン5.1.6についても該当箇所は同様です。 入力値の扱いは今回の脆弱性修正まで変わっていないので、影響は-dオプション処理の有無次第です。

問題となる処理は2006年2月頃にPHPレポジトリのリビジョン207052にて追加されています。 該当リビジョンの修正一覧と差分は以下です。
Revision 207052
Diff of /php/php-src/trunk/sapi/cgi/cgi_main.c

PHPのリリースとしては、2006年11月頃リリースされたバージョン5.2.0にて変更が取り入れられています。 その一つ前は2006年8月頃リリースされたバージョン5.1.6ですが、こちらにはその変更は含まれていません。 脆弱性の影響についてもこの変更に同期しており、バージョン5.1.6においては影響を受けず、 バージョン5.2.0において影響を受ける事を確認しています。

この適用より更に前の2004年にリリースされているバージョン5.0.0の時点で、 オプションの処理は既に複数に分かれており、CGI等の外部入力を考慮した実装になっていました。 その部分の実装については、今回の脆弱性の影響を受けないバージョンと殆ど変わっていません。 今回の問題はその設計の意図を読み取れずに、変更を適用してしまったため発生したのではないかと推測されます。

-
 
カテゴリー :
脆弱性  
タグ :
Vulnerability   PHP  
この記事のURL :
https://sect.iij.ad.jp/d/2012/05/087662.html