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应用提速面面观
Oct 09 PHP
php下用GD生成生成缩略图的两个选择和区别
Apr 17 PHP
PHPMyadmin 配置文件详解(配置)
Dec 03 PHP
让PHP支持断点续传的源码
May 16 PHP
PHP 八种基本的数据类型小结
Jun 01 PHP
PHP 使用MySQL管理Session的回调函数详解
Jun 21 PHP
使用PHP和HTML5 FormData实现无刷新文件上传教程
Sep 06 PHP
ci检测是ajax还是页面post提交数据的方法
Nov 10 PHP
laravel学习教程之存取器
Jul 30 PHP
PHP实现多关键字加亮功能
Oct 21 PHP
PHP实现二维数组去重功能示例
Jan 12 PHP
PHP高精确度运算BC函数库实例详解
Aug 15 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
浅析Mysql 数据回滚错误的解决方法
2013/08/05 PHP
基于preg_match_all采集后数据处理的一点心得笔记(编码转换和正则匹配)
2014/01/31 PHP
PHP获取时间排除周六、周日的两个方法
2014/06/30 PHP
CI框架实现优化文件上传及多文件上传的方法
2017/01/04 PHP
详谈symfony window下的安装 安装时候出现的问题以及解决方法
2017/09/28 PHP
php实现解析xml并生成sql语句的方法
2018/02/03 PHP
浅析PHP 中move_uploaded_file 上传中文文件名失败
2019/04/17 PHP
PHP设计模式(一)工厂模式Factory实例详解【创建型】
2020/05/02 PHP
javascript中的location用法简单介绍
2007/03/07 Javascript
JavaScript flash复制库类 Zero Clipboard
2011/01/17 Javascript
JavaScript 继承使用分析
2011/05/12 Javascript
原生javascript获取元素样式
2014/12/31 Javascript
全面解析bootstrap格子布局
2016/05/22 Javascript
JS实现表单多文件上传样式美化支持选中文件后删除相关项
2016/09/30 Javascript
js利用appendChild对标签进行排序的实现方法
2016/10/16 Javascript
javascript 使用正则test( )第一次是 true,第二次是false
2017/02/22 Javascript
前端自动化开发之Node.js的环境搭建教程
2017/04/01 Javascript
在JS中如何把毫秒转换成规定的日期时间格式实例
2017/05/11 Javascript
jQuery实现遍历XML节点和属性的方法示例
2018/04/29 jQuery
详解如何从零开始搭建Express+Vue开发环境
2018/07/17 Javascript
React中使用UEditor百度富文本的方法
2018/08/22 Javascript
详解vue如何使用rules对表单字段进行校验
2018/10/17 Javascript
通过扫小程序码实现网站登陆功能
2019/08/22 Javascript
vue-video-player实现实时视频播放方式(监控设备-rtmp流)
2020/08/10 Javascript
Python多进程同步Lock、Semaphore、Event实例
2014/11/21 Python
Django的分页器实例(paginator)
2017/12/01 Python
pycharm下查看python的变量类型和变量内容的方法
2018/06/26 Python
pytorch中的weight-initilzation用法
2020/06/24 Python
世界上获奖最多的手机镜头:Olloclip
2018/03/03 全球购物
《风娃娃》教学反思
2014/04/19 职场文书
选秀节目策划方案
2014/06/06 职场文书
2014年团支书工作总结
2014/11/14 职场文书
《分数乘法》教学反思
2016/02/24 职场文书
Anaconda安装pytorch及配置PyCharm 2021环境
2021/06/04 Python
Python torch.flatten()函数案例详解
2021/08/30 Python
浅谈为什么我的 z-index 又不生效了
2022/07/15 HTML / CSS