كيف يمكنني تحديد التمديد الحقيقي/النوع للملف برمجيًا؟

StackOverflow https://stackoverflow.com/questions/481743

سؤال

أنا أعمل على برنامج نصي يقوم بمعالجة تحميلات المستخدم على الخادم ، وكطبقة إضافية من الأمان ، أود أن أعرف:

هل هناك طريقة لاكتشاف نوع التمديد/الملف الحقيقي للملف ، والتأكد من أنه ليس نوع ملف آخر ملثمين بامتداد مختلف؟

هل هناك ختم بايت أو معرف فريد لكل نوع/امتداد؟

أود أن أكون قادرًا على اكتشاف أن شخصًا ما لم يطبق امتدادًا مختلفًا على الملف الذي يقومون بتحميله.

شكرًا لك،

هل كانت مفيدة؟

المحلول

لا حقا لا.

ستحتاج إلى قراءة البايتات القليلة الأولى من كل ملف وتفسيرها كرأس لمجموعة محدودة من الأنواع المعروفة. تحتوي معظم الملفات على رؤوس ملفات مميزة ، ونوع من البيانات الوصفية في البايتات القليلة الأولى أو القليلة الأولى من الكيلوغرامات في حالة MP3.

سيتعين على برنامجك ببساطة محاولة تحليل الملف لكل من أنواع filetypes المقبولة.

بالنسبة لبرنامجي ، أرسل الصورة التي تم تحميلها إلى ImageMagick في كتلة التجربة ، وإذا كانت تفجر ، فأعتقد أنها كانت صورة سيئة. يجب اعتبار ذلك غير آمن ، لأنني أقوم بتحميل البيانات الثنائية التعسفية (التي يتم توفيرها) في برنامج خارجي ، وهو ناقل هجوم بشكل عام. هنا ، أنا أثق في ImageMagick بعدم فعل أي شيء لنظامي.

أوصي بكتابة المعالجات الخاصة بك لنوعية كبيرة تنوي استخدامها ، لتجنب أي متجهات هجوم.

تحرير: أرى في PHP هناك بعض الأدوات للقيام بذلك نيابة عنك.

أيضا ، أنواع MIME هي ما يدعي متصفح المستخدم الملف ليكون. من المفيد ومفيدة قراءة هؤلاء والتصرف عليها في الكود الخاص بك ، ولكنها ليست طريقة آمنة ، لأن أي شخص يرسل لك ملفات سيئة سوف يزيف رؤوس MIME بسهولة. إنه نوع من الدفاع عن خط المواجهة للحفاظ على رمزك الذي يتوقع JPEG من Barfing على بابوا نيو غينيا ، ولكن إذا قام شخص ما بتضمين فيروس في .exe وأطلق عليه اسم JPEG ، فلا يوجد سبب لعدم تعرض نوع MIME.

نصائح أخرى

لدى PHP عدة طرق لقراءة محتويات الملفات لتحديد نوع MIME ، اعتمادًا على إصدار PHP الذي تستخدمه:

ألق نظرة على وظائف FileInfo إذا كنت تقوم بتشغيل PHP 5.3+

$finfo = finfo_open(FILEINFO_MIME); 
$type = finfo_file($finfo, $filepath);
finfo_close($finfo);  

بدلاً من ذلك ، تحقق من mime_content_type للإصدارات القديمة.

$type = mime_content_type($filepath);

لاحظ أن مجرد التحقق من صحة نوع الملف لا يكفي إذا كنت تريد أن تكون آمنًا حقًا. يمكن لشخص ما ، على سبيل المثال ، تحميل ملف JPEG صالح يستغل ثغرة في العارض المشترك. للحماية من هذا ، ستحتاج إلى ماسح ضوئي للفيروسات.

PHP لديه superglobal $ _files الذي يحمل معلومات مثل الحجم ونوع الملف. يبدو أن النوع يتم أخذه من نوع من الرأس ، وليس امتدادًا ، لكنني قد أكون مخطئًا.

هناك مثال على ذلك موقع W3Schools.

سأختبر ما إذا كان يمكن خداع ذلك عندما أحصل على فرصة.

تحديث:

ربما يعرف الجميع هذا ، ولكن يمكن خداع $ _files. تمكنت من تحديد ذلك بهذه الطريقة:

$arg = escapeshellarg( $_FILES["file"]["tmp_name"] );
system( "file $arg", $type );
echo "Real type:  " . $type;

إنه يستخدم بشكل أساسي UNIX ملف يأمر. ربما تكون هناك طرق أفضل ، لكنني لم أستخدم PHP منذ فترة. عادةً ما أتجنب استخدام أوامر النظام إن أمكن.

هذا لا يزال مزورة. أود أن أتأكد من أنه لا يمكنك (أو لا) تشغيل ملف تم تحميله على الخادم تلقائيًا.

سيكون لدي أيضا ملف الماسح الضوئي في الفيروس/التجسس, ، ودعه يقوم بالعمل من أجلك.

يمكنك استخدام الكود أدناه الذي يمنحك نوع التمرير إذا قمت بتغيير الامتداد ثم أيضًا

$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo $mime = finfo_file($finfo, $_FILES['userfile']['tmp_name']);
finfo_close($finfo);

مستخدمو Windows: فقط قم بتحرير php.ini و unflemment هذا السطر:

extension=php_fileinfo.dll

تذكر إعادة تشغيل Apache من أجل php.ini الجديد ليصبح ساري المفعول.

في *nix ، تخبرك الأولين بايت للملف (انظر "الرقم السحري"). في Windows ، ... في بعض الأحيان سيكون هذا صحيحًا ("معلومات الرأس"). إنه ، في نهاية المطاف ، يعتمد على نظام التشغيل.

لدى التنفيذيين بشكل عام "توقيع" على البايتات الأولى ؛ أجد أنه من الصعب على الرغم من التأكد حقًا من نوع الملف حقًا.

ما أنواع الملفات التي تتوقعها؟ ربما يمكنك التحقق من أنه يتوافق مع ما تتوقعه ويرفض كل شيء آخر.

لقد ذكر آخرون بالفعل FileInfo ، وهو ما أعتقد أنه الحل الصحيح ، لكنني سأضيف هذا فقط في حال لم تتمكن من استخدام ذلك لسبب ما. معظم (الكل؟) *تشمل توزيعات NIX أمر يسمى file أنه عند تشغيل ملف سوف يخرج نوعه. يحتوي على مفتاح للإخراج بتنسيق قابل للقراءة البشرية (افتراضي) أو نوع MIME. يمكن أن تستعيد البرنامج النصي الخاص بك هذا البرنامج على الملف الذي تم تحميله وقراءة النتيجة. مرة أخرى ، هذا ليس هو النهج المفضل. إذا كنت على Windows ، فإن هذه الأداة متاحة من خلال Cygwin.

هل التحقق من نوع MIME ببساطة بما فيه الكفاية؟ أفترض أن تغيير الامتداد على ملف لا يغير نوع MIME؟

هل نوع MIME مؤشر قوي بما فيه الكفاية للذهاب هنا؟

شكرا لجميع الردود حتى الآن.

هل التحقق من نوع MIME ببساطة بما فيه الكفاية؟ أفترض أن تغيير الامتداد على ملف لا يغير نوع MIME؟ هل نوع MIME مؤشر قوي بما فيه الكفاية للذهاب هنا؟

يعتمد الأمر حقًا على كيفية استخدامه.

  • إذا قمت بتقديم عمليات تحميل وتنزيلات ، فلا شيء مهم لأنه لا يتم تنفيذه.
  • إذا تمت معالجته بواسطة خادم الويب ، فسيعتمد ذلك على كيفية تكوين خادم الويب ، على الرغم من أنه يخضع لمعظم هذه التعليقات.
  • إذا كانت صورة ، فسيتم عرضها إما ، أو لا ، أو تكون هدف مآثر مكتبة الصور. لكن هؤلاء فقط.
  • قد لا يؤثر شيء مثل ملف PDF على الخادم الخاص بك ، بل هو كمبيوتر الشخص الذي يصل إلى الملف.
  • إذا تم تمريرها إلى وظيفة مثل "System ()" ، فسنعود إلى سلوك نظام التشغيل-كما لو كان "ينقر نقرًا مزدوجًا" ، وقد يتم النظر في تمديد الملف.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top