دسته OWASP: MASVS-PLATFORM: تعامل پلتفرم
نمای کلی
تغییر مسیر هدف زمانی رخ میدهد که یک مهاجم بتواند تا حدی یا به طور کامل محتوای یک هدف مورد استفاده برای راهاندازی یک مؤلفه جدید در چارچوب یک برنامه آسیبپذیر را کنترل کند.
هدفی که برای راهاندازی مؤلفه جدید استفاده میشود، میتواند به روشهای مختلفی ارائه شود، که معمولاً یا به صورت یک هدف سریالی در یک فیلد extras یا به صورت یک رشته مرتب شده و تجزیه میشود. کنترل جزئی پارامترها نیز میتواند به همان نتیجه منجر شود.
تأثیر
تأثیر میتواند متفاوت باشد. یک مهاجم ممکن است ویژگیهای داخلی را در برنامه آسیبپذیر اجرا کند، یا ممکن است به اجزای خصوصی مانند اشیاء ContentProvider صادر نشده دسترسی پیدا کند.
کاهشها
به طور کلی، ویژگیهای مربوط به تغییر مسیر intent های تو در تو را افشا نکنید. در مواردی که اجتنابناپذیر است، روشهای کاهش خطر زیر را اعمال کنید:
- اطلاعات بستهبندیشده را به درستی پاکسازی کنید. مهم است که به یاد داشته باشید پرچمهای (
FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION, FLAG_GRANT_PERSISTABLE_URI_PERMISSION, and FLAG_GRANT_PREFIX_URI_PERMISSION) را بررسی یا پاک کنید و بررسی کنید که intent به کجا هدایت میشود.IntentSanitizerمیتواند در این فرآیند کمک کند. - از اشیاء
PendingIntentاستفاده کنید. این کار از export شدن کامپوننت شما جلوگیری میکند و action intent هدف را تغییرناپذیر میسازد.
برنامهها میتوانند با استفاده از متدهایی مانند ResolveActivity بررسی کنند که یک intent به کجا هدایت میشود:
کاتلین
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)
}
جاوا
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 استفاده کنند:
کاتلین
val intent = IntentSanitizer.Builder()
.allowComponent("com.example.ActivityA")
.allowData("com.example")
.allowType("text/plain")
.build()
.sanitizeByThrowing(intent)
جاوا
Intent intent = new IntentSanitizer.Builder()
.allowComponent("com.example.ActivityA")
.allowData("com.example")
.allowType("text/plain")
.build()
.sanitizeByThrowing(intent);
محافظت پیشفرض
اندروید ۱۶ یک راهکار امنیتی پیشفرض برای مقابله با سوءاستفادههای تغییر مسیر Intent معرفی میکند. در بیشتر موارد، برنامههایی که معمولاً از Intentها استفاده میکنند، هیچ مشکل سازگاری را تجربه نخواهند کرد.
انصراف از مدیریت تغییر مسیر Intent
اندروید ۱۶ یک API جدید معرفی میکند که به برنامهها اجازه میدهد از محافظتهای امنیتی هنگام راهاندازی صرفنظر کنند. این ممکن است در موارد خاصی که رفتار امنیتی پیشفرض با موارد استفاده مشروع برنامه تداخل دارد، ضروری باشد.
در اندروید ۱۶، میتوانید با استفاده از متد removeLaunchSecurityProtection() در شیء Intent ، از محافظتهای امنیتی انصراف دهید. برای مثال:
val i = intent
val iSublevel: Intent? = i.getParcelableExtra("sub_intent")
iSublevel?.removeLaunchSecurityProtection() // Opt out from hardening
iSublevel?.let { startActivity(it) }
اشتباهات رایج
- بررسی اینکه آیا
getCallingActivity()مقداری غیر از null برمیگرداند یا خیر. برنامههای مخرب میتوانند برای این تابع مقدار null ارائه دهند. - با فرض اینکه
checkCallingPermission()در همه زمینهها کار میکند، یا اینکه این متد وقتی واقعاً یک عدد صحیح برمیگرداند، یک استثنا ایجاد میکند.
ویژگیهای اشکالزدایی
برای برنامههایی که اندروید ۱۲ (سطح API 31) یا بالاتر را هدف قرار میدهند، میتوانید یک ویژگی اشکالزدایی را فعال کنید که در برخی موارد به شما کمک میکند تشخیص دهید که آیا برنامه شما در حال اجرای ناامن یک intent است یا خیر.
اگر برنامه شما هر دو اقدام زیر را انجام دهد، سیستم اجرای یک intent ناامن را تشخیص میدهد و نقض StrictMode رخ میدهد:
- برنامه شما یک intent تو در تو را از موارد اضافی یک intent تحویل داده شده جدا میکند.
- برنامه شما بلافاصله با استفاده از آن intent تو در تو، مانند ارسال intent به
startActivity()،startService()یاbindService()یک کامپوننت برنامه را اجرا میکند.