Browser Forensic
디지털 포렌식에서 웹 브라우저 아티팩트 분석은 사용자가 특정 웹 브라우저에서 어떤 인터넷 행위를 했는지 확인할 수 있기 때문에 중요한 분석 과정으로 여겨진다.
본글은 Google의 Chrome 브라우저를 대상으로 History 삭제 정책을 확인하고, 이를 토대로 Ext4 파일 시스템에서의 History 복원 정책을 정의한다. 이후에 History 복원 정책을 토대로 '인터넷 사용 기록 삭제'가 적용된 환경에서 실제 아티팩트 분석을 진행해 정보 추출 가능 여부를 정의한다.
Scenario
본 실습은 Rooting이 진행된 Android의 S7(SM-G930S) 기기에서 진행하며, Chrome Browser의 실습 환경은 '검색어', '다운로드', '방문 URL' 기록이 존재할 수 있게 재현하고 이후 '인터넷 사용 기록 삭제'를 적용한다.
실습 환경에서의 시나리오 내용은 다음과 같고, 아래의 사진은 실습 환경 재현의 모습이다.
1. 'Best of the best 13기' 검색 후 BoB 사이트에 방문하여 pdf 파일을 다운로드한다.
2. 'Team H4C' 검색 후 H4C 사이트에 방문한다.
3. Chrome의 '인터넷 사용 기록 삭제' 기능을 이용해 인터넷 검색 및 방문 기록을 삭제한다.
History Deletion Policy
Android의 Ext4 파일 시스템에서 Chrome 브라우저의 History 복원 과정을 정의하기 위해 먼저 History 삭제 정책을 정의해야 한다.
Chrome 브라우저의 History 데이터는 Journaling 모드는 'journal' 모드의 'TRUNCATE' 방식을 사용하는 SQLite에 저장되고, 삭제 방식은 'secure-delete' 방식을 사용한다.
History Recovery Flow Chart
본 문단의 삭제된 History 복원 과정은 '인터넷 사용 기록 삭제' 이벤트 이후의 이미지 파일을 기점으로 한다. Chrome Browser의 History 삭제 정책을 기반으로 Ext4 파일 시스템에서 효율적인 History 복원 흐름도를 정의한다.
Chrome Browser는 SQLite 파일에 History 데이터를 저장하고, SQLite의 'secure-delete' 모드로 History 데이터를 삭제한다. 이때, SQLite의 Journaling은 'jounal'의 'TRUNCATE' 방식을 이용하기 때문에 Ext4 파일 시스템 단위에서 'History-journal' 파일에 할당되었던 모든 Extent Entry를 복원하여 삭제된 History 데이터를 복원할 수 있다. 흐름도의 각 순서 번호와 자세한 설명은 다음과 같다.
1. History 파일 추출 및 History-journal 파일 Inode Number 확보.
- 이미지 파일을 FTK Imager에 업로드하여 History 파일 추출하고 SQLite 내부의 Table 데이터 존재 여부를 확인한다.
- 이미지 파일을 FTK Imager에 업로드하여 History-journal 파일의 Inode Number를 확보한다.
2. History-journal 파일의 Inode Entry 접근 및 History-journal 파일의 File Version 확보.
- 이전 단계에서 확보한 History-journal 파일의 Inode Number로 History-journal 파일의 Inode Entry에 접근한다.
- History-journal 파일의 Inode Entry에서 File Version 값을 확보한다.
3. journal에서 History-journal 파일에 할당되었던 모든 Extent Entry 확보.
- 이전 단계에서 확보한 History-journal 파일의 File Version 값을 Ext4의 journal에서 검색한다. 이후 검색된 Hex 값의 Inode Entry를 해석해 History-journal 파일에 할당되었던 모든 Extent Entry 데이터를 확보한다.
4. History-journal 파일에 할당되었던 모든 Data Block 영역 추출.
- 이전 단계에서 확보한 History-journal 파일에 할당되었던 모든 Extent Entry를 해석해, 디스크 이미지 파일에서 History-journal 파일에 할당되었던 모든 Data Block 영역을 추출한다.
5. '인터넷 사용 기록 삭제' 이벤트 이전의 데이터를 포함하는 SQLite 트랜잭션 백업 Page 확보 및 History 파일 복원.
- 이전 단계에서 추출한 History-journal 파일에 할당되었던 모든 Data Block 영역에서 '인터넷 사용 기록 삭제' 이벤트 이전의 유효한 데이터를 포함하는 SQLite 트랜잭션 백업 Page를 확보하고 History 파일에 복원한다.
History Recovery 1 (Normal Mode)
본 문단은 이전 문단에서 제시한 Ext4 파일 시스템에서의 효율적인 History 복원 흐름도를 기반으로, '인터넷 사용 기록 삭제' 이벤트가 발생한 History 파일의 복원을 진행한다.
1. History 파일 추출 및 History-journal 파일 Inode Number 확보.
- 이미지 파일을 FTK Imager에 업로드하여 History 파일 추출하고 SQLite 내부의 Table 데이터 존재 여부를 확인한다.
아래는 FTK Imager로 History 파일을 추출한 모습이다.
추가적으로 History 파일의 중요한 데이터를 포함하는 일부 Table인 'downloads', 'keyword_search_terms', 'urls' Table을 확인한 모습으로, '인터넷 사용 기록 삭제' 이벤트가 발생했으나 'downloads' Table에서는 유효한 데이터가 존재하고 나머지 2개의 Table인 'keyword_search_terms', 'urls'에서는 유효한 데이터를 확인할 수 없는 모습이다.
- 이미지 파일을 FTK Imager에 업로드하여 History-journal 파일의 Inode Number를 확보한다.
아래는 FTK Imager로 History-journal 파일을 확인한 모습으로, Inode Number가 '2031889'임을 알 수 있다.
2. History-journal 파일의 Inode Entry 접근 및 History-journal 파일의 File Version 확보.
- 이전 단계에서 확보한 History-journal 파일의 Inode Number로 History-journal 파일의 Inode Entry에 접근한다.
History-journal 파일의 Inode Number가 '2031889'(0x1F0111)이었으므로, Inode Table의 '0x1F011000'((0x1F0111 - 1)x 0x100) 번 Byte로 이동하면 History-journal 파일의 Inode Entry에 접근할 수 있다. 아래는 History-journal 파일의 Inode Entry 모습이다.
- History-journal 파일의 Inode Entry에서 File Version 값을 확보한다.
History-journal 파일의 File Version은 '0x76 A0 91 F9'가 된다.
3. journal에서 History-journal 파일에 할당되었던 모든 Extent Entry 확보.
- 이전 단계에서 확보한 History-journal 파일의 File Version 값을 Ext4의 journal에서 검색한다. 이후 검색된 Hex 값의 Inode Entry를 해석해 History-journal 파일에 할당되었던 모든 Extent Entry 데이터를 확보한다.
이전 단계에서 확보한 File Version 값인 '0x76 A0 91 F9'을 Ext4의 journal에 검색하고, 검색된 모든 영역의 Inode Entry의 Extent Entry를 해석해 History-journal 파일에 할당되었던 모든 Extent Entry를 추출한다.
아래는 Ext4의 journal에서 74개의 File Version Hex 값이 검색된 모습이다.
그 중 연속되는 2개의 Inode Entry만을 수동으로 분석해 보았다. 첫 번째 Inode Entry의 Number of Valid Extent Entry 값은 '0x03'이고, 그 중 첫 번째 Extent Entry는 '8044045'(0x7ABE0D)번 Block 부터 1 Block, 두 번째 Extent Entry는 '8044034'(0x7ABE02)번 Block 부터 11 Block, 세 번째 Extent Entry는 '8043723'(0x7ABCCB)번 Block 부터 3 Block 영역을 의미한다.
두 번째 Inode Entry의 Number of Valid Extent Entry 값은 '0x00'이고, 때문에 Extent Entry가 존재하지 않는다.
4. History-journal 파일에 할당되었던 모든 Data Block 영역 추출.
- 이전 단계에서 확보한 History-journal 파일에 할당되었던 모든 Extent Entry를 해석해, 디스크 이미지 파일에서 History-journal 파일에 할당되었던 모든 Data Block 영역을 추출한다.
필자는 3, 4 단계를 자동화해 주는 Python 코드를 작성해 분석을 진행하였다. 아래는 코드를 실행하는 모습으로, 이전 단계에서 수동으로 분석한 Inode Entry Case는 터미널에서 출력된 3번째 Inode Entry Case임을 확인할 수 있다.
추가로 해당 코드는 실행 시 인자로 입력한 디렉터리에 각 Inode Entry의 Data Block 영역을 추출해 journal에서 검색된 번호 순을 이름으로 저장해 준다.
5. '인터넷 사용 기록 삭제' 이벤트 이전의 데이터를 포함하는 SQLite 트랜잭션 백업 Page 확보 및 History 파일 복원.
- 이전 단계에서 추출한 History-journal 파일에 할당되었던 모든 Data Block 영역에서 '인터넷 사용 기록 삭제' 이벤트 이전의 유효한 데이터를 포함하는 SQLite 트랜잭션 백업 Page를 확보하고 History 파일에 복원한다.
해당 분석 단계는 Python 코드가 수행할 수 없는 단계로, 추출된 파일의 Hex값을 일일이 분석해 '인터넷 사용 기록 삭제' 이벤트 이전의 유효한 백업 Page를 선별해야 한다.
본 실습은 History 내부의 여러 Table 중 중요한 데이터를 포함하는 일부 Table인 'downloads', 'keyword_search_terms', 'urls' Table 복원을 진행한다. 이 중 'downloads' Table은 '인터넷 사용 기록 삭제' 이벤트에 삭제되지 않았으므로, '인터넷 사용 기록 삭제' 이벤트가 확실하게 적용된 'keyword_search_terms', 'urls' Table 복원만을 진행한다. 아래는 History 파일의 Hex 값을 확인해 'keyword_search_terms', 'urls' Table의 각 Root Page 번호를 확인하는 모습으로, 순서대로 Root page 번호는 '0x0F', '0x0B' 값을 갖는다.
파이썬 코드 실행으로 추출된 파일의 Hex 값을 일일이 분석해 'keyword_search_terms', 'urls' Table의 Internal 혹은 Leaf Page로 추측되는 Page를 선별한다. 이후 해당 Page를 복원하려는 Table의 Root Page에 덮어 History 복원을 진행한다.
아래는 'Search_18' 파일에서 'keyword_search_terms' Table의 Leaf Page로 추정되는 Page를 선별하고, History 파일의 Root Page 번호인 '0x0F'번 ('0x15'번 섹터)에 덮어쓴 모습이다.
아래는 'Search_18' 파일에서 'urls' Table의 Leaf Page로 추정되는 Page를 선별하고, History 파일의 Root Page 번호인 '0x0B'번 ('0x11'번 섹터)에 덮어쓴 모습이다.
결과적으로 History 파일을 SQLite DB Browser로 열어 'keyword_search_terms', 'urls' Table을 확인한 모습으로, '인터넷 사용 기록 삭제' 이벤트가 발생하기 이전의 유효한 데이터를 복원한 모습이다.
Conclusion
결과적으로 Ext4 파일 시스템에서 Chrome 브라우저의 '인터넷 사용 기록 삭제'의 경우 'secure-delete'가 적용되어 History(SQLite) 파일 자체에서 삭제된 History 정보를 복원할 수 없고, History-journal 파일을 이용해 복원할 수 있다. 이 경우 Ext4의 journal을 이용해 History-journal 파일에 할당되었던, Extent Entry를 복원할 수 있으나, Ext4 journal의 사이클이 한 번 돌게 되면 Extent Entry를 복원할 수 없게 된다. 이후에 복원한 Extent Entry를 이용해 History-journal 파일에 할당되었던 Data Block Area를 추출해 '인터넷 사용 기록 삭제' 이벤트 이전의 유효한 데이터를 포함하는 Page를 복원할 수 있으나, SQLite의 journal 파일 특성상 트랜잭션이 정상적으로 완료되면 History-journal 파일에 할당되었던 디스크 영역이 비할당 영역으로 전환되기 때문에 해당 영역이 다른 데이터로 덮인다면 복원이 불가능하다.
Reference
https://www.dbpia.co.kr/journal/detail?nodeId=T15015734
https://www.dbpia.co.kr/journal/articleDetail?nodeId=NODE08736972