إعادة توجيه intent

فئة OWASP: MASVS-PLATFORM: Platform Interaction (التفاعل مع النظام الأساسي)

نظرة عامة

تحدث إعادة توجيه النية عندما يتمكّن المهاجم من التحكّم جزئيًا أو كليًا في محتويات نية مستخدَمة لتشغيل مكوّن جديد في سياق تطبيق متوفّر فيه ثغرة أمنية.

يمكن تقديم النية المستخدَمة لإطلاق المكوّن الجديد بعدة طرق، ويكون الأكثر شيوعًا إما نية مُسلسلة في حقل extras أو نية تم تجميعها في سلسلة وتحليلها. يمكن أن يؤدي التحكّم الجزئي في المَعلمات أيضًا إلى النتيجة نفسها.

التأثير

وقد يختلف التأثير. يمكن للمهاجم تنفيذ ميزات داخلية في التطبيق المعرض للاختراق، أو يمكنه الوصول إلى مكوّنات خاصة مثل عناصر ContentProvider التي لم يتم تصديرها.

إجراءات التخفيف

بشكل عام، لا تعرض الميزات ذات الصلة بإعادة توجيه النوايا المُدمَجة. في الحالات التي لا يمكن فيها تجنُّب استخدام هذه التقنيات، يُرجى اتّباع طرق التخفيف التالية:

  • إزالة البيانات غير المرغوب فيها من الحِزمة بشكل صحيح من المهم التحقق من العلامات أو إزالتها (FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION, FLAG_GRANT_PERSISTABLE_URI_PERMISSION, and FLAG_GRANT_PREFIX_URI_PERMISSION)، والتحقّق من مكان إعادة توجيه الطلب. يمكن أن يساعد IntentSanitizer في هذه العملية.
  • استخدِم عناصر PendingIntent. ويؤدي ذلك إلى منع تصدير المكوّن ويجعل نية الإجراء المستهدَف غير قابلة للتغيير.

يمكن للتطبيقات التحقّق من المكان الذي تتم إعادة توجيه النية إليه باستخدام طرق مثل methods ResolveActivity:

Kotlin

val intent = getIntent()
// Get the component name of the nested intent.
val forward = intent.getParcelableExtra<Parcelable>("key") as Intent
val name: ComponentName = forward.resolveActivity(packageManager)
// Check that the package name and class name contain the expected values.
if (name.packagename == "safe_package" && name.className == "safe_class") {
    // Redirect the nested intent.
    startActivity(forward)
}

Java

Intent intent = getIntent()
// Get the component name of the nested intent.
Intent forward = (Intent) intent.getParcelableExtra("key");
ComponentName name = forward.resolveActivity(getPackageManager());
// Check that the package name and class name contain the expected values.
if (name.getPackageName().equals("safe_package") &&
        name.getClassName().equals("safe_class")) {
    // Redirect the nested intent.
    startActivity(forward);
}

يمكن للتطبيقات استخدام IntentSanitizer باستخدام منطق مشابه مما يلي:

Kotlin

val intent = IntentSanitizer.Builder()
     .allowComponent("com.example.ActivityA")
     .allowData("com.example")
     .allowType("text/plain")
     .build()
     .sanitizeByThrowing(intent)

Java

Intent intent = new  IntentSanitizer.Builder()
     .allowComponent("com.example.ActivityA")
     .allowData("com.example")
     .allowType("text/plain")
     .build()
     .sanitizeByThrowing(intent);

أخطاء شائعة

  • التحقّق مما إذا كانت getCallingActivity() تعرِض قيمة غير فارغة يمكن أن توفر التطبيقات الضارة قيمة فارغة لهذه الدالة.
  • بافتراض أنّ checkCallingPermission() تعمل في جميع السياقات، أو أنّ المحاولة تُعرِض استثناءً عندما تُعيد في الواقع عددًا صحيحًا.

ميزات تصحيح الأخطاء

بالنسبة إلى التطبيقات التي تستهدف الإصدار 12 من نظام التشغيل Android (المستوى 31 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث، يمكنك تفعيل ميزة تصحيح الأخطاء التي تساعدك في بعض الحالات في رصد ما إذا كان تطبيقك يؤدي إلى بدء عملية غير آمنة لطلب.

إذا نفَّذ تطبيقك كلا الإجراءَين التاليَين، يرصد النظام بدء تشغيل نية غير آمنة، وتحدث مخالفة StrictMode:

  • يُفكّ تطبيقك حزمة هدف مُدمَج من البيانات الإضافية لهدف تم إرساله.
  • يبدأ تطبيقك على الفور أحد مكوّنات التطبيق باستخدام هذا الإجراء المُدمَج، مثل تمرير الإجراء إلى startActivity() أو startService() أو bindService().

المراجع