สิทธิ์ที่กำหนดเอง

หมวดหมู่ OWASP: MASVS-CODE: คุณภาพโค้ด

ภาพรวม

ความเสี่ยงที่เกี่ยวข้องกับสิทธิ์ที่กำหนดเองจะปรากฏขึ้นเมื่อคําจํากัดความสิทธิ์ที่กําหนดเองขาดหายไปหรือสะกดผิด หรือเมื่อมีการละเมิดการใช้แอตทริบิวต์ android:protectionLevel ที่เกี่ยวข้องในไฟล์ Manifest

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

สิทธิ์ที่กำหนดเองออกแบบมาเพื่อแชร์ทรัพยากรและความสามารถกับแอปอื่นๆ ตัวอย่างการใช้สิทธิ์ที่กำหนดเองอย่างถูกต้อง ได้แก่

  • การควบคุมการสื่อสารระหว่างกระบวนการ (IPC) ระหว่างแอป 2 แอปขึ้นไป
  • การเข้าถึงบริการของบุคคลที่สาม
  • การจํากัดการเข้าถึงข้อมูลที่แชร์ของแอป

ผลกระทบ

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

ความเสี่ยง: การพิมพ์ผิดในสิทธิ์ที่กำหนดเอง

มีการประกาศสิทธิ์ที่กำหนดเองในไฟล์ Manifest แต่มีการใช้สิทธิ์ที่กำหนดเองอื่นเพื่อปกป้องคอมโพเนนต์ Android ที่ส่งออก เนื่องจากมีการพิมพ์ผิด แอปพลิเคชันที่เป็นอันตรายอาจใช้ประโยชน์จากแอปพลิเคชันที่สะกดสิทธิ์ไม่ถูกต้องได้ ดังนี้

  • ลงทะเบียนสิทธิ์ดังกล่าวก่อน
  • คาดคะเนการสะกดคำในการใช้งานครั้งต่อๆ ไป

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

เช่น แอปที่มีช่องโหว่ต้องการปกป้องคอมโพเนนต์โดยใช้สิทธิ์ READ_CONTACTS แต่สะกดสิทธิ์ดังกล่าวเป็น READ_CONACTS โดยไม่ได้ตั้งใจ แอปที่เป็นอันตรายสามารถอ้างสิทธิ์ READ_CONACTS ได้เนื่องจากแอปพลิเคชันใดๆ (หรือระบบ) ไม่ได้เป็นเจ้าของแอปดังกล่าว และสามารถเข้าถึงคอมโพเนนต์ที่ได้รับการปกป้อง อีกรูปแบบที่พบบ่อยของช่องโหว่นี้คือ android:permission=True ค่า เช่น true และ false ไม่ว่าจะขึ้นต้นด้วยอักษรตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็ก จะเป็นอินพุตที่ไม่ถูกต้องสำหรับการประกาศสิทธิ์และจะได้รับการจัดการในลักษณะเดียวกับการพิมพ์ผิดอื่นๆ ในการประกาศสิทธิ์ที่กำหนดเอง วิธีแก้ไขคือ ให้เปลี่ยนค่าของแอตทริบิวต์ android:permission เป็นสตริงสิทธิ์ที่ถูกต้อง เช่น หากแอปจำเป็นต้องเข้าถึงรายชื่อติดต่อของผู้ใช้ ค่าของแอตทริบิวต์ android:permission ควรเป็น android.permission.READ_CONTACTS

การลดปัญหา

การตรวจสอบ Lint ของ Android

เมื่อประกาศสิทธิ์ที่กําหนดเอง ให้ใช้การตรวจสอบ Lint ของ Android เพื่อช่วยค้นหาการพิมพ์ผิดและข้อผิดพลาดอื่นๆ ที่อาจเกิดขึ้นในโค้ด

รูปแบบการตั้งชื่อ

ใช้รูปแบบการตั้งชื่อที่สอดคล้องกันเพื่อให้สังเกตการพิมพ์ผิดได้ง่ายขึ้น ตรวจสอบการประกาศสิทธิ์ที่กำหนดเองในไฟล์ Manifest ของแอปอย่างละเอียดเพื่อหาคำที่พิมพ์ผิด


ความเสี่ยง: สิทธิ์ที่ไม่มีเจ้าของ

สิทธิ์ใช้เพื่อปกป้องทรัพยากรของแอป แอปสามารถประกาศสิทธิ์ที่จําเป็นสําหรับการเข้าถึงแหล่งข้อมูลได้ 2 แห่ง ดังนี้

อย่างไรก็ตาม บางครั้งสิทธิ์เหล่านี้ไม่ได้กำหนดโดยแท็ก <permission> ที่เกี่ยวข้องในไฟล์ Manifest ของ APK ในอุปกรณ์ ในกรณีนี้ สิทธิ์ดังกล่าวจะเรียกว่าสิทธิ์ที่ไม่มีเจ้าของ ปัญหานี้อาจเกิดขึ้นได้จากหลายสาเหตุ เช่น

  • การอัปเดตในไฟล์ Manifest กับโค้ดที่มีการตรวจสอบสิทธิ์อาจไม่ได้ซิงค์กัน
  • APK ที่มีสิทธิ์อาจไม่รวมอยู่ในบิลด์ หรืออาจรวมเวอร์ชันที่ไม่ถูกต้อง
  • ชื่อสิทธิ์ในการตรวจสอบหรือไฟล์ Manifest อาจสะกดไม่ถูกต้อง

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

ในกรณีที่แอปที่มีสิทธิ์ใช้สิทธิ์เพื่อปกป้องหรือจํากัดคอมโพเนนต์ใดก็ตาม การดำเนินการนี้อาจให้สิทธิ์แอปที่เป็นอันตรายเข้าถึงคอมโพเนนต์นั้น ตัวอย่างเช่น การเริ่มกิจกรรมที่ได้รับการคุ้มครองโดยสิทธิ์ การเข้าถึงผู้ให้บริการเนื้อหา หรือการออกอากาศไปยังตัวรับสัญญาณออกอากาศที่ได้รับการคุ้มครองโดยสิทธิ์ที่ไม่มีเจ้าของ

นอกจากนี้ยังอาจสร้างสถานการณ์ที่แอปพลิเคชันที่มีสิทธิ์ถูกหลอกให้เชื่อว่าแอปที่เป็นอันตรายเป็นแอปที่ถูกต้องตามกฎหมาย จึงโหลดไฟล์หรือเนื้อหา

การลดปัญหา

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

แอปใช้สิทธิ์ที่กำหนดเอง my.app.provider.READ และ my.app.provider.WRITE เพื่อปกป้องการเข้าถึงผู้ให้บริการเนื้อหา

Xml

<provider android:name="my.app.database.CommonContentProvider" android:readPermission="my.app.provider.READ" android:writePermission="my.app.provider.WRITE" android:exported="true" android:process=":myappservice" android:authorities="my.app.database.contentprovider"/>

นอกจากนี้ แอปยังกำหนดและใช้สิทธิ์ที่กำหนดเองเหล่านี้ด้วย ซึ่งจะป้องกันไม่ให้แอปอื่นๆ ที่เป็นอันตรายดำเนินการดังกล่าว

Xml

<permission android:name="my.app.provider.READ"/>
<permission android:name="my.app.provider.WRITE"/>
<uses-permission android:name="my.app.provider.READ" />
<uses-permission android:name="my.app.provider.WRITE" />

ความเสี่ยง: ใช้ android:protectionLevel ในทางที่ผิด

แอตทริบิวต์นี้อธิบายระดับความเสี่ยงที่อาจเกิดขึ้นในสิทธิ์ และระบุขั้นตอนที่ระบบควรทำเมื่อตัดสินใจว่าจะให้สิทธิ์หรือไม่

การลดปัญหา

หลีกเลี่ยงระดับการปกป้องระดับปกติหรืออันตราย

การใช้ protectionLevel ปกติหรืออันตรายในสิทธิ์หมายความว่าแอปส่วนใหญ่จะขอและรับสิทธิ์ได้ ดังนี้

  • "normal" กำหนดให้ประกาศเท่านั้น
  • "อันตราย" จะได้รับอนุมัติจากผู้ใช้จำนวนมาก

ดังนั้น protectionLevels เหล่านี้จึงมีความปลอดภัยน้อย

ใช้สิทธิ์ลายเซ็น (Android เวอร์ชันตั้งแต่ 10 ขึ้นไป)

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

กำหนดสิทธิ์ที่กำหนดเองในไฟล์ Manifest ดังนี้

Xml

<permission
    android:name="my.custom.permission.MY_PERMISSION"
    android:protectionLevel="signature"/>

จำกัดการเข้าถึง เช่น กิจกรรม เฉพาะแอปที่ได้รับสิทธิ์ที่กำหนดเองนี้ ดังนี้

Xml

<activity android:name=".MyActivity" android:permission="my.custom.permission.MY_PERMISSION"/>

แอปอื่นๆ ที่ลงนามด้วยใบรับรองเดียวกับแอปที่ประกาศสิทธิ์ที่กำหนดเองนี้จะได้รับสิทธิ์เข้าถึงกิจกรรม .MyActivity และจะต้องประกาศสิทธิ์ดังกล่าวในไฟล์ Manifest ดังนี้

Xml

<uses-permission android:name="my.custom.permission.MY_PERMISSION" />

ระวังสิทธิ์ที่กำหนดเองของลายเซ็น (Android เวอร์ชันต่ำกว่า 10)

หากแอปของคุณกำหนดเป้าหมายเป็น Android เวอร์ชันต่ำกว่า 10 เมื่อใดก็ตามที่มีการนำสิทธิ์ที่กำหนดเองของแอปออกเนื่องจากการถอนการติดตั้งหรือการอัปเดต แอปที่เป็นอันตรายอาจยังคงใช้สิทธิ์ที่กำหนดเองเหล่านั้นได้ จึงจะผ่านการตรวจสอบ ปัญหานี้เกิดจากช่องโหว่การยกระดับสิทธิ์ (CVE-2019-2200) ซึ่งได้รับการแก้ไขแล้วใน Android 10

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


ความเสี่ยง: ภาวะแข่งขัน

หากแอปที่ถูกต้องตามกฎหมาย A กำหนดสิทธิ์ที่กำหนดเองตามลายเซ็นที่ใช้โดยแอป X อื่นๆ แต่มีการถอนการติดตั้งแอปดังกล่าวในภายหลัง แอปที่เป็นอันตราย B จะกำหนดสิทธิ์ที่กำหนดเองเดียวกันนั้นด้วย protectionLevel อื่นได้ เช่น normal วิธีนี้จะช่วยให้ B ได้รับสิทธิ์เข้าถึงคอมโพเนนต์ทั้งหมดที่ได้รับการปกป้องโดยสิทธิ์ที่กำหนดเองในแอป X โดยไม่ต้องลงนามด้วยใบรับรองเดียวกับแอป A

การดำเนินการนี้จะเหมือนกันหากติดตั้ง B ก่อน A

การลดปัญหา

หากต้องการทำให้คอมโพเนนต์พร้อมใช้งานสำหรับแอปที่ลงนามด้วยลายเซ็นเดียวกับแอปที่ให้บริการเท่านั้น คุณอาจหลีกเลี่ยงการกำหนดสิทธิ์ที่กำหนดเองเพื่อจำกัดการเข้าถึงคอมโพเนนต์นั้นได้ ในกรณีนี้ คุณสามารถใช้การตรวจสอบลายเซ็นได้ เมื่อแอปหนึ่งส่งคำขอไปยังแอปอื่น แอปที่ 2 จะยืนยันได้ว่าทั้ง 2 แอปได้รับการรับรองด้วยใบรับรองเดียวกันก่อนที่จะปฏิบัติตามคำขอ


แหล่งข้อมูล