PHP反序列化中如何寻找POP链

PHP反序列化中如何寻找POP链,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名申请、虚拟空间、营销软件、网站建设、莲都网站维护、网站推广。

环境搭建

运行环境要求

  • PHP >= 7.1.3

  • OpenSSL PHP Extension

  • PDO PHP Extension

  • Mbstring PHP Extension

安装题目环境

PHP反序列化中如何寻找POP链

运行题目代码

PHP反序列化中如何寻找POP链

更多请参考:https://laravel-china.org/docs/lumen/5.7/installation/2402

PS:更新P牛制作的docker环境 https://github.com/phith0n/code-breaking

漏洞点

routes/web.php文件中,定义了 web程序的路由,当我们以 GETPOST方法访问 http://website/server/editor的时候,程序就会调用 app/Http/Controllers/EditorController.php类中的 main方法。

PHP反序列化中如何寻找POP链

我们进而看 app/Http/Controllers/EditorController.php文件,很快便会发现有一个 download方法中的 $url变量没有经过任何处理用在了 file_get_contents函数中, download方法代码如下:

PHP反序列化中如何寻找POP链

这时我们便考虑 $url变量是否可控,如果可控,便可以利用 phar反序列化。我们回溯寻找 $url变量来源,会发现在 doCatchimage方法中,该变量值是从 $sources变量来。而 $sources变量由用户传来的 source参数决定(通过 http://website/server/editor/?action=Catchimage&source[]=phar://xxx.gif即可控制 $url变量),相关代码如下:

PHP反序列化中如何寻找POP链

那么接下来,我们就要寻找可利用的类方法,然后通过 phar反序列化触发漏洞。

了解PHPGGC

在寻找 pop链之前,我们不妨先看看 phpggc中已有的 4种关于 Laravel框架 RCEpayload生成方法,以便我们更快速的找出本题的 pop链,其 4种 Laravel框架 RCEpayload生成方法分别如下:

第1种

PHP反序列化中如何寻找POP链

其反序列化时,类方法调用过程如下:

PHP反序列化中如何寻找POP链

第2种

PHP反序列化中如何寻找POP链

其反序列化时,类方法调用过程如下:

PHP反序列化中如何寻找POP链

第3种

PHP反序列化中如何寻找POP链

其反序列化时,类方法调用过程如下:

PHP反序列化中如何寻找POP链

第4种

PHP反序列化中如何寻找POP链

其反序列化时,类方法调用过程如下:

PHP反序列化中如何寻找POP链

这里我选取 第1种phar反序列化执行结果图(题目环境为 PHP7.1.16):

PHP反序列化中如何寻找POP链

然而本题目的环境还有一些额外的限制,例如 PHP版本为 7.2.14,且设置了禁用了如下函数和类(这个通过 phpggc的第一个  Laravel框架 RCE生成 phpinfo函数的利用 phar即可看到):

disable_functions:
system,shell_exec,passthru,exec,popen,proc_open,pcntl_exec,mail,apache_setenv,mb_send_mail,dl,set_time_limit,ignore_user_abort,symlink,link,error_log

disable_classes:
GlobIterator,DirectoryIterator,FilesystemIterator,RecursiveDirectoryIterator

由于在 PHP7.x版本中,很多函数禁止动态调用了,加上上面的这些限制,所以我们还需要寻找其他利用点,结合上述 POP链,完成写 shell

开始寻找pop链

我们可以发现上面的4种 RCE入口点都是从 PendingBroadcast类的 __destruct方法开始的,那么我们着重搜索 dispatch方法和 __call方法。经过一番搜索,发现 ValidGenerator类中的 __call比较好利用。

PHP反序列化中如何寻找POP链

我们可以看到其代码中先调用了 call_user_func_array函数,然后将 call_user_func_array函数的执行结果又传入  call_user_func函数,只要我们能控制住 call_user_func_array函数的执行结果,相当于  call_user_func函数的两个参数都可控,这样我们便可以调用任意类方法。

我们接着搜索可以用于控制 call_user_func_array函数执行结果的类,这里我找到了 DefaultGenerator类的 __call方法,我们可以看到返回值 $this->default完全可控。

PHP反序列化中如何寻找POP链

现在 call_user_func(res)中的两个参数都可控了。那么如果我们想写shell,就要调用 file_put_contents函数,而这个函数需要两个参数,所以直接通过 call_user_func函数是无法使用该函数的,我们需要通过 call_user_func_array函数来使用 file_put_contents函数,用法形如: call_user_func_array('file_put_contents',array('shell.php','test'))

通过直接搜索 call_user_func_array函数,我们会发现两个比较好利用的类函数。但是这里的第一个 ClosureWrapper类我们无法利用,所以得利用 ReturnCallback类的 invoke方法,具体代码如下:

PHP反序列化中如何寻找POP链

很明显 invoke方法两个参数都可控,现在我们只要构造好一个 Invocation类对象即可。通过搜索,我们会发现 Invocation是一个接口,那么我们找到他的实现类即可。这里我找到了 StaticInvocation类来实现上诉功能,其代码具体如下:

PHP反序列化中如何寻找POP链

这样子,我们的整个 POP链就构造好了。下面是 exp

 {
     {
         ;
         ;
         (, ){
              ;
              ;
        }
    }
};
 {
     {
         ;
          (  ){
              ;
        }
    }
     {
         ;
         ;
         ;
        
          (,   ,   )
        {
              ;
              ;
              ;
        }
    }
};
 {
     
    {
         ;
          ()
        {
              ;
        }
    }
};
 {
     {
         ;
          (){
              ;
        }
    }
};
{
      ;
      (,);
       ();
       ();
       ();
       (,(,),);
       (,);
      ;
      ;
    ()  () : ;
     ();
    ();
    ();
    ();
    (,);
    ();
};

最后

我们再通过下面这张图片,来理清整个 POP链 的调用过程。

PHP反序列化中如何寻找POP链

看完上述内容,你们掌握PHP反序列化中如何寻找POP链的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联行业资讯频道,感谢各位的阅读!


文章名称:PHP反序列化中如何寻找POP链
链接分享:http://scyanting.com/article/ppoeig.html