چرا mail() در PHP خطرناک است ؟

اخیرا آسیب پذیری هایی در سایت های ثبت کننده اکسپلویت در مضمون استفاده نا امن از تابع mail() در php به ثبت رسیده است. اما واقعا چرا mail() در PHP خطرناک است ؟

در این پست به بررسی آسیب پذیری موجود و نحوه ی ایمن سازی آن ها می پردازیم.

به عنوان مثال در CVE-2016-9920 می توانید آسیب پذیری RCE (Remote Command Execution) را مشاهده کنید.

که به نفوذگر یا هکر اجازه می دهد دستورات خود را از راه دور ، صرفاً با نوشتن یک ایمیل از طریق رابط Roundcube  بر روی سرور تارگت (Target) اجرا نماید.

تابع mail() در PHP

همانطور که می دانید با استفاده از تابع mail() در PHP می توانید ایمیل ارسال کنید. این تابع به وسیله ۵ پارامتر پیکربندی و مقداردهی می شود :

bool mail( string $to, string $subject, string $message [, string $additional_headers [, string $additional_parameters ]] )

۳ پارامتر اول mail() اجباری (required) ، و ۲ پارامتر آخر آن اختیاری (Optional) می باشند.

۳ پارامتر اول حساسیت کمتری دارند زیرا تحت تاثیر حملات تزریق (injection) قرار نمی گیرند.

البته به این نکته نیز باید توجه داشته باشید که اگر پارامتر $to در اختیار کاربر باشد می تواند ایمیل های اسپم را وارد کند.

چرا mail() در PHP خطرناک است ؟ | حملات تزریق هدر ایمیل ( Email header injection )

پارامتر چهارم تابع mail() یک رشته را دریافت می کند که در آن می توان هدر را مشخص کرد.

از آنجا که هدرهای پست با مشخصه  CRLF  \ r \ n5 از هم جدا می شوند ،

یک هکر می تواند از این مشخصه ها برای افزودن هدر ایمیل های اضافی در هنگام استفاده از ورودی کاربر در پارامتر چهارم ، استفاده کند.

این حمله با عنوان Email Header Injection ( تزریق ایمیل کوتاه) شناخته شده است.

با ارسال چندین آدرس ایمیل به یک CC هدر تزریق شده : یا BCC: هدر می توانید از ارسال چندین ایمیل اسپم استفاده کنید.

توجه داشته باشید که برخی از برنامه های پستی \ n to \ r \ n را به طور خودکار جایگزین می کنند.

چرا mail() در PHP خطرناک است ؟ | پارامتر پنجم

برای استفاده از تابع mail() و ارسال ایمیل ، ابتدا باید تنظیمات SMTP Server را پیکربندی کنید.

زمانی که PHP با پارامتر دوم پیکربندی می شود، تابع mail() پیکربندی های MTA (Mail Transfer Agent) را صدا می زند.

اگر چه PHP به صورت پیشفرض با استفاده از تابع escapeshellcmd() روی پارامتر ۵ فیلترینگ اعمال می کند،

اما آرگومان ۵  اجازه می دهد تا آرگومان های برنامه جدید را به MTA اضافه کنید.

بنابراین ، یک نفوذگر می تواند پرچم (flag) های برنامه را اضافه کند که در برخی از MTA ایجاد فایل با محتوای کنترل شده توسط کاربر امکان پذیر می باشد.

mail("iran123@example.com", "subject", "message", "", "-f" . $_GET['from']);

هکر می تواند در پارامتر $_GET دستورات خود را از راه دور اجرا و پارامتر های اضافی را به برنامه ارسال کند.

به عنوان مثال با استفاده از پارامتر -O در ارسال ایمیل می توان برای پیکربندی مجدد و با پارامتر -X مکان لاگ فایل را تعیین کرد.

حالا زمانی که سیستم های مدیریت محتوا (CMS) مانند وردپرس و جوملا از این کتابخانه ها استفاده می کنند، اهمیت این آسیب پذیری افزایش می یابد.

که به صورت کاملا مفصل و پروژه محور در دوره ی امنیت در وردپرس و امنیت در جوملا تدریس شده است.

چرا تابع escapeshellarg() ایمن نیست ؟

در پاسخ به سوال چرا mail() در PHP خطرناک است لازم است این تابع را نیز بررسی کنیم.

در PHP جهت فیلترینگ و کنترل اجرای دستورت سیستمی دو تابع escapeshellcmd() و escapeshellarg() را وجود دارد. کد زیر به ظاهر ایمن به نظر می رسد :

system(escapeshellcmd("./program -param1 ". escapeshellarg( $_GET['arg'] )));

در حالی که با پیلود زیر و پارامتر های دیگر می توان آن را بایپس (Bypass) کرد :

./program -param1 'foobar'\\'' -param2 payload \'

تابع mail() به صورت اتوماتیک از تابع escapeshellcmd() در پارامتر پنجم استفاده می کند.

چرا FILTER_VALIDATE_EMAIL ایمن نیست ؟

یکی دیگر از راه های کسب اطیمنان از معتبر بودن ایمیل ، استفاده از تابع فیلترینگ filter_var($email, FILTER_VALIDATE_EMAIL) در پارامتر پنجم است.

اما می توان از فضای خالی و سفید بین کوتیشن ها استفاده و ادرس ایمیل مخرب را وارد کرد :

'a."'\ -OQueueDirectory=\%0D<?=eval($_GET[c])?>\ -X/var/www/html/"@a.php

چگونه از تابع mail() به صورت ایمن تر استفاده کنیم ؟

تا اینجا به این سوال پرداختیم که چرا mail() در PHP خطرناک است ، حالا باید در مورد ایمن سازی آن صحبت کنیم.

از آنجایی که هیچ وقت امنیت صد در صد نیست،  پس نمی توان روشی صد در صد مطمئن را نیز استفاده کرد.

اما می شود سورس را تا حد بالایی ایمن نگه داشت.

  • پارامتر اول ($to) : ورودی کاربر مستقیما ارسال نشود و حتما فیلتر شود.
  • پارامتر چهارم : همه کاراکترهای \ r  و \ n حذف شوند.
  • پارامتر پنجم : از ورودی کاربر در این قسمت استفاده نشود.
  • پارامتر دوم و سوم نیز نیازی به فیلترینگ ندارند.

علاوه بر اینکه چرا mail() در PHP خطرناک است می توانید شیوه ی برنامه نویسی ایمن PHP را در دوره ی های کشف باگ و تحلیل باگ فرابگیرید.

تحلیل باگ و امنیت در PHP | انالیز باگ

ارسال دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *