欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[漏洞复现]thinkphp3.2_find_select_delete

程序员文章站 2022-03-24 14:15:06
...

个人博客地址

http://www.darkerbox.com

欢迎大家学习交流

参考网址:

https://xz.aliyun.com/t/2629#toc-3

环境:

链接:https://pan.baidu.com/s/1DyHy1Z-IPhPFzQC_mEIZeQ 
提取码:8vxn 

漏洞概述

如何搭建环境我就不细说了,可以参照参考网址里的步骤搭建。
还需要phpstorm配合xdebug调试,网上教程很多,不多介绍了。

漏洞利用

搭建好环境后,直接上payload,测试是否正常。我本地搭建到了8083端口

http://127.0.0.1:8083/index.php?m=Home&c=Index&a=test&id[table]=users%20where%201%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--

[漏洞复现]thinkphp3.2_find_select_delete
测试成功!!

当然没那么简单,看看到底是如何成功的。。

首先我们需要知道参数是怎么传进去的。
看到url,就可以知道参数传给了index.php

[漏洞复现]thinkphp3.2_find_select_delete
但是index.php只有短短的20几行代码,只有一个地方包含了一个名为ThinkPHP/ThinkPHP.php的文件,找到这个文件。

thinkphp文件有100行了,但大多数行都是定义常量。只有两行比较重要

[漏洞复现]thinkphp3.2_find_select_delete
加载了一个核心类文件。
加载完这个类文件后,直接调用了这个类的静态方法start()
这个方法也是加载了一些配置文件,定义了类的自动加载等

[漏洞复现]thinkphp3.2_find_select_delete
核心还是在App::run();这一行,运行应用。
[漏洞复现]thinkphp3.2_find_select_delete

但是这个文件没有包含其他文件,这个App类怎么来的呢?上面刚说过定义了类的自动加载,不了解php的类的自动加载先去了解一下再回来接着看,不过影响不大。

通过下断点或者通过看类的自动加载函数都可以找到App这个类文件。

Think类和App类都在thinkphp3.2.3\ThinkPHP\Library\Think目录下,名字叫think.class.php和app.class.php。

找到App类后,再找到App的静态方法:run(),这个方法也是执行了一些初始化工作。此时我打开了调试器。

[漏洞复现]thinkphp3.2_find_select_delete
我先跟进了App:init()函数,在第app.class.php的38行继续跟进dispatch方法,

[漏洞复现]thinkphp3.2_find_select_delete

到了dispatcher.class.php文件中的地24行

[漏洞复现]thinkphp3.2_find_select_delete
这里调用了一个C函数。跟进一下发现该函数在functions.php中,$_config应该保存了些全局变量,因为$_config里有121个元素

[漏洞复现]thinkphp3.2_find_select_delete
[漏洞复现]thinkphp3.2_find_select_delete
依次执行完,我发现$varModule,$varController,$varAction和我们的url传的参数一一对应,但现在还不确定就是一样的。

[漏洞复现]thinkphp3.2_find_select_delete
继续往下走,到了第140行,获取模块名称,看到后面的self::getModule($varModule)

[漏洞复现]thinkphp3.2_find_select_delete
跟进这个静态方法。发现这里$_GET[$var],即$_GET[‘m’]获取了参数m的值。即Home。

[漏洞复现]thinkphp3.2_find_select_delete

然后define('MODULE_NAME', defined('BIND_MODULE')? BIND_MODULE : self::getModule($varModule));将获取到的m的参数值定义为常量。

之后检测这个模块是否存在。不存在则会报错。
之后到了第239和240行,可以看到,这里将$_GET['c']和$_GET['a']分别定义为常量CONTROLLER_NAME,ACTION_NAME

[漏洞复现]thinkphp3.2_find_select_delete

到这里,已经获取到了三个参数的值,分别为m,c,a。并且都赋值给了常量。

然后执行到返回,跳出这个方法,后面是全局安全过滤。

[漏洞复现]thinkphp3.2_find_select_delete
至此App:init()也执行完了。

[漏洞复现]thinkphp3.2_find_select_delete

在App.class.php的第208行执行了exec方法。主方法
跟进这个方法
[漏洞复现]thinkphp3.2_find_select_delete

刚进去就安全检测参数CONTROLLER_NAME了,因为没检测到,所以直接跳转到后面的else语句,创建控制器实例,传了了两个参数,第一个是控制器名字,即c参数的值,即index。第二个参数是空。这个index其实就是IndexController.class.php中的的index。他会自动找到这个文件。

[漏洞复现]thinkphp3.2_find_select_delete
在110行调用了invokeAction方法,并传了一个moduleIndexController.class.phpIndexControllermodule,这个变量是一个对象,即上图中的控制器实例,也就是`IndexController.class.php中的IndexController对象`。action即我们的a参数的值,跟进。
[漏洞复现]thinkphp3.2_find_select_delete

[漏洞复现]thinkphp3.2_find_select_delete
在127行实例化了ReflectionMethod对象,这个是php的类,具体作用我也解释不清楚。

[漏洞复现]thinkphp3.2_find_select_delete

继续来到177行,这里的$method即ReflectionMethod对象,moudleIndexController,moudle是`IndexController`对象,action即参数a的值,即test。这行代码的作用就是调用了$moudle的test方法。跟进test方法

[漏洞复现]thinkphp3.2_find_select_delete
就是我们自己定义的test方法。
[漏洞复现]thinkphp3.2_find_select_delete
函数i在functions.php中,作用是自动获取参数值。作用即$_GET[‘id’],因为我们传入的id是一个数组,所以这里的$id也是一个数组。第十一行的users其实是表名,M(‘users’)会返回一个实例化后的model,保存的有数据库连接信息,可以查询数据。

[漏洞复现]thinkphp3.2_find_select_delete
接着又调用了find方法。漏洞在这,可以看到$options是我们的$id,即$options是可控的,传一个数组,绕过了第一个判断,至于为什么要绕过这个判断,后面会说。主要是为了绕过\$options['where'] = $where;(个人理解)。

[漏洞复现]thinkphp3.2_find_select_delete

在第730行,获取表的主键,只要这个表的主键是一个,则$pk是字符串,如果是两个,则$pk是数组,如果主键是一个,则也会绕过第二个if的判断,因为is_array($pk)是false。

[漏洞复现]thinkphp3.2_find_select_delete
之后进入了第751行的_parseOptions方法

[漏洞复现]thinkphp3.2_find_select_delete

[漏洞复现]thinkphp3.2_find_select_delete
因为$options中没有where元素(上面已经绕过了),所以绕过了这个判断,之后返回。

[漏洞复现]thinkphp3.2_find_select_delete
此时的$options如下图
[漏洞复现]thinkphp3.2_find_select_delete
接着来到762行,跟进select函数

[漏洞复现]thinkphp3.2_find_select_delete
到了这里也就接近尾声了。

public function select($options=array()) {
        $this->model  =   $options['model'];//获取model,其实就是表名
        $this->parseBind(!empty($options['bind'])?$options['bind']:array());//参数绑定
        $sql    = $this->buildSelectSql($options);//构造sql语句
        $result   = $this->query($sql,!empty($options['fetch_sql']) ? true : false);//执行查询,返回结果,这里就已经将报错输出了。
        return $result;
    }

[漏洞复现]thinkphp3.2_find_select_delete

不具体分析了,文中可能不对的地方有点多,刚学习,望见谅,如果哪里不对,可以到评论区评论,我会及时改正,谢谢

欢迎大家一起学习交流,共同进步,欢迎加入信息安全小白群

[漏洞复现]thinkphp3.2_find_select_delete

相关标签: 漏洞复现