ETC./Paper Reviews

(review)Android Password Managers and Vault Applications: Data Storage Security Issues Identification

마띠(쥔장) 2022. 8. 25. 17:55

2022년 6월 Journal of Information Security and Applications (JISA)에 발표된 'Android Password Managers and Vault Applications: Data Storage Security Issues Identification'이라는 제목의 논문입니다.


Introduction

이 논문을 언급하기 전 먼저 다른 논문을 소개드리겠습니다. 2021년에 같은 저자들이 ICAI에 'Android Password Managers and Vault Applications: Comparative Security Analysis'이라는 논문을 냈었는데요, 해당 논문에서는 

  1. PM/VA에 맡겨진 데이터가 노출될 수 있는 보안 위협을 지적하면서 4개의 인기 있는 안드로이드 PM/VA를 보안적 측면에서 비교하고
  2. 보안성을 평가할 수 있는 기준과 분석 프로세스에 대해 설명했습니다.

이 때 저자들이 선정했던 4개 어플리케이션은 Keeper, LastPass, Dashlane, Bitwarden인데, 그 중 Bitwarden이 가장 안전했다고 할 수 있지만 그 마저도 본인들이 제시한 보안 기준을 완전히 만족시키지는 못했다고 합니다. 그래서 각 어플리케이션의 행위와 작동 원리를 분석하여 공식 문서에서 누락된  세부사항이 무엇이고 보안 수준이 어떤지 확인하는 등의 '심층 조사'가 필요하다고 결론을 냈었습니다.

그렇게 나온 후속 연구 논문이 이 글의 주제가 될 'Android Password Managers and Vault Applications: Data Storage Security Issues Identification'으로, 지난 연구 주제였던 4개 어플리케이션 중 보안 수준이 높았던 2개 어플리케이션인 Keeper와 Bitwarden을 대상으로 심층 평가를 진행하는 내용입니다. 디버깅과 리버싱을 이용해 지난 연구에서 필요성을 느꼈던 '공식 문서에는 누락된 보안 스토리지에 대한 분석'과 '각 어플리케이션의 보안 수준이 어느 정도인지 확인하는 것'이 이 논문의 목표라고 할 수 있습니다.

Methodology

이런 목표를 달성하기 위해 논문에서 제시하는 분석 과정은 다음과 같습니다.

  1. 공식 문서와 어플리케이션에서 찾을 수 있는 아티팩트를 우선적으로 분석하고
  2. 어플리케이션의 보안 설계를 파악한 다음
  3. 보안 스토리지를 구현하기 위해 사용한 방식을 식별합니다
  4. 다음으로 보안 위협이 발생할 수 있는 설계 상 오류를 찾고 구현의 핵심적인 매커니즘을 분석합니다
  5. 위 내용을 바탕으로 취약점이 될 수 있는 공격 벡터를 식별하고
  6. 결과적으로 보안 스토리지의 보안성을 깨뜨릴 수 있는지 확인하는 과정을 거칩니다

위 과정이 잘 정제되어 깔끔하긴 하지만 저는 약간 추상적으로 느껴져서, 실제적으로 논문에서 표현하는 분석 과정을 이렇게 정리해보았습니다. 지금 설명 드리는 내용은 논문의 'Methodology' 파트인데, 이 다음 순서가 'Data storage security issues identification - Custom attacks development - Simulative attacks'입니다. 3개 파트가 논문의 핵심 내용을 다루고 있다고 할 수 있는데요.

이 바로 다음에 소개드릴 'Identification' 부분에서 시스템의 설계/구현을 통해 발견된 취약한 부분을 공격하는 방법에 대해 설명하고 있고 각 포인트를 'AV'라고 칭하고 있습니다. 그 다음 Custom attack 부분에서는 이 AV를 기반으로 'A'를 설계하는데, A는 각 AV에 대응하는 맞춤형 공격 알고리즘 정도로 이해하시면 됩니다. 마지막으로 Simulative attacks 부분에서 논문 저자가 설계한 attack을 직접 실험해보는 attack instance, 'AI'를 제시하는 흐름을 가지고 있습니다.

  • Data storage security issues identifiaction → AV_X
  • Custom attacks devlopment A_X
  • Simulative attacks AI_X

쯤에서 제가 이 논문을 리뷰하기로 한 이유에 대해서 잠깐 이야기 드리자면, 지금까지 말씀드린 것처럼 이 논문의 전체적인 흐름이

  1. 분석이 필요한 시스템에 대해서 시스템의 설계 부분을 본 다음
  2. 발견된 오류에 대해 이어질 수 있는 취약성을 소개하고
  3. 그 취약성을 기반으로 공격도 설계해서 그 결과도 제시하는 식인데요.

그래서 제가 관심있는 주제를 하나 선정했을 때 그 시스템을 대상으로 security analysis를 할 수 있는 전반적인 과정을 배울 수 있다고 생각했습니다. 또 어플리케이션 분석이 어플의 설계에 따라서 그 때 그 때 다른 접근법이 필요한데, 그럼 이 논문에서는 어떻게 접근하고 있는지 궁금한 마음에 이 논문을 골랐습니다. 그래서 제가 생각한 이런 장점을 조금 더 잘 소개 드리기 위해 논문에 작성된 방식이 아니라 [하나의 AK에 대응하는 AAI를 한 번에 소개하는 식]으로 약간 순서를 바꿔서 글을 적도록 하겠습니다.

Data storage security issues identification

논문 저자들이 연구에 사용한 모바일 기기는 각각 안드로이드 버전 9.0, 5.1이고 모두 루팅된 상태입니다. 그 중 pixel3 기종은 암호가 걸려있습니다. 실험 대상 어플리케이션은 위에서 말씀드렸듯 Keeper와 Bitwarden이고, 아쉽지만 저자들이 실험했을 당시 가장 최신 버전이었던 2020년 업데이트 버전입니다.

Keeper insepction

Keeper의 첫 번째 공격 벡터를 식별하는 과정부터 설명드리겠습니다. 아래 사진은 안드로이드의 data 폴더 내에 keeper가 그 데이터를 저장하는 스토리지 구조인데요그 중 /data/data/com.callpod.android_apps.keeper라는 디렉터리는 인증된 사용자가 VA에서 암호화된 파일을 열어보는 그 시간동안만 복호화된 copy를 임시적으로 저장하는 곳입니다. 그 후 사용자가 파일을 닫으면 바로 삭제돼서 평소에는 빈 상태를 유지한다고 합니다.

그렇게 식별한 AV_K1은 로컬 장치에 볼트 데이터로서 암호화되어 있어야 할 파일이 일시적으로 복호화돼서 저장된다는 것입니다

  • AV_K1: Break the confidentiality by using data recovery tools in order to recover the decrypted copies of the original files that are leaked to the device's flash storage

이에 대한 ATTACK의 알고리즘을 요약하자면 현재 RAM에 보관되어 있는 데이터 카피를 만들기 위해 칩오프나, 취약점을 이용해 덤프를 뜨는 등의 방법을 통해 Cold boot 상태에서의 full access를 얻는 것입니다.

논문에서는 볼트 어플리케이션에서 jpg 파일을 몇 초간 열고 닫은 다음, 최근 실행 프로그램 목록에서 keeper를 지우고 disk digger라는 파일 복구 어플을 이용해 data 디렉터리를 스캔했을 때 온전히 복구할 수 있었다고 합니다. disk digger라는 도구는 간단한 삭제 파일 복구 도구인데, 암호화된 파일이 일시적으로 복구-삭제되는 과정에서 파일이 삭제되었는지 저장된 상태로 유지되는지에 관계없이 액세스 권한을 가진 모든 사용자가 파일을 복구할 수 있기 때문에 설계 결함으로 볼 수 있습니다. 

첫 번째 AV는 삭제 후 복구 식의 접근이었다면 두 번째 공격벡터는 tmp_decrypted_record_files 디렉터리를 모니터링하여 사용자가 파일을 조회하는 동안의 타이밍을 노리는 것입니다.

  • AV_K2: Break the confidentiality by monitoring the contents of the “tmp_decrypted_record_files” while the legitimate user is viewing attached files

여기서는 해당 디렉터리에 변경 사항이 생기면 바로 로컬 카피를 만드는 행위를 하는, 프로그램을 직접 짜서 실험했다고 합니다. 실제로 저자들이 모니터링 어플리케이션을 이용했을 때 Cs_로 시작하는 임시 파일이 생겼고 확장자를 jpeg로 변경하니 완전한 원본 카피임을 확인할 수 있었다고 합니다.

다음으로 주목한 설계는 Keeper가 모든 UEDEA, 사용자 데이터를 저장하는 /data/data/com.callpod.android_apps.keeper/databases/${loginId}.sql 파일의 'setting' 테이블인데, 그 중 민감한 데이터를 저장하는 'known_value', 'sync_name', 'suggestion_locale', 'url_list' 행을 제외한 나머지 93개 행은 별도의 암호화나 인증 시스템이 없다고 합니다.

그렇게 식별한 세번째 벡터는 사용자 인증 과정을 우회하여 정상 사용자 대신 데이터를 변경하고 이 보안 매커니즘을 완화시키는 것입니다attack 알고리즘은 먼저 sql db파일의 카피를 생성하고 민감한 데이터의 name-value 쌍을 변조하여 기존의 db 파일을 대체하는 변조된 db 파일을 만드는 방법으로 진행됩니다.

  • AV_K3: Disable application's security mechanisms or make them weakened by applying unauthorized changes on behalf of the legitimate user by bypassing user identity verification

AV_K3에 대응하는 AIK3부터 K7까지 총 4개인데요. 4개가 다 비슷비슷합니다. 그 중 첫 번째는 스크린샷을 방지하는 설정의 변조에 관한 것입니다. Keeper의 스크린샷 방지 매커니즘은 prevent_scrennshots라는 변수의 값이 1일 때 동작하고 0일 때 비활성화되는데, 이 값을 변경하는 과정에서 별도의 사용자 인증 매커니즘이 없기 때문에 아래 쿼리를 실행해 값을 토글할 수 있습니다.

이런 식으로 말입니다.

다음 Attack Instance도 비슷한 결인데, 이번에는 패스워드 입력란에 패스워드를 입력할 때 보이지 않게 하는 하이딩 기능을 비활성화하는 쿼리를 날립니다. 관련 설정을 변경할 수 있는 hide_passwords의 값을 0으로 업데이트하여 테이블 설정 값을 변조하는 방식으로 이루어집니다. 이러한 설정을 업데이트 했을 때 암호를 마스킹하는 기능이 사라지고 기본 기능이 비활성화 되었다는 별도의 메시지도 뜨지 않아 공격을 성공했다고 합니다.

지금까지 스크린샷, 패스워드 하이딩 기능을 비활성화했는데, Keeper는 VA답게 마스터 패스워드를 일정 카운트 이상 잘못 입력했을 때 스스로 자폭을 해서 데이터를 초기화하는 기능이 있습니다. enable self destruct 값을 0으로 업데이트하는 쿼리 실행을 통해서 다음과 같이 우회도 가능했다고 합니다.

왼쪽 사진은 우회하기 전 마스터 패스워드를 잘못입력했을 때 뜨는 메시지이고 오른쪽이 우회 후 화면인데 초기화까지의 남은 입력 가능 횟수를 보여주는 것이 아니라 단순히 잘못입력했다는 메시지만 띄워주고 10번 이상 잘못 입력한 뒤에 맞는 비밀번호를 입력했을 때 바로 로그인할 수 있었다고 합니다.

같은 결로 timeout과 관련된 설정도 우회할 수 있습니다. 이번에는 일정 시간이 지났을 때 자동으로 잠금이 되는 auto lock 기능의 timeout 값을 변경하였고 쿼리 실행 후에 기본 값인 600초를 임의의 시간 값으로 변경할 수 있었다고 합니다.

여기까지 AV_K3과 관련한 AI 4개 설명이 끝났고 다음은 AV_K4입니다.

Keeper의 DB에서 password 테이블의 행들은 크게 암호화된 데이터 값 자체를 저장하는 FHERV 행(빨간색으로 표시)과 그 행의 상태를 저장하는 FHT 행(초록색으로 표시)으로 나눌 수 있습니다그리고 공식 문서에 따르면 그 중에서도 FHERV 행은 모두 같은 Client key로 암호화됩니다. 이 때 사용되는 GCM 모드의 AES 암호화 (AES in GCM)는 개별적인 행의 무결성은 검증하지만, 같은 키로 여러 개의 행을 암호화했을 때 그 여러 개 데이터 사이의 무결성은 보장하지 않는다는 문제가 있습니다.

FHERV의 상태를 저장하는 행인 말그대로 상태 값이므로 FHT01의 값을 가질 수 있을 텐데, 이 말은 즉 FHT 행이 0 값을 가질 때 FHERV는 암호화가 풀린 데이터를 저장하고 있다 라는 뜻으로 예상할 수 있습니다따라서 password 테이블에서의 복호화된 데이터를 찾기 위해 리버싱을 해보았을 때 암호화를 담당하는 Encryptor라는 클래스에 다음과 같은 함수가 있고, GCM 모드의 AES에 추가적으로 CBC모드도 사용하고 있음을 알 수 있었습니다.

이 때 사용하는 패딩 모드가 Spongy Castle이라는 오픈 소스 라이브러리(org.spongycastle.jce.provider)를 사용하며, 이런 부분이 공식 문서에 누락되었다는 점도 밝혔지만 더 중요한 것은 Encryptor 인터페이스의 AesCbcWithEmptyIv, AesCbc, AesGcm리턴값을 다음과 같이 일정한 상수로 설정했다는 점입니다.

결론적으로 PASSWORD 테이블의 'encrypted', 'cipher', 'password', 3개 필드는 항상 같은 값을 가지며 RV에 대해 별도의 인증 확인 체계를 사용하지 않는다는 것을 확인했습니다. 

여기까지 마지막 2개의 공격 벡터를 더 도출할 수 있어요. 먼저 1개 키로 암호화하는 여러 개의 행들에 대한 인증 체계가 없으니 password 테이블에서 적절한 레코드를 하나 선택하고 그 레코드에 해당하는 필드를 삭제하거나 다른 필드의 값으로 변경하는 식으로 password 테이블 변조할 수 있습니다. 물론 아무런 필드가 삭제하면 무결성이 깨지므로 필드와 레코드의 매핑 구조가 같은 값으로 변경해야 합니다.

  • AV_K4: Change the correspondence between the FHERVs and the encrypted RVs to modify unauthorized record X. Forge an application record by using the encrypted RVs (FHERVs) in arbitrary row of the ‘password’ table

예를 들어 2개의 uid record를 고르고 아래 사진과 같은 3개의 쿼리를 실행해서tmp에 바꾸려고 하는 uid를 넣고 아까 고른 2개 uid record 값을 스왑하는 식으로  공격자가 합법적인 사용자를 속여 Keeper에 이미 저장된 데이터를 이용해서 로그인할 수 있다고 설명하고 있습니다.

그리고 다섯번재 공격 벡터는 CBC 모드를 사용하고 그 초기 벡터를 알고 있는 시스템에 대해 수행할 수 있는 비트 플리핑에 관한 공격에 대한 것인데, 여기서는 KeeperDB에서 적절한 레코드 값을 삭제한 다음 다른 필드값을 비트 플리핑을 통해 변조하고 덮어쓰는 방법입니다. 

  • AV_K5: Forge an application record X by applying bit-flipping attack. To tamper with the one or more FHERVs in the row of the password table corresponding to the record X.

이렇게 합법적인 사용자 대신 연결 필드 값을 수정하여 응용프로그램 레코드를 위조하는 식입니다.

Bitwarden insepction

이제 다음으로 Bitwarden에 대한 설명입니다. 공격 벡터 식별을 위해 데이터를 저장하는 구조부터 보겠습니다. Bitwarden의 /data/data/com.x8bit.bitwarden/shared_prefs 디렉터리 안에 com.x8bit.bitwarden_preferences.xml이라는 파일이 존재하는데, 이 xml 파일에 거의 모든 세팅을 암호화 없이 저장한다고 합니다.

또 Bitwarden은 깃허브에서 그 소스 코드를 볼 수 있는데, /data/data/com.x8bit.bitwarden/files/bitwarden.db 파일에서 'ciphers ~'라는 id가 가질 수 있는 value의 유형, 암호화 구조도 찾을 수 있습니다. 이 구조의 경우 keeper와 달리 인증된 암호화를 사용하기 때문에 비트 플리핑 공격은 불가능하지만 하나의 밸류와 그 메타데이터에 대한 매핑 신뢰성을 보장해주지는 않고 있다고 합니다.

따라서 preferences.xml 파일의 id-value 쌍을 식별한 후 각 쌍에 대한 설정 이름을 변조하는 식으로 비트워든의 보안 매커니즘을 약화시킬 수 있습니다.

  • AV_B1: applying unauthorized changes to the application's security settings

예를 들어 Bitwarden 타임에 관한 설정 정보를 소스코드를 통해 찾은 다음, value 값을 변조 주는 식입니다.

두 번째 공격 벡터도 비슷한데, 그 대상 파일이 XML이 아니라 DB라고 생각하시면 됩니다. DB 내에 여러 열들에 대해서 그 매핑 정보를 인증하는 시스템도 따로 존재하지 않으므로 아래 알고리즘처럼 위조될 레코드와 필드의 매핑을 스왑하는 식으로 공격이 가능합니다.

  • AV_B2: applying unauthorized changes to the application's security settings

논문에서 제시하는 실험 결과를 보면 왼쪽이 행위 전, 오른쪽이 레코드 변조 후 사진입니다각각의 패스워드를 서로 스와핑하여 NAMEURL등의 정보는 같지만 서로의 패스워드가 바뀐 것처럼 연출할 수 있습니다

Conclusion

이제 결론으로 가보면 Keeper와 Bitwarden 모두 Android Application Sandbox에서의 보안 수준에 전적으로 의존하고 있으며 Keeper는 내부 저장소에 복호화 파일을 저장하는 점, Bitwarden은 XML을 통해 설정을 저장해 누구나 쉽게 변경할 수 있는 점 때문에 역시 둘 다 안전하지 않고 개선이 필요하다고 마무리하고 있습니다. 또 해당 논문에서는 식별한 여러가지 보안 위협들의 패턴을 정의해두는 것을 향후 계획으로 잡고 있습니다.

Impression

이 논문을 읽고 느낀점은, 논문에서 모든 분석의 시작을 Data Storage Identification으로 잡고 처음부터 알려주고 있어서 따라하면서 보기 좋았고 향후 계획에서 언급되었던  Anti-pattern을 정의하는 데이터 셋을 몇 개 모아서 룰을 만들 수 있을 것 같다고 생각했습니다하지만 제조사 자체 클라우드로 데이터를 전송하거나 볼트 어플리케이션끼리의 파일 전송에 대해서는 다루지 않은 점, 민감한 파일을 복호화할 수 밖에 없을 때 어플리케이션이 어떻게 안전을 보장하는 지에 대한 궁금증은 해결되지 않아서 아쉽기도 했네요. 

 

728x90