L3HCTF部分web题复现
best-profile 先看代码,问题在这部分 @app.route("/ip_detail/<string:username>", methods=["GET"]) def route_ip_detail(username): res = requests.get(f"http://127.0.0.1/get_last_ip/{username}") if res.status_code != 200: return "Get last ip failed." last_ip = res.text try: ip = re.findall(r"\d+\.\d+\.\d+\.\d+", last_ip) country = geoip2_reader.country(ip) except (ValueError, TypeError): country = "Unknown" template = f""" <h1>IP Detail</h1> <div>{last_ip}</div> <p>Country:{country}</p> """ return render_template_string(template) 经典的ssti模板注入,在比赛的时候一直尝试 甚至都怀疑到了是否能绕过string:username,走目录遍历,结果是nginx的缓存投毒,在做题的时候我甚至都没去注意这个文件 location ~ .*\.(js|css)?$ { proxy_ignore_headers Cache-Control Expires Vary Set-Cookie; proxy_pass http://127.0.0.1:5000; proxy_cache static; proxy_cache_valid 200 302 12h; } 特殊后缀proxy_cache static开启了缓存,因为用户注册时并没有限制特殊字符,则我们可以通过构建类似与test.js 的用户名来访问/get_last_ip/ 欺骗缓存,这样服务器通过 requests.get 访问即使没有cookie也会返回缓存数据 构建用户 ...