R136A1

[InsecureBank] 4. Local Encryption issues + 10. Weak Cryptography implementation + 22. Hardcoded secrets (java어떻게봄?) 본문

Android/InsecureBankv2

[InsecureBank] 4. Local Encryption issues + 10. Weak Cryptography implementation + 22. Hardcoded secrets (java어떻게봄?)

r136a1x27 2021. 11. 12. 19:39

4. Local Encryption Issues

[사전 지식]

앱 개발을 진행하다보면 데이터를 저장하여 관리해야 할 상황에 직면한다.

이 때 데이터의 양이 크거나, 중요한 데이터는 서버나 DB, 파일의 형태로 저장을 하면 되겠지만

간단한 설정 값이나 문자열 같은 데이터는 DB에 저장하기에는 부담스럽다.

이런 경우 안드로이드에서 기본적으로 제공되는 SharedPreferences를 사용하여 관리하면 편리하게 사용이 가능하다

 

위치: /data/data/{앱의 패키지 명}/shared_prefs/{기록파일명}.xml

앱 폴더 내에 저장되므로, 앱을 삭제하면 당연히 데이터도 삭제된다.

 

SharedPreferences를 사용해 객체를 생성하고, 메소드를 사용하여 생성하고, 삭제하고, 수정할 수 있다.

 

[발생 기능]

앱을 실행시키면 Autofill Credentials을 클릭하면, 자동으로 로그인, 패스워드 정보가 입력된다

이는 사용자 디바이스 내에서 불러오는 정보이므로, shared_prefs에 있을 수도 있다고 추측할 수 있다.

 

adb shell 에서

cd /data/data/com.android.insecurebankv2/shared_prefs 해서 이동하고,

ls를 통해 존재하는 파일을 확인하고, cat을 통해 확인한다.

1) WebViewChromiumPrefs.xml

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <int name="lastVersionCodeUsed" value="377014315" />
</map>

2) com.android.insecurebankv2_preferences.xml

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="serverport">8888</string>
    <string name="serverip">192.168.25.51</string>
</map>

3) mySharedPreferences.xml

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="superSecurePassword">RYrcDyKtJRpSlT2Uti4l0g==&#10;    </string>
    <string name="EncryptedUsername">amFjaw==&#13;&#10;    </string>
</map>

이 중 주목해야 할 것은 마지막 xml이고,

취약점이 있는 부분은 모순적이게도 "superSecurePassword"와 "EncrytedUsername"이다.

 

==이 붙은 걸로 봐선 우선적으로 Base64 Encoding을 생각할 수 있었고,

EncryptedUsername은 Decoding 되었다.

 

 

superSecurePassword는 Decoding되지 않았기 때문에

추가적으로 어떤 암호화 또는 인코딩 기법을 사용했는지 소스코드에서 확인이 필요하다.

 

사전지식에서 말한 바와 같이, SharedPreferences를 사용해 객체를 생성하고, 메소드를 사용하여 다루므로

SharedPreferences가 포함된 소스코드를 찾아야 한다.

 

Bytecode Viewer 내 String 검색 기능을 사용한 결과 총 5가지 소스코드에서 발견되었다.

(완전하지 않으므로 100% 신뢰하지는 말 것)

1) DoLogin$RequestTask (확인 불가)

 

2) DoTransfer$RequestDoGets2 

getSharedPreferences를 통해서 /data/data/{앱의 패키지 명}/shared_prefs/ 아래에 있는 "인자값" 파일명을 불러와

SharedPreference 객체에 저장한다.

 

객체.getString으로 EncryptedUsername을 가져와 Base64.decode하는 것으로 보아,

아까 시도했던 Base64가 맞았음을 알 수 있다.

 

아래에 superSecurePassword도 받아와서, DoTransfer.access에 돌린다.

3) DoTransfer$RequestDoTransferTask

→ CryptoClass로 연결됨

UTF-8방식으로 받아온 하드코딩된 key(This is the super secret key 123)과 Base64 decode한 var1을

aes256decrypt함수에 돌린다.

ㄴAES암호화/CBC모드/PKCS5패딩을 사용하여 암호화한다.

 

암호화할 때, 1. 암호화할 문자열 2. 모드 3. 비트 수 4. Secret Key가 사용되고,

여기서 Secret Key가 하드코딩되어 있고,

AES는 암복호화 시 같은 키를 사용하는 대칭키 암호화 알고리즘이므로 복호화할 수 있다.

 

추가적으로 초기화 벡터(IV: Initial Vector)값은 예측할 수 없는 랜덤한 값을 사용해야 한다.

(참고: https://mr-donkey.tistory.com/29?category=802124)

 

https://www.devglan.com/online-tools/aes-encryption-decryption 

 

4) LoginActivity

사실 처음 취약점 기능이라고 생각한 액티비티가 로그인 액티비티이므로, 여기부터 먼저 보는 것이 옳다.

어떤 행위를 하는지 모르는 DoTransfer$RequestDoGets2 보다 더 직관적으로 쉽게 이해할 수 있다.

getString으로 받고, Base64디코딩하여 아이디에, aesDecrypt하여 패스워드에 뿌려준다.(setText)

이후 decrypt 내용은 동일하다.

 

5) MyBroadCastReceiver

 

전부 살펴본 결과, 받아오는 데이터 및 Decrypt 과정은 동일하다는 것을 알 수 있다.

 

 

 

10. Weak Cryptography implementation

결함이 있는 암호화 알고리즘을 사용해 발생

대표적으로 base64와 같은 "암호화"가 아닌 "인코딩"으로 데이터를 감추는 경우와

암호화를 사용하였으나 현대로 오면서 쉽게 복호화 가능한, 결함이 발견된 알고리즘을 사용하는 경우이다.
(DES, SHA-1, MD5)

 

위에서 찾은 것과 동일하다.

 

22. Hardcoded secrets

(1) 위에서 찾은 AES secret key 하드코딩

(2) 테스트 계정 정보 주석

Bytecode Viewer의 String 검색 기능은 불완전하여, 더 명확한 검색 기능을 갖고 있는 프로그램이 필요하다.

또 Bytecode Viewer는 주석까지 완전히 재현해주지 않는 것 같다.

com.android.insecurebankv2

ChangePassword.java, DoLogin.java에 테스트 계정이 그대로 노출되었다고 나와있으나, 찾을 수 없다.

 

Bytecode-Viewer(X)

jd-gui(X)
jadx-gui(X)

 

java 파일은 어떻게 해야 볼 수 있는지?

https://dazemonkey.tistory.com/155 

https://mr-donkey.tistory.com/41?category=802124 

Comments