Chuyển hướng ý định

Danh mục OWASP: MASVS-PLATFORM: Tương tác với nền tảng

Tổng quan

Chuyển hướng ý định xảy ra khi kẻ tấn công có thể kiểm soát một phần hoặc toàn bộ nội dung của ý định dùng để chạy một thành phần mới trong bối cảnh một ứng dụng dễ bị tấn công.

Bạn có thể cung cấp ý định dùng để chạy thành phần mới theo nhiều cách, thường là ý định chuyển đổi tuần tự trong trường extras hoặc kết hợp với một chuỗi và được phân tích cú pháp. Việc kiểm soát một phần các tham số cũng có thể dẫn đến kết quả tương tự.

Tác động

Mức độ tác động có thể khác nhau. Kẻ tấn công có thể thực thi chức năng nội bộ trong ứng dụng dễ bị tấn công hoặc có thể truy cập vào các thành phần riêng tư như đối tượng ContentProvider chưa xuất.

Giải pháp giảm thiểu

Chung

Nhìn chung, đừng cung cấp chức năng liên quan đến việc chuyển hướng ý định lồng nhau. Trong trường hợp không thể tránh khỏi, hãy áp dụng các phương pháp giảm thiểu sau đây:

  • Dọn dẹp thông tin đi kèm đúng cách. Bạn cần nhớ kiểm tra hoặc xoá cờ (GRANT_URI_PERMISSIONS) và kiểm tra vị trí mà ý định đang được chuyển hướng. IntentSanitizer có thể giúp bạn thực hiện quy trình này.
  • Sử dụng đối tượng PendingIntent. Điều này ngăn việc xuất thành phần và làm cho ý định của hành động mục tiêu không thể thay đổi được.

Các ứng dụng có thể kiểm tra vị trí mà một ý định đang được chuyển hướng bằng các phương thức như 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);
}

Các ứng dụng có thể dùng IntentSanitizer theo logic tương tự như sau:

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);

Lỗi thường gặp

  • Kiểm tra xem getCallingActivity() có trả về một giá trị không rỗng hay không. Các ứng dụng độc hại có thể cung cấp giá trị rỗng cho hàm này.
  • Cho rằng checkCallingPermission() hoạt động trong mọi ngữ cảnh hoặc rằng phương thức này đưa ra ngoại lệ khi thực sự trả về một số nguyên.

Các tính năng gỡ lỗi

Đối với các ứng dụng nhắm mục tiêu Android 12 (API cấp 31) trở lên, bạn có thể bật tính năng gỡ lỗi để, trong một số trường hợp, giúp bạn phát hiện xem ứng dụng có đang khởi chạy một ý định theo cách không an toàn hay không.

Nếu ứng dụng thực hiện cả hai hành động sau đây, thì hệ thống sẽ phát hiện một lượt khởi chạy ý định theo cách không an toàn và một lỗi vi phạm StrictMode xảy ra:

  • Ứng dụng của bạn sẽ tách các ý định lồng nhau khỏi các thành phần đi kèm của ý định đã phân phối.
  • Ứng dụng sẽ bắt đầu ngay một thành phần ứng dụng bằng cách dùng ý định lồng nhau đó, chẳng hạn như chuyển ý định đến startActivity(), startService() hoặc bindService().

Tài nguyên