php实现Linux服务器木马排查及加固功能


Posted in PHP onDecember 29, 2014

网站频繁被挂马?做一些改进,基本上能把这个问题解决,因为discuz x等程序存在漏洞,被上传了websehll,每次被删除过段时间又出来了,最终查到所有的木马。

从以下几个方面查找并加强(如果能不开启会员功能,不给任何上传入口,保护好后台密码,加固好PHP,一般就没什么问题了)。

1.根据特征码查找:

php木马一般含有

<?php eval($_POST[cmd]);?>

或者
<?php assert($_POST[cmd]);?>
find /wwwroot/* -type f -name "*.php" |xargs grep "eval(" > /wwwroot/scan.txt

结果就查出很多明显的webshell,并且发现都藏在attachment等目录下

2.利用网上的一个php代码,搜索最近被修改的文件

scandir.php
内容如下:

<?php 

set_time_limit(0);//防止超时 

/** 

* 

* php目录扫描监控增强版 

* 

* @author lssbing (lssbing#gmail.com) 

* @date 2010-1-18 

* @license BSD 

* @version 1.0 

* 

下面几个变量使用前需要手动设置 

* 

**/ 

/*===================== 程序配置 =====================*/ 

$pass="12345";//设置密码 

$jkdir="."; //设置监控扫描的目录,当前目录为'.',上一级目录为'..',也可以设置绝对路径,后面不要加斜杠,默认为当前目录 

$logfilename="./m.log";//设置存储log的路径,可以放置在任意位置 

$exclude=array('data','images');//排除目录 

$danger='eval|cmd|passthru|gzuncompress';//设置要查找的危险的函数 以确定是否木马文件 

$suffix='php|inc';//设置要扫描文件的后缀 

/*===================== 配置结束 =====================*/ 

 

$filename=$_GET['filename']; 

$check=$_GET['check']; 

$jumpoff=false; 

$url = $_SERVER['PHP_SELF']; 

$thisfile = end(explode('/',$url)); 

$jump="{$thisfile}|".implode('|',$exclude); 

$jkdir_num=$file_num=$danger_num=0; 

define('M_PATH',$jkdir); 

define('M_LOG',$logfilename); 

if ($check=='check') 

{ 

$safearr = explode("|",$jump); 

$start_time=microtime(true); 

safe_check($jkdir); 

$end_time=microtime(true); 

$total=$end_time-$start_time; 

$file_num=$file_num-$jkdir_num; 

$message= " 文件数:".$file_num; 

$message.= " 文件夹数:".$jkdir_num; 

$message.= " 可疑文件数:".$danger_num; 

$message.= " 执行时间:".$total; 

echo $message; 

}else{ 

if ($_GET['m']=="del") Delete();//处理文件删除 

//读取文件内容 

if(isset($_GET['readfile'])){ 

//输出查看密码,密码校验正确以后输出文件内容 

if(emptyempty($_POST['passchack'])){ 

   echo"<form id=\"form1\" name=\"form1\" method=\"post\">" 

    . " <label>pass" 

    . " <input type=\"text\" name=\"passchack\" />" 

    . " </label>" 

    . " <input type=\"submit\" name=\"Submit\" value=\"提交\" />" 

    . "</form>" 

   .""; 

   exit; 

}elseif(isset($_POST['passchack'])&&$_POST['passchack']==$pass){ 

   $code=file_get_contents($_GET['readfile']); 

   echo"<textarea name=\"code\" cols=\"150\" rows=\"30\" id=\"code\" style='width:100%;height:450px;background:#cccccc;'>{$code}</textarea>"; 

   exit; 

}else{ 

   exit; 

} 

 

}else{ 

record_md5(M_PATH); 

if(file_exists(M_LOG)){ 

        $log = unserialize(file_get_contents(M_LOG)); 

}else{ 

        $log = array(); 

} 

 

if($_GET['savethis']==1){ 

//保存当前文件md5到日志文件 

@unlink(M_LOG); 

file_put_contents(M_LOG,serialize($file_list)); 

echo "<a href='scandir.php'>保存成功!点击返回</a>"; 

exit; 

} 

if(emptyempty($log)){ 

echo "当前还没有创建日志文件!点击[保存当前]创建日志文件!"; 

}else{ 

if($file_list==$log){ 

   echo "本文件夹没有做过任何改动!"; 

}else{ 

   if(count($file_list) > 0 ){ 

    foreach($file_list as $file => $md5){ 

    if(!isset($log[$file])){ 

     echo "新增文件:<a href={$file} target='_blank'>".$file."</a>"." 创建时间:".date("Y-m-d H:i:s",filectime($file))." 修改时间:".date("Y-m-d H:i:s",filemtime($file))." <a href=?readfile={$file} target='_blank'>源码</a><a href='?m=del&filename={$file}' target='_blank'>删除</u></a><br />"; 

    }else{ 

     if($log[$file] != $md5){ 

     echo "修改文件:<a href={$file} target='_blank'>".$file."</a>"." 创建时间:".date("Y-m-d H:i:s",filectime($file))." 修改时间:".date("Y-m-d H:i:s",filemtime($file))." <a href=?readfile={$file} target='_blank'>源码</a><br />"; 

 

     unset($log[$file]); 

     }else{ 

     unset($log[$file]); 

     } 

    } 

    } 

   } 

   if(count($log)>0){ 

    foreach($log as $file => $md5){ 

    echo "删除文件:<a href={$file} target='_blank'>".$file."</a><br />"; 

    } 

   } 

    } 

} 

} 

} 

 

//计算md5 

function record_md5($jkdir){ 

        global $file_list,$exclude; 

        if(is_dir($jkdir)){ 

                $file=scandir($jkdir); 

                foreach($file as $f){ 

                        if($f!='.' && $f!='..' && !in_array($f, $exclude)){ 

                                $path = $jkdir.'/'.$f; 

                                if(is_dir($path)){ 

                                        record_md5($path); 

                                }else{ 

                                        $file_list[$path]=md5_file($path); 

                                } 

                        } 

                } 

        } 

} 

 

function Safe_Check($jkdir)//遍历文件 

{ 

global $danger ,$suffix ,$jkdir_num ,$file_num ,$danger_num; 

 

$hand=@dir($jkdir) or die('文件夹不存在') ; 

while ($file=$hand->read()) 

{ 

    $filename=$jkdir.'/'.$file; 

    if (!$jumpoff) { 

   if(Jump($filename))continue; 

    } 

    if(@is_dir($filename) && $file != '.' && $file!= '..'&& $file!='./..') 

    {   $jkdir_num++; 

    Safe_Check($filename); 

    } 

    if (preg_match_all ("/\.($suffix)/i",$filename,$out)) 

    { 

 

   $str=''; 

   $fp = @fopen($filename,'r')or die('没有权限'); 

   while(!feof($fp)) 

   { 

   $str .= fgets($fp,1024); 

   } 

   fclose($fp); 

   if( preg_match_all ("/($danger)[ \r\n\t]{0,}([\[\(])/i",$str,$out)) 

   { 

   echo "<font color='green' style='font-size:14px'>可疑文件:{$filename}</font>"." 创建时间:".date("Y-m-d H:i:s",filectime($filename))." 修改时间:".date("Y-m-d H:i:s",filemtime($filename))." <a href='?readfile={$filename}' target='_blank'><u>查看代码</u></a> <a href='?m=del&filename=$filename' target='_blank'>删除</u></a><br>"; 

   $danger_num++; 

   } 

    } 

    $file_num++; 

} 

} 

function Edit()//查看可疑文件 

{ 

global $filename; 

$filename = str_replace("..","",$filename); 

$file = $filename; 

$content = ""; 

if(is_file($file)) 

{ 

    $fp = fopen($file,"r")or die('没有权限'); 

    $content = fread($fp,filesize($file)); 

    fclose($fp); 

    $content = htmlspecialchars($content); 

 

} 

echo "<textarea name='str' style='width:100%;height:450px;background:#cccccc;'>$content</textarea>\r\n"; 

exit(); 

} 

function Delete()//删除文件 

{ global $filename,$pass; 

if(emptyempty($_POST['passchack'])){ 

    echo"<form id=\"form1\" name=\"form1\" method=\"post\">" 

   . " <label>pass" 

   . " <input type=\"text\" name=\"passchack\" />" 

   . " </label>" 

   . " <input type=\"submit\" name=\"Submit\" value=\"提交\" />" 

   . "</form>" 

    .""; 

    exit; 

}elseif(isset($_POST['passchack'])&&$_POST['passchack']==$pass){ 

   (is_file($filename))?($mes=unlink($filename)?'删除成功':'删除失败 查看权限'):''; 

   echo $mes; 

   exit(); 

}else{ 

   echo '密码错误!'; 

   exit; 

} 

} 

function Jump($file)//跳过文件 

{ 

global $jump,$safearr; 

if($jump != '') 

{ 

    foreach($safearr as $v) 

    { 

   if($v=='') continue; 

   if( eregi($v,$file) ) return true ; 

    } 

} 

return false; 

} 

?> 

<a href="scandir.php">[查看文件改动]</a>|<a href="scandir.php?savethis=1">[保存当前文件指纹]</a>|<a href="scandir.php?check=check">[扫描可疑文件]</a>

执行后能看到最近被修改的文件,具有参加价值

3.修改php.ini,限制以下函数

disable_functions =  phpinfo,passthru,exec,system,chroot,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_alter,ini_restore,dl,pfsockopen,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,fsocke,popen,proc_close,curl_exec,curl_multi_exec,parse_ini_file,show_source,dl,escapeshellarg,escapeshellcmd

4.修改nginx.conf ,限制一些目录执行php文件

server 

{ 

    listen       80; 

    server_name  www.***.com; 

    index   index.htm index.html index.php; 

    root  /wwwroot/; 

     

 

       

    rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last; 

    rewrite ^([^\.]*)/article-([0-9]+)-([0-9]+)\.html$ $1/portal.php?mod=view&aid=$2&page=$3 last; 

    rewrite ^([^\.]*)/forum-(\w+)-([0-9]+)\.html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last; 

    rewrite ^([^\.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last; 

    rewrite ^([^\.]*)/group-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=group&fid=$2&page=$3 last; 

    rewrite ^([^\.]*)/space-(username|uid)-(.+)\.html$ $1/home.php?mod=space&$2=$3 last; 

    rewrite ^([^\.]*)/([a-z]+)-(.+)\.html$ $1/$2.php?rewrite=$3 last; 

    rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last; 

         

 

        location ~ ^/images/.*\.(php|php5)$ 

                { 

              deny all; 

                } 

 

        location ~ ^/static/.*\.(php|php5)$ 

                { 

               deny all; 

                } 

 

        location ~* ^/data/(attachment|avatar)/.*\.(php|php5)$ 

            { 

                deny all; 

            } 

 

    location ~ .*\.(php|php5)?$ 

    {       

      fastcgi_pass  127.0.0.1:9000; 

      fastcgi_index index.php; 

      include fcgi.conf; 

    } 

     

         

 

error_page  400 /404.html; 

error_page  403 /404.html; 

error_page  404 /404.html; 

error_page  405 /404.html; 

error_page  408 /404.html; 

error_page  410 /404.html; 

error_page  411 /404.html; 

error_page  412 /404.html; 

error_page  413 /404.html; 

error_page  414 /404.html; 

error_page  415 /404.html; 

error_page  500 /404.html; 

error_page  501 /404.html; 

error_page  502 /404.html; 

error_page  503 /404.html; 

error_page  506 /404.html; 

 

 

log_format  acclog    "$remote_addr $request_time $http_x_readtime [$time_local] \"$request_method http://$host$request_uri\" $status $body_bytes_sent \"$http_referer\" \"$http_user_agent\""; 

        access_log  /logs/access.log  acclog; 

}

此处需要注意的是

location ~ ^/images/.*\.(php|php5)$ 

{ 

  deny all; 

}

这些目录的限制必须写在

location ~ .*\.(php|php5)?$ 

{       

  fastcgi_pass  127.0.0.1:9000; 

  fastcgi_index index.php; 

  include fcgi.conf; 

}

的前面,否则限制不生效。

PHP 相关文章推荐
PHP个人网站架设连环讲(一)
Oct 09 PHP
WHOIS类的修改版
Oct 09 PHP
用session做客户验证时的注意事项
Oct 09 PHP
php循环创建目录示例分享(php创建多级目录)
Mar 04 PHP
destoon调用企业会员公司形象图片的实现方法
Aug 21 PHP
PHP7.0版本备注
Jul 23 PHP
php抛出异常与捕捉特定类型的异常详解
Oct 26 PHP
PHP中Trait及其应用详解
Feb 14 PHP
PHP数据库编程之MySQL优化策略概述
Aug 16 PHP
详解Yaf框架PHPUnit集成测试方法
Dec 27 PHP
thinkPHP框架实现多表查询的方法
Jun 14 PHP
Laravel相关的一些故障解决
Aug 19 PHP
php连接oracle数据库及查询数据的方法
Dec 29 #PHP
php查询mssql出现乱码的解决方法
Dec 29 #PHP
php+mysql大量用户登录解决方案分析
Dec 29 #PHP
php从memcache读取数据再批量写入mysql的方法
Dec 29 #PHP
php操作mongoDB实例分析
Dec 29 #PHP
Yii实现多数据库主从读写分离的方法
Dec 29 #PHP
php调用mysql存储过程实例分析
Dec 29 #PHP
You might like
四月新番又没了,《Re:从零开始的异世界生活》第二季延期至7月播出
2020/05/06 日漫
一篇入门的php Class 文章
2007/04/04 PHP
PHP之COOKIE支持详解
2010/09/20 PHP
Linux下安装oracle客户端并配置php5.3
2014/10/12 PHP
javascript下给元素添加事件的方法与代码
2007/08/13 Javascript
JavaScript插入动态样式实现代码
2012/02/22 Javascript
JS下拉缓冲菜单示例代码
2013/08/30 Javascript
js螺旋动画效果的具体实例
2013/11/15 Javascript
JavaScript将数据转换成整数的方法
2014/01/04 Javascript
JS实现的生成随机数的4个函数分享
2015/02/11 Javascript
JQuery实现的图文自动轮播效果插件
2015/06/19 Javascript
详解angularjs结合pagination插件实现分页功能
2017/02/10 Javascript
vue.js选中动态绑定的radio的指定项
2017/06/02 Javascript
NodeJS简单实现WebSocket功能示例
2018/02/10 NodeJs
JS在Array数组中按指定位置删除或添加元素对象方法示例
2019/11/19 Javascript
js布局实现单选按钮控件
2020/01/17 Javascript
简单了解常用的JavaScript 库
2020/07/16 Javascript
[01:04:31]DOTA2-DPC中国联赛定级赛 iG vs Magma BO3第二场 1月8日
2021/03/11 DOTA
python格式化字符串实例总结
2014/09/28 Python
浅要分析Python程序与C程序的结合使用
2015/04/07 Python
Python使用分布式锁的代码演示示例
2018/07/30 Python
Python开发虚拟环境使用virtualenvwrapper的搭建步骤教程图解
2018/09/19 Python
django解决订单并发问题【推荐】
2019/07/31 Python
python中plt.imshow与cv2.imshow显示颜色问题
2020/07/16 Python
css3实现背景模糊的三种方式(小结)
2020/05/15 HTML / CSS
美国餐厅用品和厨房设备批发网站:KaTom Restaurant Supply
2018/01/27 全球购物
android面试问题与答案
2016/12/27 面试题
合作投资意向书
2014/04/01 职场文书
建筑工地文明标语
2014/10/09 职场文书
贵阳市党的群众路线教育实践活动党(工)委领导班子整改方案
2014/10/26 职场文书
廉洁自律个人总结
2015/02/14 职场文书
毕业证明书
2015/06/19 职场文书
推荐六本经典文学奖书籍:此生必读
2019/08/22 职场文书
一文弄懂MySQL中redo log与binlog的区别
2022/02/15 MySQL
React四级菜单的实现
2022/04/08 Javascript
i7 6700处理器相当于i5几代
2022/04/19 数码科技