2016-04-20

curl | bashをサーバーサイドで判定する方法

Detecting the use of "curl | bash" server side | Application Security

ソフトウェアをインストールするとき、シェルスクリプトを実行するのはよくあることだ。しかし、そのシェルスクリプトが他人のリモートサーバーでホストされていた場合、curl | bashするのは危険だ。まともなユーザーは、curl | bashする前に、まず中身を確認して、悪意がないことを確かめるものだ。

しかしもし、サーバー側がwgetやcurlといったツールとブラウザーを判定して、それぞれ別のコードを返した場合どうか。ユーザーが見るのは囮のシェルスクリプトだ。

しかし、それではcurlやwgetを利用してシェルスクリプトをダウンロードするユーザーは騙せない。しかしもし、curlとcurl | bashを判定することができたらどうか。実は、できるのだ。

curlとcurl | bashを判定する方法は、bashの処理にある。bashはコードを順次実行していく。コードの実行中はパイプからの読み出しが滞る。ネットワークとパイプのバッファーが全て埋まってしまえば、サーバーからのデータのダウンロードは中断する。したがって、コードの冒頭にsleepを置いて、バッファーを埋めるために無害で表示されないnull文字を送りつける。ダウンロードが途中で中断すれば、curlはパイプを経由してbashに出力しているのだと判断できる。

curl | bashを判定するサーバーを判定する方法

では、ユーザーはどうやってcurl | bashを判定するサーバーを判定すればいいのだろうか。判定が上に述べたような簡単なディレイで行われているならば、そういうディレイを発生させてやればよい。

curl https://example.com/setup.bash | (sleep 3; cat)

しかし、curl | bashを判定する方法はその他にもあるし、ディレイを複数使って判定することもできるので、確実に判定はできない。信頼できないデータはまずローカルのファイルに落として、中身を検証してから、ローカルのファイルをbashで実行すべきだ。

1 comment:

Anonymous said...

同じ理由で信頼できないバイナリはソース見てから自分でビルドすべきということになるはずである。

そして信用できるサイトからのバイナリを無確認で実行しているのであれば、
同じように信用できるサイトからのシェルスクリプトであれば無確認で実行して良いはずである。