PDA

View Full Version : فایلهای آپلودی، MIME type sniffing، و حفرهء امنیتی



eshpilen
چهارشنبه 14 تیر 1391, 17:21 عصر
قبلا در تاپیک دیگری (http://forum.iranphp.org/Thread-%D9%85%D8%B4%DA%A9%D9%84-%D8%AF%D8%B1-%D9%86%D8%A7%D9%85%DA%AF%D8%B0%D8%A7%D8%B1%DB%8C-%D9%81%D8%A7%DB%8C%D9%84%D9%87%D8%A7%DB%8C-%D8%B9%DA%A9%D8%B3-%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%D8%A7%D9%86-%D8%AF%D8%B1-%D8%B3%D8%A7%DB%8C%D8%AA) درمورد اینکه آیا باید نسبت به محتویات فایلهای آپلودی، و نه تنها پسوند اونها، حساس بود بحث کرده بودیم و کسی نمونه و دلیلی براش ارائه نداده بود.

این چند روزه مطالبی رو مطالعه کردم که به این موضوع ربط دارن.

قضیه از این قرار است که بازهم IE، این مرورگر معروف به دردسرسازی و ناامنی در طول تاریخ، یک ویژگی خاصی داره که باعث ایجاد حفرهء امنیتی میشه.

البته این مشکل در نسخه های قدیمی مثل IE6 وجود داشته و کشف شده، اما با توجه به تستهای بنده، ظاهرا هنوز حتی روی IE7 و IE8 هم ولو به شکل محدودتر این مشکل وجود داره.

بنده چون IE8 داشتم فقط تونستم روی نسخهء 8 تست کنم. یکسری حالات ممکنه روی نسخهء 8 امن باشن ولی روی نسخهء 6 یا 7 امن نباشن. هرکس داره میتونه تست کنه و نتیجه رو بگه.

مثال - یک فایل php یا txt در www ایجاد کنید و این کد رو توش بذارید:


<?php header('Content-Type: text/plain'); ?>
<html>
<body>
<script>alert('XSS');</script>
</body>
</html>

بعد اون رو در IE باز کنید.
مشاهده میکنید که کد جاوااسکریپت ما اجرا میشه.
چون IE محتویات فایل رو بعنوان HTML شناسایی و اجرا میکنه، حتی با وجود اینکه ما با هدر Content-Type: text/plain بهش گفتیم که باید محتویات پاسخ رو بعنوان متن ساده درنظر بگیره.

چرا IE این کار رو میکنه؟
چیزهایی در منابع گفته شده بود که ظاهرا این قضیه به آپاچی هم ارتباط داره و تاریخچه ای هست. ظاهرا آپاچی بصورت پیشفرض کانفیگ درستی نداشته و بنابراین زیاد پیش میامده که نوع فایل با هدرهای ارسال شده تطابق نداشته. بعد IE اومده خواسته هوشمندبازی دربیاره و بجای اینکه خطا بده یا محتویات رو خراب نمایش بده، خودش نوع دیتا رو از روی محتویاتش تشخیص بده و اونها رو بر اساس تشخیص/حدس خودش تفسیر و اجرا کنه؛ احتمالا بخاطر اینکه یوزرفرندلی تر باشه.

البته خوشبختانه این جریان فعلا فقط روی فایلهای txt اینطور خطرناک عمل میکنه. چون بنده هدر کد مثال بالا رو image/jpg گذاشتم یا از پسوند jpg استفاده کردم، که در هر دو حالت کد جاوااسکریپت اجرا نشد. ولی شاید مثلا روی IE6 یا IE7 اجرا بشه (هرکس IE6 یا 7 داره میتونه تست کنه و نتیجه رو بگه).

البته فکر میکنم در بیشتر سیستمهای آپلود پسوند txt جزو پسوندهای مجاز نیست. بنابراین شاید مشکل جدی ای وجود نداشته باشه و اصلا نیازی به چک کردن محتویات فایل نباشه. ولی بازم مطمئن نیستم و برای اطمینان احتمالا باید بیشتر فکر و تحقیق و تست کنیم. IE6 هم که الان دیگه رسما منسوخ شده تلقی میشه، ولی از طرف دیگه هنوز عده ای از کاربران ازش استفاده میکنن (بخصوص با توجه به اینکه با ویندوز XP نصب میشه).
حالا من الان خسته هستم و همین تست و مطالب رو هم به زور تونستم تموم کنم که الان بفرستم. بعدا میتونیم بیشتر روش بررسی کنیم.

ضمنا این یک حمله به کلاینت بود با استفاده از باگ مرورگر. فکر میکنم در بحثهای قبلی بیشتر متوجه خطر این فایلها در سمت سرور بودیم تا کلاینت.

eshpilen
چهارشنبه 14 تیر 1391, 17:21 عصر
وای وای! وضع IE7 خرابه.
یک فایل بنام test.jpg در www ایجاد کنید و کدهای HTML+Javascript رو درش ذخیره کنید.
وقتی در IE7 آدرس test.jpg رو بصورت مستقیم میدی (http://localhost/test.jpg) کدها رو اجرا میکنه.
واقعا افتضاحه!!

ayub_coder
چهارشنبه 14 تیر 1391, 20:03 عصر
تو نسخه 6 و 7 اجرا میشه ولی تو 8 اجرا نمیشه. توی کروم و فایرفاکس هم اجرا نمیشه.
مایم تایپ ها هم قابل جعل هستن. و فقط از روی مایم تایپ نباید اجازه ی آپلود و اجرای فایل ها رو بدیم.

colors
پنج شنبه 27 مهر 1391, 01:05 صبح
سلام

کسی برای این مشکل راه حلی نداره؟ در کل باید چکار کرد؟

eshpilen
پنج شنبه 27 مهر 1391, 13:39 عصر
راههای مختلفی رو پیشنهاد کرده بودن که دقیقا یادم نیست.
یکیش فکر کنم عبور دادن فایلها از کتابخانه های پردازش کنندهء اونا بود.
مثلا فایلهای تصویری رو با توابع GD بخونید و دوباره سیو کنید.
اما فکر نمیکنم فقط یک روش به تنهایی کافی باشه. احتمالا برای اطمینان بیشتر باید از چند روش همزمان استفاده کرد. نکات متعددی هست که باید درنظر داشت.
بین اینا فکر میکنم همون پردازش با توابع کتابخانه ای امنیت خوبی (نه 100%) داشته باشه، ولی مطمئن نیستم. ضمنا بهرحال احتمالا پردازش زیادی هم مصرف میکنه، اما اگر برای امنیت راه دیگری نداشته باشیم مجبوریم انجامش بدیم (*).

*: یک چیزی در جایی چند وقت پیش دیدم که بهش Polyglot گفته میشد. Polyglot ها در برنامه نویسی به دیتایی میگن که همزمان در بیش از یک فرمت معتبر باشه. مثلا دیتایی که هم بعنوان دیتای یک فرمت تصویری بتونه تفسیر بشه و خطای سینتاکس نداشته باشه و هم بعنوان کدمنبع یک زبان برنامه نویسی. فکر نکنید همچنین چیزی نمیشه! میشه! منتها درست کردنش برای فرمتهای تصویری پیشرفته و دارای فشرده سازی مثل jpg و gif و اینها کار راحتی نیست و شاید در بعضی موارد غیرممکن باشه. من خودم یک Polyglot که همزمان هم یک فایل تصویری هست و هم سورس کد PHP معتبر رو براحتی ساخته بودم قبلا (و هر کد PHP هم که بخواید میشه توش قرار داد - درواقع اصلا هر کدی از هر زبانی رو میشه درش قرار داد!). منتها با یک فرمت تصویری بسیار ساده این کار رو کرده بودم (با فرمت wbmp اگر درست یادم باشه)؛ فایل بدست آمده از توابع GD هم بدون هیچ تغییری در کدهای PHP داخلش عبور میکرد. با فرمتهای تصویری پیچیده اگر این کار رو بخوایم بکنیم باید اطلاعات و مهارت کامل نسبت به جزییات اون فرمت و الگوریتم های فشرده سازی بکار رفته داشته باشیم.

بنابراین شاید برای اطمینان بیشتر لازم باشه توی محتویات فایل رو هم برای کدهای جاوااسکریپت (یا اگر لازم باشه برای PHP هم) جستجو کنید. ولی خود این مسئلهء ساده ای نیست و پیچیدگی و راههای دور زدن خودش رو میتونه داشته باشه.
کلا این داستان واقعا پیچیده و مشکلی هست.
همش هم تقصیر IE.
بنظر من اصلا باید IE رو تحریم کنیم!!
چطور بعضی سایتها اونم دولتی و سایت دانشگاه مینویسن که فقط از مرورگر IE استفاده شود! بنظر من بعکس باید بنویسن/بنویسیم از مرورگر IE استفاده نشود!! یعنی اصلا اول مرورگر رو چک کنیم اگر IE بود اجازهء اجرا ندیم، چون خطر امنیتی داره. اگر IE اینقدر آمار نداشت میشد باید همین کار رو میکردیم باهاش.

البته این بحث Polyglot که گفتم رو زیاد هم وحشت نکنید. چون کار هرکسی نیست و دقیقا معلوم هم نیست شدنی باشه یا نباشه و تا چه حدی. حداقل فعلا فکر نمیکنم در دنیا جز افراد معدودی کسی بلد باشه. ولی ممکنه در آینده حتی برنامش بیاد که هرکس بتونه همچین فایلهایی درست کنه!!

خلاصه من نمیدونم از دست IE باید چه کنیم. سر به بیابان بذاریم.

حالا خودتون جستجو کنید منابع رو پیدا کنید و جزییات و روشهای دیگری رو که لازمه بخونید.
من که وقت ندارم الان دوباره اون مطالب تکراری رو پیدا و مطالعه کنم و براتون بگم.
در آینده اگر خواستم سیستم آپلودی چیزی بنویسم میرم سراغش. فعلا دارم روی سیستم رجیستر و لاگین خودم کار میکنم که از این چیزا نداره.

colors
پنج شنبه 27 مهر 1391, 14:23 عصر
مثلا فایلهای تصویری رو با توابع GD بخونید و دوباره سیو کنید.

به نظرتون چطوره یه محدودیت فرمت داشته باشیم مثلا هر فرمتی که آپلود میشه اونو با استفاده از همین توابع DG به jpg یا ... تبدیل کنیم. در حال حاظر تو این پروژه ای که دارم اینو روندو واسش پیش گرفتم تا حداقل یکمی بشه امنیت اونرو تامین کرد.

نظرتون چیه عرض و ارتفاع تصویر آپلود شده روهم بررسی کنیم. مطمئنا یه فایل text عرض و ارتفاع نداره! داره؟ :لبخند: البته نمیدونم میشه با کد عرض و ا رتفاع رو جعل کرد یا نه.


بنظر من اصلا باید IE رو تحریم کنیم!!
والا فکر خوبیه ولی کو گوش شنوا...
البته اگه بخوایم مردمو به سمت مرورگرهای پیشرفته و جدید ببریم مطمئنا خیلی از این شرکتهای گردن کلفت ایران مث راهبر و ... 100٪ ورشکسته میشن :قهقهه:


من که وقت ندارم الان دوباره اون مطالب تکراری رو پیدا و مطالعه کنم و براتون بگم.
چرا انقدر بد اخلاق!! (شوخی)

colors
پنج شنبه 27 مهر 1391, 14:41 عصر
نظرتون چیه عرض و ارتفاع تصویر آپلود شده روهم بررسی کنیم. مطمئنا یه فایل text عرض و ارتفاع نداره! داره؟

ظاهرا اینم نمیشه.

زماني كه فقط به تصاوير اجازه آپلود داده شود، توسعه دهندگان معمولا هدر تصوير را توسط تابع PHP (getimagesize) اعتبارسنجي مي كنند. با فراخواني اين تابع، اندازه تصوير برگردانده مي شود. اگر اعتبارسنجي تصوير، نامعتبر باشد به اين معني است: هدر نامعتبر است و تابع false برمي گرداند. بنابراين، توسعه دهنده مي تواند true يا false بودن را چك نموده و اعتبارسنجي فايل آپلود شده را با استفاده از اين اطلاعات انجام دهد. بنابراين، اگر كاربر مهاجم سعي كند يك فايل ساده php shell كه در يك فايل jpg تعبيه شده را آپلود نمايد، تابع false برگردانده و اجازه آپلود داده نمي شود ولي حتي از اين روش هم مي توان عبور كرد. با باز نمودن تصوير در يك اديتور تصوير مانند Gimp، بخش comment آن قابل ويرايش بوده، مي توان كد PHP در آن قرار داد. لذا تصوير داراي هدر معتبر بوده و مي تواند از چك تابع getimagesize عبور كند. وقتي درخواست گرفتن تصوير از مروگر وب داده شود، كد PHP اجرا مي شود.
یکی از دوستان تو دنیای پارسی (http://www.forum.parsiworld.ir/showthread.php?p=283) زده.

عجب! خیلی جالبه همین مطلب رو تو 10 تا سایت دیگه پیدا کردم از جمله سایت آقای کرامتی فر که هیچکدومشون منبعی ذکر نکردن؟..!

Unique
جمعه 28 مهر 1391, 01:46 صبح
سریعترین راه نسبت به getimagesize و فکر کنم از اون هم بهتر استفاده از تابع exif_imagetype هستش ، این تابع دقیقا بهتون میگه فایلتون چه نوع عکسی هست ! اگرچه میشه باز هم fake کرد اما خوب کاچی ... /;)