Intent ที่รอดำเนินการ

หมวดหมู่ OWASP: MASVS-PLATFORM: การโต้ตอบกับแพลตฟอร์ม

ภาพรวม

PendingIntent คือการอ้างอิงถึงโทเค็นที่ระบบดูแล แอปพลิเคชัน A สามารถส่ง PendingIntent ไปยังแอปพลิเคชัน B เพื่ออนุญาตให้แอปพลิเคชัน B ดำเนินการที่กำหนดไว้ล่วงหน้าในนามของแอปพลิเคชัน A ได้ ไม่ว่าแอปพลิเคชัน A จะยังทำงานอยู่หรือไม่ก็ตาม

ความเสี่ยง: PendingIntent ที่เปลี่ยนแปลงได้

PendingIntent สามารถเปลี่ยนแปลงได้ ซึ่งหมายความว่าแอปพลิเคชัน B สามารถอัปเดต Intent ภายในที่ระบุการดำเนินการได้ตามตรรกะที่อธิบายไว้ในเอกสารประกอบ fillIn() กล่าวคือ แอปที่เป็นอันตรายสามารถแก้ไขช่องที่ไม่ได้กรอกของ PendingIntent และอนุญาตให้เข้าถึงคอมโพเนนต์ที่ไม่ได้ส่งออกของแอปพลิเคชันที่มีช่องโหว่ได้

ผลกระทบ

ผลกระทบจากช่องโหว่นี้จะแตกต่างกันไปตามการใช้งานฟังก์ชันที่ไม่ได้ส่งออกของแอปที่เป็นเป้าหมาย

การลดปัญหา

ทั่วไป

ตรวจสอบว่าได้ตั้งค่าการดำเนินการ คอมโพเนนต์ และแพ็กเกจแล้วเพื่อหลีกเลี่ยงช่องโหว่ที่ร้ายแรงที่สุด

Kotlin

val intent = Intent(intentAction)

// Or other component setting APIs e.g. setComponent, setClass
intent.setClassName(packageName, className)

PendingIntent pendingIntent =
    PendingIntent.getActivity(
        context,
        /* requestCode = */ 0,
        intent, /* flags = */ PendingIntent.FLAG_IMMUTABLE
    )

Java

Intent intent = new Intent(intentAction);

// Or other component setting APIs e.g. setComponent, setClass
intent.setClassName(packageName, className);

PendingIntent pendingIntent =
        PendingIntent.getActivity(
            getContext(),
            /* requestCode= */ 0,
            intent, /* flags= */ 0);

Flag IMMUTABLE

หากแอปกำหนดเป้าหมายเป็น Android 6 (ระดับ API 23) ขึ้นไป ให้ระบุความสามารถในการเปลี่ยนแปลงได้ เช่น ทำได้โดยใช้ FLAG_IMMUTABLE เพื่อป้องกันไม่ให้แอปพลิเคชันที่เป็นอันตรายกรอกข้อมูลในช่องที่ไม่ได้กรอก

Kotlin

val pendingIntent =
    PendingIntent.getActivity(
        context,
        /* requestCode = */ 0,
        Intent(intentAction),
        PendingIntent.FLAG_IMMUTABLE)

Java

PendingIntent pendingIntent =
        PendingIntent.getActivity(
            getContext(),
            /* requestCode= */ 0,
            new Intent(intentAction),
            PendingIntent.FLAG_IMMUTABLE);

ใน Android 11 (ระดับ API 30) ขึ้นไป คุณต้องระบุช่องที่จะทำให้เปลี่ยนแปลงได้ ซึ่งจะช่วยลดช่องโหว่โดยไม่ตั้งใจประเภทนี้

แหล่งข้อมูล


ความเสี่ยง: การเล่น Intent ที่รอดำเนินการซ้ำ

เล่น PendingIntent ซ้ำได้ เว้นแต่จะตั้งค่าแฟล็ก FLAG_ONE_SHOT คุณควรใช้ FLAG_ONE_SHOT เพื่อหลีกเลี่ยงการโจมตีแบบเล่นซ้ำ (การดำเนินการที่ไม่ควรทำซ้ำ)

ผลกระทบ

ผลกระทบจากช่องโหว่นี้จะแตกต่างกันไปตามการใช้งานปลายทางที่รับ Intent แอปที่เป็นอันตรายซึ่งใช้ประโยชน์จาก PendingIntent ที่สร้างขึ้นโดยไม่ได้ตั้งค่า FLAG_ONE_SHOT อาจดักจับและนำ Intent กลับมาใช้ซ้ำเพื่อทำซ้ำการดำเนินการที่ควรทำได้เพียงครั้งเดียว

การลดปัญหา

PendingIntent ที่ไม่ได้มีไว้เพื่อเรียกใช้หลายครั้งควรใช้แฟล็ก FLAG_ONE_SHOT เพื่อหลีกเลี่ยงการโจมตีแบบรีเพลย์

Kotlin

val pendingIntent =
      PendingIntent.getActivity(
          context,
          /* requestCode = */ 0,
          Intent(intentAction),
          PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_ONE_SHOT)

Java

PendingIntent pendingIntent =
        PendingIntent.getActivity(
            getContext(),
            /* requestCode= */ 0,
            new Intent(intentAction),
            PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);

แหล่งข้อมูล


แหล่งข้อมูล