Mobile Application Security [EP. 6.2]

Datafarm
4 min readSep 6, 2023

สวัสดีผู้อ่านทุกท่านครับ กลับมาพบกับบทความ Android Security กันต่อในตอนที่ 6.2 ครับ ซึ่งในตอนที่ 6.1 ผมได้อธิบายถึงเรื่องของ Android Application Structure, Intents, Deep Links, AIDL, Messenger ไปแล้ว หากผู้อ่านท่านใดจำไม่ได้หรือยังไม่ได้อ่านสามารถอ่านได้ที่ลิงก์ในท้ายบทความนะครับ เอาล่ะครับเพื่อไม่ให้เป็นการเสียเวลาเราไปเข้าสู่เนื้อหาของบทความกันเลยครับ

Binder

มาเริ่มกันที่ Binder ครับ ซึ่งก่อนจะไปถึงเรื่อง Binder ผมขอพูดถึง IPC กันก่อน ซึ่ง IPC ย่อมาจากคำว่า Inter-Process Communication โดย IPC จะมีหน้าที่ในการควบคุมการแลกเปลี่ยนข้อมูลหรือการสื่อสารระหว่าง Process เช่น การส่งผ่านข่าวสาร (Message Passing), การประสานเวลา (Synchronization), การ Shared Memory เป็นต้น

ในส่วนของ Binder นั้นเป็น IPC ตัวหนึ่งในระดับ Kernel-level โดยหน้าที่ของมันก็คือการย้ายข้อมูลหรือส่งข้อมูลจาก Process Memory หนึ่งไปยังอีก Process Memory หนึ่ง แต่ในบทความนี้ผมขอไม่ลงลึกถึงเนื้อหาในส่วนนี้นะครับ แต่หากผู้อ่านท่านใดสนใจสามารถศึกษาเพิ่มเติมได้จากในลิงก์ท้ายบทความนะครับ นอกจากนี้แล้วในเรื่องของ Binder ยังถูกพูดถึงในงาน Black Hat ในปี 2015 อีกด้วยในหัวข้อ “Man in the Binder: He Who Controls IPC, Controls the Droid” ดังนั้นแล้วหากใครสนใจสามารถตามไปดูได้ใน YouTube เลยครับ

Components

Components คือส่วนประกอบของแอปพลิเคชันในระบบแอนดรอยด์ซึ่งสามารถแบ่งออกได้เป็น Activity, Service, Broadcast Receiver และ Provider โดยส่วนประกอบต่าง ๆ มีบทบาทหน้าที่ในการทำงานแตกต่างกัน ซึ่ง Components ต่าง ๆ จะถูกพัฒนาขึ้นโดย Developer ตามแต่วัตถุประสงค์ของแอปพลิเคชันนั้น ๆ โดยเราสามารถตรวจสอบ Components ต่าง ๆ เหล่านี้ได้ในไฟล์ AndroidManifest.xml

Activities

Activity คือส่วนที่ติดต่อกับผู้ใช้งานหรือก็คือหน้าจอที่แสดงผลให้กับผู้ใช้งานเห็นในแอปพลิเคชัน โดยแอปพลิเคชันส่วนใหญ่จะต้องมีอย่างน้อยหนึ่ง Activity ที่มีการอนุญาตให้มีการเรียกใช้งานผ่าน Intent ซึ่งเราสามารถตรวจสอบ Activity ได้จาก AndroidManifest ดังตัวอย่างในภาพที่ 1

ภาพที่ 1 ไฟล์ AndroidManifest.xml แสดง Activity ต่าง ๆ ของแอปพลิเคชัน

จากภาพที่ 1 เป็นการประกาศ Activity ในไฟล์ AndroidManifest ซึ่งเราจะสังเกตได้ว่าภายในหนึ่งแอปพลิเคชันนั้นประกอบไปด้วย Activity มากมาย ซึ่งหากผู้พัฒนาไม่คำนึงถึงความปลอดภัยของแอปพลิเคชันก็อาจทำให้เกิดช่องโหว่ได้เช่นกัน ดังภาพที่ 2

ภาพที่ 2 ไฟล์ AndroidManifest แสดงการประกาศ Activity อย่างไม่ปลอดภัย

จากภาพที่ 2 เป็นการประกาศ Activity ภายใน AndroidManifest ที่ไม่ปลอดภัยโดยที่ Activity ดังกล่าวได้ตั้งค่า Attribute android:exported=”true” ซึ่งการตั้งค่าดังกล่าวเปรียบเสมือนการ Shared ให้แอปพลิเคชันอื่นสามารถเรียกใช้งาน Activity ดังกล่าวได้โดยตรง

จากตัวอย่างในภาพที่ 2 เป็นการประกาศ Activity ของแอปพลิเคชัน “Damn Vulnerable Bank” โดย Activity ดังกล่าวเป็นฟังก์ชันในการโอนเงิน ดังนั้นแอปพลิเคชันอื่นสามารถเรียกใช้งานฟังก์ชันการโอนเงินของแอปพลิเคชัน “Damn Vulnerable Bank” ได้โดยไม่ต้องยืนยันตัวตนหรือ Login ใด ๆ เลย

จากตัวอย่างในภาพที่ 2 เป็นการประกาศ Activity ของแอปพลิเคชัน “Damn Vulnerable Bank” โดย Activity ดังกล่าวเป็นฟังก์ชันในการโอนเงิน ดังนั้นแอปพลิเคชันอื่นสามารถเรียกใช้งานฟังก์ชันการโอนเงินของแอปพลิเคชัน “Damn Vulnerable Bank” ได้โดยไม่ต้องยืนยันตัวตนหรือ Login ใด ๆ เลย

Services

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

ภาพที่ 3 ไฟล์ AndroidManifest แสดงการประกาศ Service ของแอปพลิเคชัน

Broadcast Receivers

Broadcast Receiver มีหน้าที่ในการรับข้อมูลของ Broadcast Intent ที่ถูกส่งมาจากแอปพลิเคชันอื่น โดย Broadcast Receiver จะถูกกำหนดไว้ที่ AndroidManifest ในส่วนของ “receiver” หรือสามารถประกาศแบบ Dynamic ได้ด้วย Method “registerReceiver”

Receivers จะมีหน้าที่หลักในการรับข้อมูล Input จากแอปพลิเคชันอื่นมาทำงานหรือส่ง Broadcast ต่อไป เช่น มีข้อความหรือสายเรียกเข้า, ข้อความแจ้งเตือนผู้ใช้งานเมื่อแบตเตอรี่ต่ำ ซึ่งส่วนสำคัญของการใช้งาน Receiver ให้ปลอดภัยคือต้องมีการตรวจสอบ Broadcast หรือข้อมูลที่ได้รับจากแอปพลิเคชันอื่นและจำกัดด้วยว่า Broadcast ใดที่ Receiver ยอมรับและนำมาประมวลผลในแอปพลิเคชัน

Content Providers

Content Provider คือส่วนประกอบของแอปพลิเคชันแอนดรอยด์ที่มีหน้าที่ในการ Shared ข้อมูลต่าง ๆ ของแอปพลิเคชันเพื่อให้แอปพลิเคชันอื่นสามารถเรียกใช้งานได้ เช่น Database (SQLite) หรือข้อมูลอื่น ๆ ที่เกี่ยวข้อง

ในการประกาศใช้งาน Content Provider ให้มีความปลอดภัยควรคำนึงถึงเรื่องของ Business Requirement ก่อนเป็นอันดับแรกโดยพิจารณาว่าต้องการ Shared ข้อมูลเพื่อให้แอปพลิเคชันอื่นเรียกใช้งานหรือไม่ ซึ่งเราสามารถตั้งค่า Attribute android:exported=”true” ที่ AndroidManifest หากต้องการ Shared ข้อมูลเช่นเดียวกับ Components อื่น ๆ

นอกจากนี้แล้วเรายังสามารถกำหนด Permissions ให้กับ Content Provider เพื่อป้องกันและจำกัดสิทธิ์ในการเข้าถึงข้อมูลใน Provider สำหรับแอปพลิเคชันอื่น ๆ โดย Permission เราสามารถประกาศได้ในไฟล์ AndroidManifest ซึ่ง Attribute “readPermission” และ “writePermission” จะต้องถูกประกาศก่อนเพื่อขออนุญาตจากผู้ใช้งานในการเข้าถึงฐานข้อมูลหรือแก้ไขข้อมูล

ภาพที่ 4 ไฟล์ AndroidManifest แสดงการประกาศ Content Provider ของแอปพลิเคชัน

WebView

WebView มีหน้าที่ในการทำงานเปรียบเสมือน Web Browser ซึ่งจะถูกฝังมากับแอปพลิเคชันในระบบแอนดรอยด์ โดย WebView สามารถ Render HTML, ประมวลผล JavaScript หรือแม้กระทั่งประมวลผล Active Content ซึ่งทั้งนี้จะขึ้นอยู่กับเวอร์ชันของ WebView เอง

โดย Content ที่จะโหลดไปประมวลผลบน WebView สามารถดึงมาจากเว็บไซต์หรือไฟล์ต่าง ๆ บนเว็บแอปพลิเคชัน เช่น Template HTML ผู้พัฒนาแอปพลิเคชันมักจะดึง Content จากเว็บแอปพลิเคชันมาแสดงบนแอปพลิเคชันแอนดรอยด์ผ่าน WebView เพื่อให้สะดวกต่อการพัฒนาและเพื่อให้ง่ายต่อการเปลี่ยนแปลงเนื้อหาโดยไม่ต้องอัปเดตแอปพลิเคชันบ่อย ๆ

นอกจากนี้แล้วการเรียกใช้งาน WebView ก็มีความเสี่ยงต่อการถูกโจมตีได้เช่นกัน โดยความเสี่ยงที่อาจเกิดขึ้นจะเหมือนกับความเสี่ยงกับ Web Browser ตามมาตรฐานช่องโหว่ Web Application ของ OWASP Top 10

แต่อย่างไรก็ตามผู้พัฒนาสามารถแอปพลิเคชันสามารถตั้งค่า WebView เพื่อให้เกิดความปลอดภัยในการใช้งานได้ ซึ่งในแอนดรอยด์เวอร์ชัน 4.4 WebView จะถูกฝังมากับ Chromium Browser เพื่อแก้ไขปัญหาในการ Render Content ต่าง ๆ ต่อมาในแอนดรอยด์เวอร์ชัน 5 ทาง Google ได้พัฒนา WebView ให้สามารถอัปเดตได้เช่นเดียวกันกับแอปพลิเคชันอื่น ๆ เพราะในแอนดรอยด์เวอร์ชันก่อนหน้า WebView ไม่สามารถดำเนินการอัปเดตได้หากไม่อัปเดตระบบปฏิบัติการแอนดรอยด์ ดังนั้นแล้วเพื่อให้เกิดความปลอดภัยสูงสุดในการใช้งานผู้ใช้งานควรอัปเดตระบบและ Software อย่างสม่ำเสมอ

Shared UID

สำหรับแอปพลิเคชันบนระบบแอนดรอยด์ในทุก ๆ แอปพลิเคชันจะต้องมีการ Signed ก่อนเพื่อระบุตัวตนของผู้พัฒนาแอปพลิเคชันนั้นๆและเป็นการอนุญาตให้ผู้พัฒนาแอปพลิเคชันสามารถแก้ไขหรืออัปเดตแอปพลิเคชันดังกล่าวได้ นอกจากนี้แล้วการ Signed แอปพลิเคชันด้วย Key เดียวกันจะสามารถใช้เลข UID หรือ User ID เดียวกันได้

การใช้เลข UID เดียวกันจะทำให้แอปพลิเคชันสามารถ Shared ข้อมูลระหว่างแอปพลิเคชันได้ ดังนั้นแล้วหากสองแอปพลิเคชันมีการใช้เลข UID เดียวกันและมีแอปพลิเคชันใดแอปพลิเคชันหนึ่งที่มีช่องโหว่ ความเสี่ยงที่เกิดขึ้นจะส่งผลกระทบให้กับอีกแอปพลิเคชันด้วยเช่นกัน ตัวอย่างเช่นหากแอปพลิเคชัน A และแอปพลิเคชัน B มีการ Shared ข้อมูลร่วมกันด้วยเลข UID เดียวกัน และแอปพลิเคชัน A มีช่องโหว่ Code Execution, Directory Traversal แอปพลิเคชัน B ก็อาจจะถูกโจมตีด้วยช่องโหว่ดังกล่าวได้นั่นเอง

ในการ Shared UID แอปพลิเคชันจะต้องกำหนดค่า Attribute “android:sharedUserId” ในไฟล์ AndroidManifest.xml

ภาพที่ 5 ไฟล์ AndroidManifest.xml แสดงการ Shared UID ระหว่างแอปพลิเคชัน Bob และ Alice

จากภาพที่ 5 เมื่อสังเกตที่ Attribute “android:sharedUserId” ทั้งสองแอปพลิเคชันมีการ Shared UID ร่วมกันระหว่างแอปพลิเคชัน Bob และ Alice นั่นหมายความว่าเมื่อติดตั้งแอปพลิเคชันทั้งสองลงบนอุปกรณ์แอนดรอยด์เครื่องเดียวกันแล้ว ทั้งสองแอปพลิเคชันจะมีเลข UID เหมือนกัน ข้อมูลหรือไฟล์ใด ๆ ที่ถูกเก็บไว้บน Local Storage ของแอปพลิเคชัน Alice จะสามารถเข้าถึงได้โดยตรงจากแอปพลิเคชัน Bob ในทางกลับกันหากแอปพลิเคชัน Alice มีช่องโหว่เช่น Directory Traversal ผู้ไม่ประสงค์ดีสามารถโจมตีแอปพลิเคชัน Bob ด้วยช่องโหว่ดังกล่าวและสามารถเข้าถึงข้อมูลหรือไฟล์ใน Local Storage ของแอปพลิเคชัน Bob ได้เช่นกัน

--

--