إنتقل إلى المحتوى الرئيسي

كشف متعددي الصيغ

كيف يحدد باطن الملفات الصالحة في صيغ متعددة في نفس الوقت.

ما هو ملف متعدد الصيغ؟​

متعدد الصيغ (من اليونانية "كثير الألسنة") هو ملف:

  1. صالح عند تفسيره كصيغة A
  2. صالح أيضاً عند تفسيره كصيغة B
  3. قد يتصرف بشكل مختلف في كل سياق

لماذا متعددو الصيغ خطيرون​

سيناريو الهجوم: تجاوز البريد الإلكتروني​

لماذا هذا يعمل​

  1. ماسحات البريد تفحص البداية - ترى %PDF
  2. Windows يفحص المحتوى الفعلي - يجد رأس MZ بالداخل
  3. أدوات مختلفة، تفسيرات مختلفة

التوليفات الشائعة لمتعددي الصيغ​

الأساسيالثانويناقل الهجوم
PDFEXEالبريد الإلكتروني، تحميلات الويب
PNGHTMLXSS الويب، استضافة الصور
GIFJavaScriptXSS المبني على الصور
ZIPJARاستغلال Java

PDF + EXE (الأكثر شيوعاً)​

+----------------------------------+
| %PDF-1.4 | <- رأس PDF
| ...كائنات PDF... |
| MZ | <- رأس PE (مضمن)
| ...كود تنفيذي... |
| %%EOF | <- ذيل PDF
+----------------------------------+

قارئات PDF تتوقف عند %%EOF. Windows يجد MZ وينفذ.


خوارزمية الكشف​

pub fn detect_polyglot(data: &[u8], db: &SignatureDatabase) -> Result<Vec<String>> {
let mut detected_formats = Vec::new();

// فحص مواقع متعددة للتوقيعات
let check_offsets = [0, 512, 1024, 2048];

for offset in check_offsets {
if offset >= data.len() {
break;
}

let slice = &data[offset..];
let matches = db.match_signatures(slice);

for (sig_idx, _confidence) in matches {
let sig = &db.signatures[sig_idx];
let format = sig.extensions[0].clone();

if !detected_formats.contains(&format) {
detected_formats.push(format);
}
}
}

// حالة خاصة: PDF مع PE مضمن
if data.starts_with(b"%PDF") {
if let Some(pe_pos) = find_bytes(data, &[0x4D, 0x5A]) {
if pe_pos > 100 { // ليس في البداية (مضمن)
detected_formats.push("exe".to_string());
}
}
}

Ok(detected_formats)
}

تأثير مستوى التهديد​

fn assess_threat(...) -> ThreatLevel {
// متعدد الصيغ = دائماً خطير
if detected_formats.len() > 1 {
return ThreatLevel::Dangerous;
}

// ... فحوصات أخرى ...
}

المبرر:

  • الملفات الشرعية ليست أبداً متعددة الصيغ
  • أي ملف متعدد الصيغ يجب فحصه
  • أفضل أن نحذر زيادة من أن نفقد هجوماً

استراتيجيات الدفاع​

1. رفض متعددي الصيغ​

async fn validate_upload(data: &[u8]) -> Result<(), &'static str> {
let config = DetectionConfig::default();
let result = FileType::from_bytes(data, &config)?;

if result.detected_formats.len() > 1 {
log::error!("رُفض متعدد الصيغ: {:?}", result.detected_formats);
return Err("ملفات متعددة الصيغ غير مسموحة");
}

Ok(())
}

2. فرض نوع المحتوى​

fn validate_claimed_type(data: &[u8], claimed: &str) -> bool {
let config = DetectionConfig::default();
let result = FileType::from_bytes(data, &config).ok()?;

// رفض إذا متعدد الصيغ
if result.detected_formats.len() > 1 {
return false;
}

// رفض إذا النوع المكتشف لا يتطابق مع المدعى
result.extension == claimed
}

ملاحظة أمنية

ملفات متعددي الصيغ مشبوهة بطبيعتها. بينما توجد بعض الحالات الشرعية، أي ملف يُكتشف كصيغ متعددة يجب:

  1. تسجيله
  2. عزله أو حظره
  3. مراجعته يدوياً قبل السماح

في حالة الشك، ارفض.