หมวดหมู่ OWASP: MASVS-CODE: คุณภาพโค้ด
ภาพรวม
เมื่อจัดเก็บหรือโอนข้อมูลออบเจ็กต์ Java จำนวนมาก การซีเรียลไลซ์ข้อมูลก่อนมักจะมีประสิทธิภาพมากกว่า จากนั้นแอปพลิเคชัน กิจกรรม หรือผู้ให้บริการที่รับข้อมูลจะดำเนินการดีซีเรียลไลซ์ข้อมูล ในสถานการณ์ปกติ ระบบจะซีเรียลไลซ์และดีซีเรียลไลซ์ข้อมูลโดยไม่ต้องให้ผู้ใช้ดำเนินการใดๆ อย่างไรก็ตาม ผู้ไม่ประสงค์ดีอาจใช้ความสัมพันธ์ที่เชื่อถือได้ระหว่างกระบวนการดีซีเรียลไลซ์กับออบเจ็กต์ที่ต้องการในทางที่ผิด เช่น ดักจับและแก้ไขออบเจ็กต์ที่ซีเรียลไลซ์แล้ว ซึ่งจะทำให้ผู้ไม่ประสงค์ดีสามารถโจมตีได้ เช่น การปฏิเสธการให้บริการ (DoS), การโจมตีเพื่อยกระดับสิทธิ์ และการดำเนินการโค้ดจากระยะไกล (RCE)
แม้ว่าคลาส Serializable จะเป็นวิธีทั่วไปในการจัดการ การเรียงอันดับ แต่ Android ก็มีคลาสของตัวเองสำหรับจัดการการเรียงอันดับที่เรียกว่า Parcel การใช้คลาส Parcel จะซีเรียลไลซ์ข้อมูลออบเจ็กต์เป็นข้อมูลสตรีมไบต์ และแพ็กเป็น Parcel โดยใช้อินเทอร์เฟซ Parcelable ได้
ซึ่งช่วยให้ขนส่งหรือจัดเก็บ Parcel ได้อย่างมีประสิทธิภาพมากขึ้น
อย่างไรก็ตาม ควรพิจารณาอย่างรอบคอบเมื่อใช้คลาส Parcel เนื่องจากคลาสนี้มีไว้เพื่อเป็นกลไกการขนส่ง IPC ที่มีประสิทธิภาพสูง แต่ไม่ควรใช้จัดเก็บออบเจ็กต์ที่ซีเรียลไลซ์แล้วภายในพื้นที่เก็บข้อมูลถาวรในเครื่อง เนื่องจากอาจทำให้เกิดปัญหาความเข้ากันได้ของข้อมูลหรือข้อมูลสูญหาย เมื่อต้องอ่านข้อมูล คุณสามารถใช้อินเทอร์เฟซ Parcelable เพื่อดีซีเรียลไลซ์
Parcel และเปลี่ยนให้กลับมาเป็นข้อมูลออบเจ็กต์ได้
การโจมตีเพื่อใช้ประโยชน์จากการดีซีเรียลไลซ์ใน Android มี 3 ช่องทางหลักๆ ดังนี้
- ใช้ประโยชน์จากสมมติฐานที่ไม่ถูกต้องของนักพัฒนาแอปที่ว่าการดีซีเรียลไลซ์ออบเจ็กต์ที่มาจากประเภทคลาสที่กำหนดเองนั้นปลอดภัย ในความเป็นจริงแล้ว ออบเจ็กต์ที่มาจากคลาสใดก็ได้อาจถูกแทนที่ด้วยเนื้อหาที่เป็นอันตราย ซึ่งในกรณีที่เลวร้ายที่สุดอาจรบกวนตัวโหลดคลาสของแอปพลิเคชันเดียวกันหรือแอปพลิเคชันอื่นๆ การรบกวนนี้อยู่ในรูปแบบของการแทรกค่าที่เป็นอันตราย ซึ่งอาจนำไปสู่การขโมยข้อมูลหรือการยึดบัญชีตามวัตถุประสงค์ของคลาส
- ใช้ประโยชน์จากวิธีการดีซีเรียลไลซ์ที่ถือว่าไม่ปลอดภัยโดยการออกแบบ (เช่น CVE-2023-35669 ซึ่งเป็นข้อบกพร่องในการโจมตีเพื่อยกระดับสิทธิ์ในเครื่องที่อนุญาตให้แทรกโค้ด JavaScript ที่กำหนดเองผ่านช่องทางการดีซีเรียลไลซ์ Deep Link)
- ใช้ประโยชน์จากข้อบกพร่องในตรรกะของแอปพลิเคชัน (เช่น CVE-2023-20963 ซึ่งเป็นข้อบกพร่องในการโจมตีเพื่อยกระดับสิทธิ์ในเครื่องที่อนุญาตให้แอปดาวน์โหลด และเรียกใช้โค้ดภายในสภาพแวดล้อมที่มีสิทธิ์ผ่านข้อบกพร่องภายในตรรกะพัสดุ WorkSource ของ Android)
ผลกระทบ
แอปพลิเคชันใดก็ตามที่ดีซีเรียลไลซ์ข้อมูลที่ซีเรียลไลซ์แล้วซึ่งไม่น่าเชื่อถือหรือเป็นอันตรายอาจเสี่ยงต่อการโจมตีเพื่อดำเนินการโค้ดจากระยะไกลหรือการโจมตีเพื่อปฏิเสธการให้บริการ
ความเสี่ยง: การดีซีเรียลไลซ์อินพุตที่ไม่น่าเชื่อถือ
ผู้โจมตีสามารถใช้ประโยชน์จากการขาดการยืนยันพัสดุภายในตรรกะของแอปพลิเคชันเพื่อแทรกออบเจ็กต์ที่กำหนดเอง ซึ่งเมื่อดีซีเรียลไลซ์แล้ว อาจบังคับให้แอปพลิเคชันเรียกใช้โค้ดที่เป็นอันตรายที่อาจส่งผลให้เกิดการปฏิเสธการให้บริการ (DoS), การโจมตีเพื่อยกระดับสิทธิ์ และการดำเนินการโค้ดจากระยะไกล (RCE)
การโจมตีประเภทนี้อาจเกิดขึ้นอย่างแนบเนียน เช่น แอปพลิเคชันอาจมี Intent ที่คาดหวังพารามิเตอร์เพียงรายการเดียว ซึ่งจะได้รับการดีซีเรียลไลซ์หลังจากผ่านการตรวจสอบแล้ว หากผู้โจมตีส่งพารามิเตอร์เพิ่มเติมที่เป็นอันตรายรายการที่ 2 ที่ไม่คาดคิดมาพร้อมกับพารามิเตอร์ที่คาดหวัง การดำเนินการนี้จะทำให้มีการดีซีเรียลไลซ์ออบเจ็กต์ข้อมูลทั้งหมดที่แทรก เนื่องจาก Intent จะถือว่าพารามิเตอร์เพิ่มเติมเป็น
Bundle ผู้ใช้ที่เป็นอันตรายอาจใช้ลักษณะการทำงานนี้เพื่อแทรกข้อมูลออบเจ็กต์ ซึ่งเมื่อดีซีเรียลไลซ์แล้ว อาจนำไปสู่ RCE, การบุกรุกข้อมูล หรือข้อมูลสูญหาย
การลดความเสี่ยง
แนวทางปฏิบัติแนะนำคือให้ถือว่าข้อมูลที่ซีเรียลไลซ์แล้วทั้งหมดไม่น่าเชื่อถือและอาจเป็นอันตราย ตรวจสอบข้อมูลเพื่อยืนยันว่าข้อมูลเป็นคลาสและรูปแบบที่แอปพลิเคชันคาดหวัง เพื่อให้มั่นใจในความสมบูรณ์ของข้อมูลที่ซีเรียลไลซ์แล้ว
โซลูชันที่เป็นไปได้คือการใช้รูปแบบการมองไปข้างหน้าสำหรับ
java.io.ObjectInputStream ไลบรารี การแก้ไขโค้ดที่รับผิดชอบการ
ดีซีเรียลไลซ์จะช่วยให้มั่นใจได้ว่าระบบจะดีซีเรียลไลซ์เฉพาะชุดคลาสที่ระบุไว้อย่างชัดเจนภายใน Intent
ตั้งแต่ Android 13 (ระดับ API 33) เป็นต้นมา มีการอัปเดตเมธอดหลายรายการภายในคลาส Intent ซึ่งถือเป็นทางเลือกที่ปลอดภัยกว่าเมธอดเก่าที่เลิกใช้งานแล้วสำหรับการจัดการพัสดุ เมธอดใหม่ที่ปลอดภัยกว่าประเภทข้อมูล เช่น getParcelableExtra(java.lang.String, java.lang.Class) และ
getParcelableArrayListExtra(java.lang.String, java.lang.Class) จะตรวจสอบประเภทข้อมูลเพื่อตรวจหาจุดอ่อนที่เกิดจากความไม่ตรงกันซึ่งอาจทำให้แอปพลิเคชัน
ขัดข้องและอาจถูกใช้ประโยชน์เพื่อโจมตีเพื่อยกระดับสิทธิ์ เช่น CVE-2021-0928
ตัวอย่างต่อไปนี้แสดงวิธีใช้คลาส Parcel เวอร์ชันที่ปลอดภัย
สมมติว่าคลาส UserParcelable ใช้ Parcelable และสร้างอินสแตนซ์ของข้อมูลผู้ใช้ที่เขียนลงใน Parcel จากนั้นคุณสามารถใช้เมธอดที่ปลอดภัยกว่าประเภทข้อมูลต่อไปนี้ของ readParcelable เพื่ออ่านพัสดุที่ซีเรียลไลซ์แล้ว:
Kotlin
val parcel = Parcel.obtain()
val userParcelable = parcel.readParcelable(UserParcelable::class.java.classLoader)
Java
Parcel parcel = Parcel.obtain();
UserParcelable userParcelable = parcel.readParcelable(UserParcelable.class, UserParcelable.CREATOR);
โปรดสังเกตการใช้ UserParcelable.CREATOR ภายในเมธอดในตัวอย่าง Java ด้านบน พารามิเตอร์ที่จำเป็นนี้จะบอกเมธอด readParcelable ว่าควรคาดหวังประเภทใด และมีประสิทธิภาพมากกว่าเมธอด readParcelable เวอร์ชันที่เลิกใช้งานแล้ว
ความเสี่ยงเฉพาะ
ส่วนนี้รวบรวมความเสี่ยงที่ต้องใช้กลยุทธ์การลดความเสี่ยงที่ไม่เป็นมาตรฐานหรือได้รับการลดความเสี่ยงใน SDK ระดับหนึ่งและแสดงไว้ที่นี่เพื่อความสมบูรณ์
ความเสี่ยง: การดีซีเรียลไลซ์ออบเจ็กต์ที่ไม่ต้องการ
การใช้ Serializable อินเทอร์เฟซภายในคลาสจะทำให้คลาสย่อยทั้งหมดของคลาสดังกล่าวใช้ อินเทอร์เฟซโดยอัตโนมัติ ในสถานการณ์นี้ ออบเจ็กต์บางรายการอาจรับช่วงอินเทอร์เฟซดังกล่าว ซึ่งหมายความว่าระบบจะยังคงประมวลผลออบเจ็กต์บางรายการที่ไม่ได้มีไว้เพื่อดีซีเรียลไลซ์
ซึ่งอาจเพิ่มพื้นที่ผิวการโจมตีโดยไม่ได้ตั้งใจ
การลดความเสี่ยง
หากคลาสรับช่วง Serializable อินเทอร์เฟซ ตาม คำแนะนำของ OWASP คุณควรใช้เมธอด readObject ดังนี้เพื่อหลีกเลี่ยงไม่ให้มีการดีซีเรียลไลซ์ออบเจ็กต์ชุดหนึ่งในคลาส
Kotlin
@Throws(IOException::class)
private final fun readObject(in: ObjectInputStream) {
throw IOException("Cannot be deserialized")
}
Java
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
แหล่งข้อมูล
- Parcelable
- Parcel
- Serializable
- Intent
- Android Deserialization Vulnerabilities: A Brief history
- Android Parcels: The Bad, the Good and the Better (video)
- Android Parcels: The Bad, the Good and the Better (presentation slides)
- CVE-2014-7911: Android <5.0 Privilege Escalation using ObjectInputStream
- CVE-CVE-2017-0412
- CVE-2021-0928: Parcel Serialization/Deserialization Mismatch
- คำแนะนำของ OWASP