
Defensive Analyse, Patch-Aufschlüsselung und Erkennungsscanner für CVE-2026-14378 (WordPress DevKit Pro Plugin <= 2.3.0).
CVE-2026-14378 ist eine kritische Unauthentifizierte Authentifizierungsumgehung (CVSS 9.8) im DevKit Pro-Plugin für WordPress, die alle Versionen bis einschließlich 2.3.0 betrifft.
Das Plugin enthält einen Entwickler-Benutzerwechselmechanismus. Wenn ein Administrator zu einem anderen Benutzerkonto „wechselt", speichert es die ID des Administrators in einem Cookie namens original_user_id. Der Fehler: Das Plugin rendert ein „Zurückwechseln"-HTML-Formular auf jeder Seite, sobald dieses Cookie vorhanden ist — auch für unauthentifizierte Besucher, die das Cookie manuell setzen. Schlimmer noch: Der Nonce-Verifizierungsschritt prüft die Administratorberechtigung des Cookie-Benutzers, nicht die Sitzung des Aufrufers — daher gibt der Server bereitwillig ein authentifiziertes Administrator-Sitzungscookie an jeden heraus, der den richtigen POST sendet.
Nettoergebnis: Null Anmeldedaten erforderlich für die vollständige Übernahme der WordPress-Administration.
| Attribut | Details |
|---|---|
| CVE-ID | CVE-2026-14378 |
| Schwachstellenklasse | Unsachgemäße Authentifizierung (CWE-287) |
| CVSS v3.1 Score | 9.8 (Kritisch) |
| CVSS-Vektor | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Betroffene Software | DevKit Pro (dplugins) WordPress-Plugin |
| Verwundbare Versionen | <= 2.3.0 |
| Gepatchte Version | 2.3.1 |
| Veröffentlichungsdatum | 02. Okt. 2026 |
DevKit Pro enthält einen Entwickler-Helfer, der es Website-Administratoren ermöglicht, in andere Benutzerkonten zu „wechseln", um Berechtigungen zu testen. Wenn der Administrator den Wechsel verwendet:
Set-Cookie: original_user_id=1isset($_COOKIE['original_user_id'])wp_footer() mit einem versteckten POST-Formular, das ein frisches Nonce enthältadmin-post.php?action=revert_switchwp_set_auth_cookie($user_id) auf, um die ursprüngliche Sitzung wiederherzustellenDer wp_footer-Hook-Handler:
// DevKit Pro <= 2.3.0 — render_switch_back_bar()
public function render_switch_back_bar() {
// FLAW: Only checks if cookie exists — no session validation!
if ( isset( $_COOKIE['original_user_id'] ) ) {
$user_id = (int) $_COOKIE['original_user_id'];
$nonce = wp_create_nonce( 'devkit_revert_switch_' . $user_id );
echo '<div id="devkit-pro-switch-back" class="devkit-switch-bar" style="display:none;">';
echo ' <form id="devkit-revert-form" action="' . admin_url('admin-post.php') . '" method="POST">';
echo ' <input type="hidden" name="action" value="revert_switch" />';
echo ' <input type="hidden" name="_wpnonce" value="' . $nonce . '" />';
echo ' <input type="hidden" name="target_user_id" value="' . $user_id . '" />';
echo ' </form>';
echo '</div>';
echo '<!-- DevKit Pro 2.3.0 Switch Component Active -->';
}
}
Der POST-Handler, der die Formularübermittlung verarbeitet:
// DevKit Pro <= 2.3.0 — handle_revert_switch()
public function handle_revert_switch() {
$user_id = (int) $_POST['target_user_id'];
$nonce = sanitize_text_field( $_POST['_wpnonce'] );
if ( ! $this->verify_nonce_and_capability( $user_id, $nonce ) ) {
wp_die( 'Unauthorized' );
}
wp_set_current_user( $user_id );
wp_set_auth_cookie( $user_id ); // <-- Grants authenticated session to caller
wp_redirect( admin_url() );
exit;
}
private function verify_nonce_and_capability( $user_id, $nonce ) {
if ( ! wp_verify_nonce( $nonce, 'devkit_revert_switch_' . $user_id ) ) {
return false;
}
// CRITICAL FLAW: Checks the cookie user's capability, not the caller's!
return user_can( $user_id, 'manage_options' );
}
user_can( $user_id, 'manage_options' ) beantwortet die Frage: „Hat Benutzer #1 die Berechtigung manage_options?“
Die Antwort für Benutzer #1 (den zuerst erstellten WordPress-Administrator) ist immer true.
Es sollte stattdessen fragen: „Hat die Person, die diese HTTP-Anfrage stellt, die Berechtigung manage_options?“
Die korrekte Prüfung ist current_user_can('manage_options'), die für einen nicht authentifizierten Besucher false zurückgeben würde.
Diese gesamte Analyse wurde durchgeführt und verifiziert gegen eine live laufende WordPress-Instanz in einem lokalen Podman-Container (http://localhost:8080) mit aktivem DevKit Pro 2.3.0.
Um dies lokal zu reproduzieren, benötigen Sie:
Schnelle Podman-Lab-Einrichtung:
# Start MariaDB
podman run -d --name wp-db \
-e MYSQL_ROOT_PASSWORD=rootpass \
-e MYSQL_DATABASE=wordpress \
-e MYSQL_USER=wpuser \
-e MYSQL_PASSWORD=wppass \
mariadb:10.6
# Start WordPress
podman run -d --name wp-app \
-p 8080:80 \
--link wp-db:mysql \
-e WORDPRESS_DB_HOST=mysql \
-e WORDPRESS_DB_NAME=wordpress \
-e WORDPRESS_DB_USER=wpuser \
-e WORDPRESS_DB_PASSWORD=wppass \
wordpress:latest