thinkphp诸多限制条件下如何getshell详解
前⾔
先说说2020_n1CTF的web题Easy_tp5复现问题。
这个题在保留thinkphp的RCE点的同时,并且RCE中ban掉许多危险函数,只能允许单参数的函数执⾏。对于现在在⽹络中流传的⽂件包含的点也增加了限制。
smile yyds!
先说⼀下这个题限制条件:
thinkphp版本:5.0.0
php版本:7
对于包含⽂件增加了限制
ban掉所有的单参数危险函数
设置open_basedir为web⽬录
设置仅在public⽬录下可写
在TP5.0.0的中,⽬前公布的只是存在利⽤Request类其中变量被覆盖导致RCE。如果ban掉单参数可利⽤函数那么只能⽤⽂件包含,但是⽂件包含做了限制不能包含log⽂件,所以只能从别的⽅⾯⼊⼿。
这些限制都太⼤了,所以需要想办法去上传⼀个shell来完成后续绕disable_function。
⾸先TP5.0.0⽬前只存在通过覆盖Request中的某些变量导致RCE,其余细节不再赘述,我们看看⼤概代码执⾏点在哪⾥。
call_user_func是代码执⾏点,我们基本上所有PHP⾃带的可利⽤函数基本被ban掉,所以我们需要从⾃写的函数调⽤来⼊⼿,⾸先我们需要看下这个点。可回调函数不仅仅指的是简单函数,还可以是⼀些对象的⽅法,包括静态⽅法。
⽅法⼀ thinkphp\library\think\Build::module
我们可以这样通过调⽤这个类的静态⽅法module,来实现写⽂件的操作。
我们先看看这个该怎么⾛,我们看到这个mkdir是在application创建⽬录,但是由于权限问题肯定⽆法创建。根据TP报错即退出的机制从⽽中断执⾏。那么我们可以通过../public/test来创建⽬录。
我们会进⼊到buildhello函数中。
⾛完流程发现我们可以在public创建了⼀个test模块,同样看到test/controller/Index.php中我们所写的../public/test保存了下来那么我们就绕过,但是执⾏完之后会发现⼀些语法错误导致代码不能执⾏。
由于这部分内容可控那我们就把他变得符合语法执⾏,我们可以这么做test;eval($_POST[a]);#/../../public/test;,这样就符合语法。
但是还有⼀个问题需要解决,就是我们这样的payload会设置⼀个不存在⽬录从⽽可以符合语法并且加⼊eval函数。但是现在还存在⼀个跨越不存在⽬录的问题。
linux环境
win环境
在Linux中不能创建不存在的⽬录,但是在win下就可以。但是报错是warning,并不会中断执⾏,并且在bindhello函数中我们会看到:
其中mkdir函数存在recursive参数为true,允许递归创建多级嵌套的⽬录。这样就可以使mkdir中使⽤不存在的⽬录就可以进⾏绕过。但是现在有个问题:前⾯的mkdir中的warning报错被TP捕获到直接会退出⽆法执⾏后⾯的内容,那么我们就需要使⽤⼀些办法进⾏抑制报错。我们经常做题会⽤到⼀个函数error_reporting,我们可以使⽤error_reporting(0)抑制报错。
我们再回到代码执⾏点,我们发现call_user_func函数执⾏完的值会执⾏循环再次回到call_user_func()中当回调函数的参数进⾏使⽤。因此需要考虑⼀下怎么调整才能让我们执⾏并且抑制报错。
1.如果我们将error_reporting放在前⾯执⾏,⽆论参数是什么都会返回0从⽽导致后⾯执⾏代码不可控。
2.如果我们将think\Build::module放前⾯,那么thinkphp报错也不能执⾏成功。
spring framework rce漏洞复现但是如果我们放⼊⼀个中间值,在第⼀次执⾏能够成功创建⽬录,并且error_reporting还能成功执⾏,这时候就需要⽤到PHP弱类型⽐较,PHP中 0 == null,0 == ⾮数字开头的字符串。
payload如下可⽰:
⽅法⼆使⽤注释符绕过语法产⽣的错误
payload如下:
这样就会使⽤注释符注释掉后⾯的语法错误,然后使⽤?>包裹住,后⾯跟上⾃⼰⽤的payload即可。但是这样会产⽣⼀个问题,⽆法在win环境下使⽤,win下⽂件夹中不能带这些字符/ \ : * ? " < > |
⽅法三⽂件包含&php伪协议
这种操作就是,我们通过之前的think\Build::module写⽂件进去,写⼊的内容是我们rot13编码过的。然后通过think\__include_file调⽤我们写⼊⽂件的内容,因为这个过滤不够完全,可以让我们包含我们所写的内容。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。