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 相关文章推荐
[转帖]PHP世纪万年历
Dec 06 PHP
PHP语法速查表
Jan 02 PHP
php中使用临时表查询数据的一个例子
Feb 03 PHP
php批量上传的实现代码
Jun 09 PHP
PHP读取文件内容后清空文件示例代码
Mar 18 PHP
PHP+jQuery 注册模块开发详解
Oct 14 PHP
Yii基于CActiveForm的Ajax数据验证用法示例
Jul 14 PHP
PHP高效获取远程图片尺寸和大小的实现方法
Oct 20 PHP
Laravel框架实现定时Task Scheduling例子
Oct 22 PHP
laravel框架中控制器的创建和使用方法分析
Nov 23 PHP
PHP使用PDO实现mysql防注入功能详解
Dec 20 PHP
php连接mysql之mysql_connect()与mysqli_connect()的区别
Jul 19 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下用GD生成生成缩略图的两个选择和区别
2007/04/17 PHP
PHP之APC缓存详细介绍 apc模块安装
2014/01/13 PHP
将二维数组转为一维数组的2种方法
2014/05/26 PHP
php管理nginx虚拟主机shell脚本实例
2014/11/19 PHP
php5.3不能连接mssql数据库的解决方法
2014/12/27 PHP
PHP获取网页所有连接的方法(附demo源码下载)
2016/03/30 PHP
详解phpstorm2020最新破解方法
2020/09/17 PHP
prototype 中文参数乱码解决方案
2009/11/09 Javascript
jQuery源码解读之hasClass()方法分析
2015/02/20 Javascript
JavaScript中的函数(二)
2015/12/23 Javascript
jquery实用技巧之输入框提示语句
2016/07/28 Javascript
JavaScript &amp; jQuery完美判断图片是否加载完毕
2017/01/08 Javascript
webpack配置的最佳实践分享
2017/04/21 Javascript
bootstrap表单示例代码分享
2017/05/18 Javascript
vue2.x集成百度UEditor富文本编辑器的方法
2018/09/21 Javascript
vue实现压缩图片预览并上传功能(promise封装)
2019/01/10 Javascript
JavaScript常用内置对象用法分析
2019/07/09 Javascript
jquery ui 实现 tab标签功能示例【测试可用】
2019/07/25 jQuery
微信小程序仿今日头条导航栏滚动解析
2019/08/20 Javascript
vuex存值与取值的实例
2019/11/06 Javascript
Vue自动构建发布脚本的方法示例
2020/07/24 Javascript
js通过canvas生成图片缩略图
2020/10/02 Javascript
python实现得到一个给定类的虚函数
2014/09/28 Python
python使用7z解压apk包的方法
2015/04/18 Python
Python 基础之字符串string详解及实例
2017/04/01 Python
Pycharm 创建 Django admin 用户名和密码的实例
2018/05/30 Python
python如何保证输入键入数字的方法
2019/08/23 Python
python离线安装外部依赖包的实现
2020/02/13 Python
HomeAway的巴西品牌:Alugue Temporada
2018/04/10 全球购物
工业自动化专业毕业生推荐信
2013/11/18 职场文书
市场营销专业求职信
2014/06/17 职场文书
小学雷锋月活动总结
2014/07/03 职场文书
常务副县长“四风”个人对照检查材料思想汇报
2014/10/02 职场文书
绍兴鲁迅故居导游词
2015/02/09 职场文书
js之ajax文件上传
2021/05/13 Javascript
小程序wx.getUserProfile接口的具体使用
2021/06/02 Javascript