8. 안드로이드 앱 진단 실습 (6) - 항목별 진단 실습 3 : 로컬 암호화 이슈
[목차]
Local Encryption issues (로컬 암호화 이슈)
1. 취약점 설명
2. 진단 방법
- 앱의 전반적인 기능들을 실행해 보고 탐색
- DB 추출 후 중요정보 암호화 여부 확인
- DB 외 파일들에서 중요정보 암호화 여부 확인
- 클라이언트단 소스코드 점검 및 암호화 로직 점검
- 복호화 시도
3. 대응 방안
[Local Encryption Issus]
1. 취약점 설명
로컬 암호화 이슈 취약점은
중요 정보가 단말기에 저장될 때
암호화되어 있지 않거나 취약한
암호화 체계 사용, 또는 복호화
힌트가 소스코드 내 노출되어 있는
취약점으로
인시큐어뱅크 앱에서 사용하는
여러 계정 정보는 암호화를 사용하지
않고 있다.
2. 진단 방법
(1) 앱의 전반적인 기능들을 실행해 보고 탐색
로그인 시도 후 앱 종료 > 앱 재실행 후
Autofill Credentials 클릭

자동완성 기능이 가능한 걸로 보아
단말기 어딘가에 계정 정보가
저장되어 있다고 생각할 수 있다.
(2) DB 추출 후 중요정보 암호화 여부 확인
adb로 쉘에 접속한 뒤 인시큐어뱅크 앱 내
디렉터리 구조를 살펴보면 다음과 같은데

쉘에서 작업하면 불편한 부분이 있어
위 파일들을 모두 로컬 PC로 옮긴 뒤
진단을 실시한다.
ㄱ. DATA 추출
C:> adb pull /dat/data/com.android.insecurebankv2 .\

추출한 뒤 들어가 보면

앱 내 데이터가 정상 추출된 것을 확인할 수 있는데
디비 내용은
databases 내 mydb 파일을



DB 내 중요 정보가 노출되는지 확인
(3) DB 외 파일들에서 중요정보 암호화 여부 확인
DB 외 살펴볼 파일은
shared_prefs 내 xml 파일로
이 전 과정인
[안드로이드 백업 취약점]에서
데이터 백업 시 생성된 tar 파일의
압축을 해제하면
sp 디렉터리 내 사용자 암호가 저장된
mySharedPreferences.xml
파일이 있었는데

당연히 shared_prefs 디렉터리 내에도
동일한 파일이 있다.

내용을 살펴보면

사용자 이름과 비번이
암호화되어 저장되어 있고
아이디는 바로 디코딩이 가능하지만

비번은 아니다.

* 참고로
인코딩과 디코딩은 단순
데이터 형식이기 때문에
키가 없이도 바로 변환이 가능하지만
암호화와 복호화의 경우는
둘 다 키가 필요하다는
차이점이 있다.
이런 시점으로 현재 사용자 아이디와
비번의 저장 방식을 살펴보면
아이디는 encoded user name이고
비번은 encrypted password라
할 수 있겠다.
(4) 클라이언트단 소스코드 점검 및 암호화 로직 점검
현재 점검 중인 대상은 앱 실행 후
Autofill Credentials 버튼을 눌렀을 때
저장되어 있는 계정 정보가
자동으로 입력되는 부분인데
LoginActivity 클래스 내
fillData_button이 호출되면


fillData() 함수 내 settings 변숫값
getsharedPreferences 메서드가
mySahredPreferences.xml
파일에 저장되어 있는 암호화된
로그인 데이터를 파싱 해
username / password로
담아주는데
이때
username / password가
복호화 되어 자동으로 앱에
입력되는 방식을 살펴보면

username의 경우 base64 방식으로
decoding 되는 것을 알 수 있는데
디코딩 후 UTF-8로 변환 뒤
string으로 만들어 준다.
그렇게 변환한 username은
평문 string으로 디코딩 되어
setText를 통해 아이디 란에 입력된다.
비번에 사용되는 암/복호화 방식은
CryptoClass()라는 클래스를 사용하는데
(해당 클래스는 아래 별도로 살펴본다)


mySahredPreferences.xml 파일에서
파싱 한 암호화된 비밀번호를
CryptoClass()의
aesDecryptedString 메서드로 복호화 한 뒤
setText로 앱 비밀번호 란에 넣어주는 구조.
복호화 하는 방식을 살펴보았는데
암호화 로직의 경우는 DoLogin 클래스 내
saveCreds 함수에서 살펴볼 수 있다.

username은 Base64
password는 aesEnctypt 방식
saveCreds 함수가 호출되는 경우는

로그인 정보가 맞아
정상적으로 로그인이 되는 경우
해당 data가 서버로 전송되면서
postdata() 함수 내
saveCreds()라는 메서드가 호출되어
username / password가 전달,
saveCreds 내
지정된 암호화 방식으로 변환 시켜
editor(mySharedPreferences.xml)에
저장되는 것

(5) 복호화 시도
password는
aesEncrypt 방식으로 암호화가 진행되었는데
aesEncrypt 함수를 한번 살펴보면

aes256 방식으로 암호화를 수행한 뒤
base64로 추가 암호화가 진행된다.
해당 aes256encrypt가 구현된
클래스를 살펴보면 복호화와 마찬가지로
CryptoClass 내에 정의되어 있는데

특이한 점은 소스코드 내
암/복호화에 사용되는 대칭 키가
하드코딩 되어있다.
'This is the super secret key 123'
암호화 키 + 대칭 키가 모두 있으니
복호화를 시도해 보면

base64 방식으로 인코딩된 결괏값 확인이 가능하며
이를 다시 디코딩 해보면

평문 비밀번호 확인이 가능하다.
3. 대응 방안
- 중요 정보를 다루는 코드를 검토하여
중요 정보가 암호화될 수 있도록 코드 추가 및 수정
- 암/복호화에 사용되는 대칭 키가 노출되지 않도록
안전하게 저장