Xoops hack: デバッグモードのコード解析
前から気になっていた, Xoopsのデバックモードのコード解析を行いました.
管理者メニュー -> 一般設定 -> デバッグモードを有効にする -> MySQL/Blockデバグ
を設定すると, ページ遷移毎にそのページを生成する際に実行されたSQL文が表示されます.
footer.phpを眺めていると, デバッグモード時に実行されそうなコードを発見しました.
cd ~/public_html/xoops-2.0.9.2-ja-eucjp/html $vi footer.php [...] 71 if ($xoopsConfig['debug_mode'] == 2 && $xoopsUserIsAdmin) { 72 $dummyfile = 'dummy_'.time().'.html'; 73 $fp = fopen(XOOPS_CACHE_PATH.'/'.$dummyfile, 'w'); 74 fwrite($fp, $xoopsLogger->dumpAll()); 75 fclose($fp); 76 echo '<script language=javascript> 77 debug_window = openWithSelfMain("'.XOOPS_URL.'/misc.php?action=showpopups&type=debug& file='.$dummyfile.'", "popup" , 680, 450); 78 </script>'; 79 }
73行目にある「XOOPS_CACHE_PATH」の値を調べるために, grepしてみました.
$ grep -rn "XOOPS_CACHE_PATH" . | grep "define(" ./include/common.php:57: define("XOOPS_CACHE_PATH", XOOPS_ROOT_PATH."/cache");
どうやら, 現在のワークディレクトリの直下にある「cache」ディレクトリのことのようです.
$xoopsLogger->dumpAll()でダンプされたSQL文が, このディレクトリに出力されるのだなと考えました.
そこで早速, MySQL/Blockデバグを有効にして, ブラウザでXoopsのページを見てみました.
残念ながら, 期待していた通りではありませんでした...
「cache」ディレクトリには何もありませんでした.
「これはどう考えてもおかしい」と思い, 少し考えました.
footer.phpの77行目にあるコードに注目しました.
「もしかしたら, misc.phpがファイルを削除しているのでは?」と思いました.
$ cd .. $ vi misc.php [...] 220 case 'debug': 221 if ($xoopsUser && $xoopsUser->isAdmin()) { 222 $file = XOOPS_CACHE_PATH.'/'.trim(str_replace('..', '', $_GET['file'])); 223 if (file_exists($file)) { 224 include($file); 225 @unlink($file); 226 } 227 } 228 break;
予想は的中していました. $xoopsLogger->dumpAll()の出力結果をincludeしてからunlinkしていたのでした.
謎はすべて解けました.
misc.phpに興味深いコードを見つけました.
そう, 222行目にある
$file = XOOPS_CACHE_PATH.'/'.trim(str_replace('..', '', $_GET['file']));
です.
悪意のあるアタッカーがディレクトリトラバースできないように「..」を除去しているのですね.
もし, このstr_replaceのコードがなければ, Apacheが読み書きできるファイルなら何でも削除できてしまいます.
こんな工夫でディレクトリトラバースを抑制できるのかと, 少し関心しました.
勉強になりました.