thinkphp诸多限制条件下如何getshell详解


Posted in PHP onDecember 09, 2020

前言

先说说2020_n1CTF的web题Easy_tp5复现问题。

这个题在保留thinkphp的RCE点的同时,并且RCE中ban掉许多危险函数,只能允许单参数的函数执行。对于现在在网络中流传的文件包含的点也增加了限制。

smile yyds!

先说一下这个题限制条件:

  • thinkphp版本:5.0.0
  • php版本:7
  • 对于包含文件增加了限制

thinkphp诸多限制条件下如何getshell详解

ban掉所有的单参数危险函数

thinkphp诸多限制条件下如何getshell详解

设置open_basedir为web目录

thinkphp诸多限制条件下如何getshell详解

设置仅在public目录下可写

thinkphp诸多限制条件下如何getshell详解

在TP5.0.0的中,目前公布的只是存在利用Request类其中变量被覆盖导致RCE。如果ban掉单参数可利用函数那么只能用文件包含,但是文件包含做了限制不能包含log文件,所以只能从别的方面入手。

这些限制都太大了,所以需要想办法去上传一个shell来完成后续绕disable_function。

首先TP5.0.0目前只存在通过覆盖Request中的某些变量导致RCE,其余细节不再赘述,我们看看大概代码执行点在哪里。

thinkphp诸多限制条件下如何getshell详解

call_user_func是代码执行点,我们基本上所有PHP自带的可利用函数基本被ban掉,所以我们需要从自写的函数调用来入手,首先我们需要看下这个点。可回调函数不仅仅指的是简单函数,还可以是一些对象的方法,包括静态方法。

thinkphp诸多限制条件下如何getshell详解

方法一 thinkphp\library\think\Build::module

我们可以这样通过调用这个类的静态方法module,来实现写文件的操作。

thinkphp诸多限制条件下如何getshell详解

我们先看看这个该怎么走,我们看到这个mkdir是在application创建目录,但是由于权限问题肯定无法创建。根据TP报错即退出的机制从而中断执行。那么我们可以通过../public/test来创建目录。

我们会进入到buildhello函数中。

thinkphp诸多限制条件下如何getshell详解

走完流程发现我们可以在public创建了一个test模块,同样看到test/controller/Index.php中我们所写的../public/test保存了下来那么我们就绕过,但是执行完之后会发现一些语法错误导致代码不能执行。

thinkphp诸多限制条件下如何getshell详解

由于这部分内容可控那我们就把他变得符合语法执行,我们可以这么做test;eval($_POST[a]);#/../../public/test;,这样就符合语法。

thinkphp诸多限制条件下如何getshell详解

但是还有一个问题需要解决,就是我们这样的payload会设置一个不存在目录从而可以符合语法并且加入eval函数。但是现在还存在一个跨越不存在目录的问题。

thinkphp诸多限制条件下如何getshell详解

linux环境

thinkphp诸多限制条件下如何getshell详解

win环境

thinkphp诸多限制条件下如何getshell详解

在Linux中不能创建不存在的目录,但是在win下就可以。但是报错是warning,并不会中断执行,并且在bindhello函数中我们会看到:

thinkphp诸多限制条件下如何getshell详解

其中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报错也不能执行成功。

但是如果我们放入一个中间值,在第一次执行能够成功创建目录,并且error_reporting还能成功执行,这时候就需要用到PHP弱类型比较,PHP中 0 == null,0 == 非数字开头的字符串。

payload如下可示:

thinkphp诸多限制条件下如何getshell详解

thinkphp诸多限制条件下如何getshell详解

方法二 使用注释符绕过语法产生的错误

payload如下:

thinkphp诸多限制条件下如何getshell详解

这样就会使用注释符注释掉后面的语法错误,然后使用?>包裹住,后面跟上自己用的payload即可。但是这样会产生一个问题,无法在win环境下使用,win下文件夹中不能带这些字符/ \ : * ? " < > |

方法三 文件包含&php伪协议

这种操作就是,我们通过之前的think\Build::module写文件进去,写入的内容是我们rot13编码过的。然后通过think\__include_file调用我们写入文件的内容,因为这个过滤不够完全,可以让我们包含我们所写的内容。

thinkphp诸多限制条件下如何getshell详解

thinkphp诸多限制条件下如何getshell详解

方法四 覆盖日志路径写入

因为题目将error_log函数ban掉了,所以这个非预期解是在不ban掉error_log函数的情况下所实现的。

payload具体如下:

thinkphp诸多限制条件下如何getshell详解

1.通过json_decode使得我们传入的{"type":"File", "path":"/var/www/html/null/public/logs"}转换成内置类stdClass的一个对象。

2.再通过get_object_vars将其转换成数组传入到think\Log::init中。

3.在其中会new了一个\think\log\driver\File,并且传入的参数是我们的'path'=>/var/www/html/null/public/logs,那么会触发类中的__construct,将其默认的path给覆盖掉。

thinkphp诸多限制条件下如何getshell详解

thinkphp诸多限制条件下如何getshell详解

4.最后因为我们触发漏洞点的特殊性,肯定会报错使得报错信息可以被计入到log文件里。

thinkphp诸多限制条件下如何getshell详解

thinkphp诸多限制条件下如何getshell详解

5.之后再通过think\Lang::load包含。

thinkphp诸多限制条件下如何getshell详解

thinkphp诸多限制条件下如何getshell详解

thinkphp诸多限制条件下如何getshell详解

方法五  ::竟然可以调用非静态方法

下面是个简单的例子。

<?php
class A{
 public function test1($a){
  echo "test1".$a;
 }
 static function test2($a){
  echo "test2".$a;
 }
 public function test3($a){
  $this->b = $a;
  echo "test3".$this->b;
 }
}

call_user_func("A::test1","x");
echo "</br>";
call_user_func("A::test2","x");
echo "</br>";
call_user_func("A::test3","x");
echo "</br>";
//$xxx=new A();
//call_user_func(array($xxx,'test3'),"x");

我们看看会怎么执行。

会发现使用::调用了public类的方法并且能够成功执行,但是会报错。并且::仅仅适合在方法中没有写$this的情况,因为$this指代的是这个对象,找不到对象自然会报错。那么我们看一下下面的payload就会一眼明白,payload其实用了跟上面预期解抑制错误的另一种方法,然后抑制报错让TP不会遇错停止执行。

这个题解的payload如下:

thinkphp诸多限制条件下如何getshell详解

1.因为PHP本身的错误处理被thinkphp所替代进行处理,所以上面就是将thinkphp所替代错误进行处理的方法给覆盖掉导致没有办法正常执行。

2.调用self::path方法,可以抛弃掉我们上一个执行的返回值,并且返回我们所输入的path。为什么会返回path,path为什么是我们输入的值,这个就是之前提到的代码执行点他是覆盖了Request类的参数,所以方法返回的是$this->path,这个我们可以控制。

thinkphp诸多限制条件下如何getshell详解

3.之后调用base64_decode,返回值就是我们base64解码的内容。

4.解码后的返回值就会进入\think\view\driver\Php::Display中,然后进入eval执行代码。

thinkphp诸多限制条件下如何getshell详解

thinkphp诸多限制条件下如何getshell详解

总结

到此这篇关于thinkphp诸多限制条件下如何getshell详解的文章就介绍到这了,更多相关tp诸多限制条件下getshell内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
判“新”函数:得到今天与明天的秒数
Oct 09 PHP
用PHP和ACCESS写聊天室(七)
Oct 09 PHP
PHP sprintf()函数用例解析
May 18 PHP
php中批量修改文件后缀名的函数代码
Oct 23 PHP
如何利用PHP执行.SQL文件
Jul 05 PHP
PHP中使用glob函数实现一句话删除某个目录下的所有文件
Jul 22 PHP
PHP使用array_merge重新排列数组下标的方法
Jul 22 PHP
Yii中的cookie的发送和读取
Jul 27 PHP
php实现的http请求封装示例
Nov 08 PHP
php技巧小结【推荐】
Jan 19 PHP
laravel实现按月或天或小时统计mysql数据的方法
Oct 09 PHP
Yii 框架控制器创建使用及控制器响应操作示例
Oct 14 PHP
HTTP头隐藏PHP版本号实现过程解析
Dec 09 #PHP
PhpStorm连接服务器并实现自动上传功能
Dec 09 #PHP
PHP大文件分割分片上传实现代码
Dec 09 #PHP
PHP rsa加密解密算法原理解析
Dec 09 #PHP
PHP如何解决微信文章图片防盗链
Dec 09 #PHP
PHP sdk文档处理常用代码示例解析
Dec 09 #PHP
PHP sdk实现在线打包代码示例
Dec 09 #PHP
You might like
php array_search() 函数使用
2010/04/13 PHP
php Ubb代码编辑器函数代码
2012/07/05 PHP
PHP获取本周第一天和最后一天示例代码
2014/02/24 PHP
laravel 5异常错误:FatalErrorException in Handler.php line 38的解决
2017/10/12 PHP
Yii框架 session 数据库存储操作方法示例
2019/11/18 PHP
兼容主流浏览器的JS复制内容到剪贴板
2014/12/12 Javascript
JavaScript修改浏览器tab标题小技巧
2015/01/06 Javascript
深入浅析search 搜索框的写法
2016/08/02 Javascript
使用bootstrap-paginator.js 分页来进行ajax 异步分页请求示例
2017/03/09 Javascript
vue拦截器Vue.http.interceptors.push使用详解
2017/04/22 Javascript
angular.fromJson与toJson方法用法示例
2017/05/17 Javascript
Vuex利用state保存新闻数据实例
2017/06/28 Javascript
使用InstantClick.js让页面提前加载200ms
2017/09/12 Javascript
vue mounted 调用两次的完美解决办法
2018/10/29 Javascript
jQuery插件实现非常实用的tab栏切换功能【案例】
2019/02/18 jQuery
html2canvas属性和使用方法以及如何使用html2canvas将HTML内容写入Canvas生成图片
2020/01/12 Javascript
微信小程序返回上一级页面的实现代码
2020/06/19 Javascript
Python pass 语句使用示例
2014/03/11 Python
解决Python中由于logging模块误用导致的内存泄露
2015/04/23 Python
python按综合、销量排序抓取100页的淘宝商品列表信息
2018/02/24 Python
python实现随机漫步算法
2018/08/27 Python
Python实现的企业粉丝抽奖功能示例
2019/07/26 Python
Python Request爬取seo.chinaz.com百度权重网站的查询结果过程解析
2019/08/13 Python
面向对象学习之pygame坦克大战
2019/09/11 Python
Python利用pip安装tar.gz格式的离线资源包
2020/09/14 Python
对pytorch中x = x.view(x.size(0), -1) 的理解说明
2021/03/03 Python
天猫精选:上天猫,就够了
2016/09/21 全球购物
在校生党员自我评价
2013/09/25 职场文书
医药专业应届毕业生求职信范文
2014/01/01 职场文书
中学生期末评语
2014/02/03 职场文书
自强之星事迹材料
2014/05/12 职场文书
求职教师自荐书
2014/06/19 职场文书
三好学生竞选稿
2015/11/21 职场文书
php字符串倒叙
2021/04/01 PHP
pytorch 如何把图像数据集进行划分成train,test和val
2021/05/31 Python
基于Redis zSet实现滑动窗口对短信进行防刷限流的问题
2022/02/12 Redis