iOS SQLite WAL
檔案深度分析

2020-2-15 by 高田鑑識

2019年是鑑識界的重大元年,Cellebrite 也在年底列出了10大重要突破,其中第一名的 checkm8 漏洞,可讓 iOS 裝置支援完整檔案系統提取(Full File System);原本無法透過 Advanced Logical 提取的的檔案或資料庫,藉著 FFS 可讓鑑識同仁取得更多甚至是破案關鍵的重要數位證據。

但如果了解 iOS 檔案系統架構的鑑識同仁,應該清楚理解採用 File Based Encryption(FBE) 加密的裝置,當任一個檔案刪除後,位於該檔案 metadata 內的 File Key 金鑰(圖一藍色框)也被刪除。

圖一、iOS資料安全架構

沒有了這把 File Key 金鑰,即使可以採用物理提取未分配的空間(unallocated space),最後獲得的也只是一堆被雜湊過後的數據,除非有無限的時間去計算反推,以現知的工具並沒有任何辦法恢復刪除的檔案或資料(除非破解 Secure Enclave, 細節可參考 iOS 檔案加密機制文章)。

圖二、各提取模式可獲取之內容

刪除的聊天資訊?

不過最近很多鑑識同仁成功採用 FFS 提取 iPhone 5S – iPhone X 裝置後,透過 PA 解析開始又出現已刪除的資料,包含 Telegram, LINE 與網頁搜尋紀錄等等;若以 File based Encryption 的安全性,已刪除的檔案應該是無法成功被提取或採用 Carve 功能拼湊而回,但為什麼 PA 上再次呈現已刪除的數據?

如果我們深入調查,其實可以發現很多 APPs 皆採用資料庫來儲存訊息,尤其是即時通訊 APP,如 LINE 與 Telegram 皆採用 SQLite 資料庫。下圖為從 PA 解析出的一則已刪除訊息。從 source file 可得知資料庫檔案名稱為 db_sqlite-wal,訊息儲存於 t2 表內。

圖三、PA 解析的已刪除資訊

Android 從版本9,iOS 從版本 7 開始,就將原本資料庫 Rollback Journal 回復日誌模式,預設變更為 WAL 模式。而採用 WAL 的 databases 目錄下會有 *.db、*.db-shm、*.db-wal 三個檔案。以下為 iOS 裝置採 FFS 提取後 LINE 目錄下的檔案清單。

圖四、LINE 目錄清單

SQLite 資料庫介紹

SQLite是一種廣泛使用的資料庫格式,幾乎在任何平台上皆可看到,熟悉PA的鑑識人員,在分析行動裝置的過程,應可發現有許多重要內容皆採用資料庫格式儲存,而比例最多則是SQLite。以下列出部分行動裝置較常用的資料庫種類:

MySQL: 開源,多執行緒且易於使用的SQL數據庫。

PostgreSQL: 高度可客製化且功能強大的開源關聯式資料庫。

MariaDB: 開源關聯式資料庫,由MySQL的原始開發人員開發維護。

Cassandra: 一個免費的開源NoSQL數據庫,旨在處理各種規模的大量非結構化數據。

SQLite: 嵌入式資料庫,常用用法是在行動裝置上供APP儲存資料使用,且一個APP只允許對應一個db檔

交易模型(Transaction Model)

早期的 SQLite 版本採用回復日誌模式(Rollback Journal)來防止資料庫寫入錯誤。回復日誌的主要目的是為了要讓 SQLite 可以完成「交易」 (Transaction),當交易失敗或中斷時可用此檔案來回復,來確保資料完整與一致性。簡易來說,A 匯款至 B 帳戶,錢不會因為匯款過程因銀行系統或用戶端裝置斷電而造成款項卡在某處,匯款結果只會有成功或失敗。而 SQLite 在 3.7 版本後引入 WAL 日誌模式,兩者的差異如下說明:

> 回復日誌 (Rollback Journal):

  • Rollback Journal 回復日誌原理是在變更資料庫檔案中的資料之前,先將所在分頁中的資料備份在另外一個地方,然後才將修改的資料寫入到資料庫檔案中;如果交易 (transaction) 失敗,則將備份資料拷貝回資料庫,取消修改;如果交易成功,則刪除備份資料,提交變更 (commit)。

  • 動畫說明:

    1. 初始階段:日誌檔案內為空白,尚未有Page資料。
    2. 備份內容:複製Page 3資料至Rollback日誌,變更的資料直接寫入DB。
    3. 完成變更:當該筆交易確認完成(Commit),會將Rollback日誌內的相關資料刪除。

動畫一、回復日誌(Rollback Journal)

> WAL (Write-Ahead Log):

  • WAL (Write-Ahead Logging) 是 SQLite 版3.7.0之後才有的功能。其工作方式和 Journal 剛好相反,所有的交易都是先寫入至 WAL 檔案中,資料庫檔案保持不變。而當 COMMIT 發生時,僅代表某筆記錄已 append 進 WAL 檔,但並不一定會寫入 DB ,直到 WAL 檔案大小到達 SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 時(預設值是1,000 pages,每一個 page 預設大小是1KB),才會將 Commit 的資料寫入進 DB。

  • shm 檔案是用來輔助-wal 檔案的,shm 是 shared memory 的縮寫,可以看做是 WAL 檔案的一個 index 檔,是為了輔助 sqlite 快速定位 WAL 檔案資訊。shm 檔案之中本身不儲存任何和 table 相關的資料,如果我們打開-shm 檔案是看不到任何交易資料的。

  • 動畫說明:

    1. 初始階段:日誌檔案內為空白,尚未有 Page 資料。
    2. 變更內容:進行中之交易內容寫入 WAL Page 3 之內,新的交易內容也會依序 append 至 WAL 檔案內,原 DB 舊的 Page 3 內容資料庫引擎直接忽略。
    3. 完成變更:當達到 checkpoint 後,會將 WAL 上的所有確認 (commit) 的交易資料回寫到資料庫檔案。若有交易失敗的 Page,則被忽略不回寫到資料庫。

    註:在尚未達到 checkpoint 前,資料優先讀取的順序是 WAL ,再來才是 DB 的內容。

動畫二、Write-Ahead Log (WAL)

WAL的優缺點:

優點:

  1. 讀寫可以同時執行,不會互相阻塞(但是寫之間仍然不能同時執行)。
  2. WAL在大多數情況下,擁有較好的效能(因為無需每次寫入兩個檔案)。
  3. 磁碟I/O行為更容易被預測。

缺點:

  1. 資料庫的所有程式必須在同一主機上,且支援共享記憶體技術。(行動裝置沒這個問題)
  2. 每個資料庫現在對應3個檔案:.db,-wal,-shm。
  3. 無法向下相容舊版本的SQLite。

SQLite WAL 逐步解析

如果鑑識人員想要更了解資料庫與 WAL 在新增資料時檔案異動過程,可以參考以下文章。

The Forensic Implications of SQLite’s Write Ahead Log

該作者從產生空白資料庫開始,並記錄了以下步驟來分析資料庫、WAL 與 shm 檔案在每個階段異動時的差異說明。以下摘要文章部分精華。

步驟一、產生空白資料庫 

產生空白資料庫 ,並計算出資料庫、WAL 與 shm 三個檔案的初始 hash 值。

步驟二、使用 SQL 指令 PRAGMA 強制 checkpoint

結果:

  1. 資料庫:內容一樣為空白,但 hash 值變更
  2. shm: hash 變更
  3. WAL: hash 沒異動。
步驟三、Insert 一筆資料

結果:

  1. 資料庫:hash 值沒異動。
  2. shm: hash 變更
  3. WAL: hash 變更,檔案大小沒異動。
步驟四、使用 SQL 指令 PRAGMA 強制 checkpoint

結果:

  1. 資料庫:hash 變更
  2. shm: hash 變更
  3. WAL: hash 、檔案大小沒動。
步驟五、Insert 第二筆資料,同時 Update 第一筆資料內容

結果:

  1. 資料庫:hash 沒異動。
  2. shm: hash 變更
  3. WAL: hash 變更檔案大小異動。
步驟六、Insert 第三筆資料

結果:

  1. 資料庫:hash 沒異動。
  2. shm: hash 變更
  3. WAL: hash 、檔案大小變更
步驟七、使用 SQL 指令 PRAGMA 強制 checkpoint

結果:

  1. 資料庫:hash 變更
  2. shm: hash 變更
  3. WAL: hash 、檔案大小沒動。
步驟八、使用 SQL Delete 指令刪除步驟五的第二筆記錄

結果:

  1. 資料庫:hash 沒異動。
  2. shm: hash 變更
  3. WAL: hash 變更檔案大小沒異動。

WAL 檢視結果

  1. 變更或新 pages 資料皆寫入 WAL 檔案內,每次寫入以一個 frame 為單位,並不會立即寫入資料庫檔案。
  2. 達到 Checkpoint 後,-wal 檔案會重複使用,但資料會被清空。

LINE WAL 測試

經以上說明,相信鑑識同仁對於 SQLite WAL 有基礎的認知,而透過 FFS 提取後 WAL 內可能會包含關鍵證據,可協助偵查方向。

在總結之前,讓我們使用 LINE 來驗證 WAL 可提取之內容,為加速測試,手機為 iPhone 6 並透過 checkra1n 越獄,搭配 tar 指令直接提取 LINE 目錄以下之檔案(含db, -wal, -shm等檔案)。

Copy to Clipboard

指令一、ssh 至 iPhone 6 採用 tar 提取

圖五、LINE 刪除訊息測試

圖六、LINE 收回訊息測試

圖七、匯入PA後解析結果

經測試結果,PA可解析 WAL 檔案內的已刪除資訊,但「收回」訊息則無法顯示。這時可建議鑑識同仁採用另一個工具,來解析 WAL 檔案。

walitean 為採用 Python 開發之 SQLite WAL 與 Journal 分析工具,透過該指令可將 WAL 轉換成標準資料庫格式,可用 SQLite Viewer 等免費工具查看 WAL 內部資料。walitean 使用方式如下:

Copy to Clipboard

指令二、將 WAL 檔案轉換成資料庫格式

圖八、瀏覽 LINEDBWAL 收回之訊息

總結:

  1. 在測試過程,LINE WAL 檔案預設大小為 4MB。
  2. 當 WAL 累積大於 4MB 時會執行 checkpoint 將已 commit 之資料回寫至 LINE 資料庫。
  3. PA 可正常解析 WAL 內的已刪除資訊。
  4. PA 現有版本尚無法解析收回之訊息。