티스토리 뷰
[ 로컬 암호화 이슈]
: 중요정보를 단말기에 저장할 때 취약한 암호화 알고리즘을 사용하거나 평문으로 저장해서 발생하는 이슈
1) 대칭키 알고리즘
: 하나의 키로 암호화, 복호화 하는 방식
< 문제점 >
- 하나의 키만 사용하므로 키가 노출될 경우 모든 암호문을 복호화 할 수 있다.
- 암호문을 전달받는 사람이 키를 소유하고 있지 않으면 내용을 확인할 수 없다.
2) 공개키 알고리즘
: 2개의 키로 암호화, 복호화 하는 방식
타인에게 절대 노출되어서는 안되는 개인키(비밀키)를 토대로 만든 공개키가 쌍을 이룬 형태이다.
- 공개키(Public Key) : 사람들에게 공개된 키이며 정보를 암호화
- 개인키(Private Key) : 사용자만 알고 있는 암호를 복호화 할 수 있는 키
< 취약점 진단 과정 >
Autofill Credentials 버튼
: 이 버튼을 사용하면 마지막으로 로그인했던 아이디와 패스워드를 자동으로 불러와 로그인
(실제 금융 앱의 자동 로그인 기능이 이와 비슷한 원리)
1. adb shell 접속
adb shell
2. 가상 디바이스 안에 인시큐어뱅크 앱의 데이터가 저장되는 곳으로 이동
cd /data/data/com.android.insecurebankv2/shared_prefs
ls -la
com.android.insecurebankv2_preferences.xml 과 mySharedPreferences.xml 파일이 존재함을 확인 가능
3. 위 2개의 파일 내용 출력
cat mySharePreferences.xml
암호화된 사용자 아이디를 담고 있는 EncryptedUsername
패스워드 같은 superSecurePassword 변수 확인 가능
cat com.android.insecurebankv2_preferences.xml
서버의 ip와 포트 정보 확인 가능
위 2개의 "SharedPreferences" 파일은 안드로이드 애플리케이션에서 해당 프로그램 내에 파일 형태로
데이터를 저장 or 삭제하기 전까지 그 내용 유지 가능.
< SharedPreferences 특징 >
1. 초기 설정값, 자동 로그인 등 간단한 환경 변수를 애플리케이션의 저장 공간 안에 파일 형태로 저장
2. 별도로 삭제하지 않는 이상 재부팅되더라도 값은 유지
3. 편집하기 위해서는 반드시 SharedPreferences.Editor 인터페이스에 포함된 메서드 사용
메서드 종류 | 메서드 설명 |
putBoolean(String key, boolean value) | Boolean 값을 키값으로 지정 |
putFloat(String key, float value) | Float 값을 키값으로 지정 |
putInt(String key, int value) | Int 값을 키값으로 지정 |
putLong(String key, long value) | long 값을 키값으로 지정 |
putString(String key, string value) | string 값을 키값으로 지정 |
putStringSet(String key, Set<String> values) | string set 값을 키값으로 지정 |
Apply(), commit() | 변경한 값을 변수에 저장 |
clear() | SharedPreferences 오브젝트에 있는 값을 지움 |
private void saveCreds(String param1String1, String param1String2) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
SharedPreferences.Editor editor = DoLogin.this.getSharedPreferences("mySharedPreferences", 0).edit();
DoLogin.this.rememberme_username = param1String1;
DoLogin.this.rememberme_password = param1String2;
param1String1 = new String(Base64.encodeToString(DoLogin.this.rememberme_username.getBytes(), 4));
CryptoClass cryptoClass = new CryptoClass();
DoLogin.this.superSecurePassword = cryptoClass.aesEncryptedString(DoLogin.this.rememberme_password);
editor.putString("EncryptedUsername", param1String1);
editor.putString("superSecurePassword", DoLogin.this.superSecurePassword);
editor.commit();
}
2번째 줄 : getSharedPreferences 클래스로 파일 생성하고 파일을 수정하기 위한 클래스 오브젝트를 정의
3-4번째 줄 : 위 코드 앞에서 로그인할 때 사용했던 아이디와 패스워드를 변수에 할당하고, rememberme_변수 이름으로 재저장
5번째 줄 : base64 인코딩으로 사용자 아이디 저장
7번째 줄 : 저장된 패스워드를 superSecurePassword 변수에 ASE로 암호화해 저장
8-9번째 줄 : 인코딩된 아이디, 암호화된 패스워드를 myShaerdPreferences에 입력
10번째 줄 : 입력된 정보들을 확실하게 저장
위 mysharedPreferences.xml 파일을 다시 확인해보면,
사용자 아이디는 base64로 인코딩 된 값으로 ZGluZXNo 이고
슈퍼 시큐어키값은 AES로 암호화 된 값으로 DTrW2VXjSoFdg0e61fHxJg== 로 저장되어 있다.
CryptoClass.class 파일에 소스코드를 확인해보면 AES에서 사용하는
대칭키와 같은 내용이 포함된 것을 확인.
CryptoClass.class 일부
public String aesEncryptedString(String paramString) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
byte[] arrayOfByte = this.key.getBytes("UTF-8");
this.plainText = paramString;
this.cipherData = aes256encrypt(this.ivBytes, arrayOfByte, this.plainText.getBytes("UTF-8"));
this.cipherText = Base64.encodeToString(this.cipherData, 0);
return this.cipherText;
}
}
2번째 줄 : getByte를 사용해 문자열 변수로 되어 있는 키값을 "UTF-8" 캐릭터로 변경한 후에 저장
3번째 줄 : PlainText에 함수 전달 인자로 받은 평문을 사용자가 입력한 암호로 저장
4번째 줄 : AES로 암호화하는 aes256encrypt 함수 호출
5번째 줄 : AES 암호화된 패스워드를 cipherText에 저장
6번째 줄 : 암호화된 패스워드 리턴
CryptoClass.class 일부 (key 값으로 암호화 수행하는 aes256encrypt 함수 코드)
public static byte[] aes256decrypt(byte[] paramArrayOfbyte1, byte[] paramArrayOfbyte2, byte[] paramArrayOfbyte3) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
IvParameterSpec ivParameterSpec = new IvParameterSpec(paramArrayOfbyte1);
SecretKeySpec secretKeySpec = new SecretKeySpec(paramArrayOfbyte2, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(2, secretKeySpec, ivParameterSpec);
return cipher.doFinal(paramArrayOfbyte3);
}
전달 인자는 대칭키값인 keyBytes
대칭키 값을 받아 패스워드를 암호화 한 후 이 값을 aesEncryptedString 함수로 리턴
리턴 받은 값은 mySharedPreferences.xml 파일에 저장.
앞에서 확인한 DTrW2VXjSoFdg0e61fHxJg== 값이 "This is the super secret key 123" 이라는 키값으로 AES 암호화 된 값.
4. AES 복호화
< 대응 방안 >
1. 사용자 아이디도 base64가 아닌 패스워드를 암호화하는 데 사용되었던 AES 암호화 사용
- 인코딩은 암호화 개념이 아니라 특정 알고리즘에 치환되는 형태이기 때문
2. 비밀번호는 aes128bit 암호화 알고리즘을 사용해 대칭키 암호화의 경우 112bit 이상 안전하다고 판단
- KISA, 모바일 대민서비스 보안취약점 점검 가이드 참조
- But, 대칭키를 사용해 암호화하는 알고리즘에서 고유키가 제대로 보호하지 못하면 아무리 강력한 암호화
방법을 사용하더라도 데이터를 안전하게 보관 X
3. 키를 관리하는 서버를 별도로 두고, 키를 주기적으로 변경
- 키를 주기적으로 변경하더라도 최소한의 인원만 키에 대한 정보를 알고 있어야 함.
4. 키를 암호화 해 파일 시스템에서 관리
- 공격자가 프로세스가 동작하는 도중, 메모리 덤프 등을 통해 키를 추출할 수 도 있다는 점에 주의
5. 소스 코드 난독화와 바이너리 무결성 검증
- 인시큐어뱅크 앱은 암호화된 키가 평문으로 저장되어 있으므로 소스코드가 노출될 경우 키값이
그대로 노출될 수 있는 가능성 존재
'Security Study > Android' 카테고리의 다른 글
[InsecureBankv2] 루팅 탐지 및 우회 (0) | 2023.01.20 |
---|---|
[InsecureBankv2] 액티비티 컴포넌트 취약점 (0) | 2023.01.20 |
[InsecureBankv2] 취약한 인증 메커니즘 (0) | 2023.01.20 |
[InsecureBankv2] 브로드캐스트 리시버 결함 (0) | 2023.01.20 |
[Bytecode Viewer] 실행 방법 (0) | 2023.01.13 |
- Total
- Today
- Yesterday
- 스테가노그래피
- networking
- 드림핵
- 안드로이드
- 모바일
- 인시큐어뱅크
- forensics
- Fiesta
- CTF
- sqlinjection
- forensic
- 리버싱
- FTKImager
- cheatengine
- Steganography
- md5
- AssaultCube
- Cookie
- 포렌식
- reversing
- mongodb
- SQLi
- 취약점
- MISC
- rev
- dreamhack
- 해킹
- web
- Android
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |