- 강의 : 안드로이드 모바일 앱 모의해킹과 시큐어코딩
- 3주차 활동 : 섹션 6. 인시큐어뱅크 각 취약점 진단 실습
1. 취약한 브로드캐스트 리시버 취약점
◆ 진단 방법
- AndroidMenifest.xml에 있는 <Receiver> 컴포넌트 점검
- Receiver 컴포넌트가 구현된 해당 클래스의 onReceiver() 메소드 기능 점검
- abd shell
am broadcast -a theBroadcast -n com.android.insecurebackv2/.MyBroadCastReceiver
4. abd로는 System Process로 인해 권한 검사 불가.
5. 따라서 Drozer를 사용하여 진단.
run.app.package.attacksurface com.android.insecurebankv2
run.app.broadcast.info -a com.android.insecurebankv2
◆ 대응 방안
- AndroidManifest.xml에 구현되어 있는 android.exported=”true” 속성을 “false”로 변경하여 외부 노출 금지
- 반드시 필요하다면 permission 속성을 통한 권한으로 접근 제한
2. 안드로이드 백업 취약점
◆ 취약점 소개
- AndroidManifest.xml 파일의 android:allowBackup 속성이 “true”로 설정되어 있는 경우 단말기 백업시 중요 정보 및 인증 정보 노출.
- 사용자가 단말기를 잃어버린 경우 제 3자에 의해 이러한 백업 취약점을 이용해 단말기를 사용하던 사용자의 중요 및 민감정보가 제 3자에게 노출될 수 있음.
◆ 진단 방법
- 안드로이드 단말기에서 비밀번호 입력없이 백업
adb backup -f <backup file name> <package name>
- 출력된 데이터를 분석하여 중요정보/ 인증정보/ 민감정보 획득
java -jar ade.jar unpack <backup file name> <tar file name>
◆ 대응 방안
- AndroidManifest.xml 파일의 android:allowBackup = “false”로 속성을 변경.
3. 로컬 암호화 이슈
◆ 취약점 소개
- 중요 정보가 단말기에 저장될 때 암호화되어 있지 않는 취약점.
- 애플리케이션 안에서 사용되는 중요한 정보는 암호화하여 저장해야 함. 이러한 정보들이 약한 암호화로 저장되거나 암호화가 되어있지 않고 평문으로 저장될 경우 여러가지 문제발생.
- Insecurebackv2 앱에서 사용하는 여러 계정 정보는 암호화를 사용하지 않음. 이러한 정보들이 유출될 경우 사용자는 큰 피해를 받음.
◆ 진단 방법
- 앱의 전반적인 기능들을 실행해보고 탐색
- DB 추출 후 중요정보 암호화 확인
- DB 외의 파일들에서 중요정보 암호화 확인
- 클러이언트단 소스코드 점검 및 암호화 로직 점검
adb pull adb pull/ data/ data/ com.android.insecurebankv2 .\
◆ 대응 방안
- 중요 정보를 다루는 코드 검토
- 중요 정보 암호화 할 수 있도록 코드 추가 및 수
4. 취약한 웹 뷰 구현
◆ 취약점 소개
- 웹뷰상에 UI 또는 패킷에서 자바스크립트 코드가 강제적으로 실행되게 함으로써 다른 사용자의 중요정보를 탈취하는 취약점
- 인시큐어뱅크에서는 자바스크립트 코드가 로컬에서만 실행되게 할 수 있지만 만약 다른 사용자에게 자바스크립트 코드를 보낼 수 있다면 다른 사용자의 중요정보를 탈취할 수 있는 취약점이 될 것.
◆ 진단 방법
- 앱 구동 후 웹뷰가 사용되거나 웹뷰과 연관이 있는 기능들을 검토.
- 웹 뷰가 사용되고 있는 코드들을 검토.
- <script>alert(”XSS”)</script>와 같은 자바스크립트를 실행할 수 있는 명령어들을 웹뷰와 연관되어 있는 UI에 대입.
◆ 대응 방안
- 자바스크립트 코드를 실행하지 못하도록 필터링 하는 코드 추가.
- 계좌가 숫자로 이루어져 있을 경우 숫자이외의 문자열을 사용하지 못하도록 조치.
- Webview 설정 중 setJavaScriptEnabled 메소드를 “false”로 설정.
5. 취약한 SD카드 저장소
◆ 취약점 소개
- 안드로이드는 내부 저장소와 외부 저장소로 나뉘며, SD카드는 외부 저장소로 모든 애플리케이션이 접근가능한 영역.
- 이러한 SD 카드에 중요 정보가 다른 애플리케이션에 의해 노출될 수 있음.
◆ 진단 방법
- AndroidManifest.xml 파일의 권한 중 WRITE_EXTERNAL_STORAGE 권한이 있는지 확인.
- 코드 분석을 통해 getExternalStorgeDirectory() 메소드가 사용되는지 확인, 그렇다면 어떤 정보들이 저장되는지 확인.
- 단말기를 통해 실제 어떤 정보들이 저장되어 있는지 SD 카드에서 확인.
- MODE_WORLD_READABLE 모드가 사용중인지 확인.
◆ 대응방안
- 중요 정보 저장 시 외부 저장소가 아닌 내부 저장소에 저장하도록 코드를 변경.
→ 여기서 내부 저장소란 /data/data/package 디렉토리 내부를 뜻함.
- 중요 정보는 반드시 암호화 될 수 있도록 조치.
6. 취약한 인증 메커니즘
◆ 취약점 소개
- 애플리케이션 사용자의 약한 인증 관리로 침해되서는 안될 부분이 침해 되어 사용자에게 피해를 입히는 취약점
- Insecurebackv2 앱의 Transfer 기능은 약한 사용자 인증으로 인해 From 값을 변조하여 다른 사람의 계좌에서 돈을 보낼 수 있는 취약점이 존재
◆ 진단 방법
- SQLiteBrowser를 활용하여 서버의 DB 점검
- Transfer 기능을 담당하는 컴포넌트의 소스코드 점검
- Insecurebackv2의 서버인 app.py의 소스코드 점검
◆ 대응 방안
- Insecurebankv2의 서버인 app.py에서 인증관련 코드 추가
- 클라이언트에서는 인증 실패 시 fail 메세지가 나오도록 코드 수정
7. 사용자 계정 목록화
◆ 취약점 소개
- 인시큐어뱅크에선 접속한 사용자의 아이디값이 노출되는 문제점 존재.
- 아이디 노출 시 패스워드 무작위 대입 공격이나 사회적인 공격이 가능하므로 제3자에게 사용자들의 아이디값을 노출되는 것은 상당히 위험.
◆ 대응방안
- 중요한 정보들은 반드시 암호화해서 저장, 외부에 노출되지 않도록 내부 저장소에 저장.
◆ 진단방법
- C드라이브에 test 폴더 생성 후 진행
- 안드로이드의 인시큐어 뱅크 앱에서 사용되는 내부 저장소 데이터를 모두 가져온다.
C:\test>adb pull /data/data/com.android.insecurebankv2 .\
3. C:\test\databases에 담겨있는 mydb 파일을 DB Browser for SQLite로 열어본다.
□사용자 로그인 내역: Browse Data > Table > names 에 담겨있는 id 및 name
→ 취약점: 위 부분 노출 시, 사용자 이름 노출.
대응방안: 위 부분 암호화.
private void trackUserLogins() {
//TODO Auto-generated method stub
runOnUiThread() → {
try{
CryptoClass cryptoClass = new CryptoClass();
username = cryptoClass.aesEncryptedString(username);
//또는 String encUsername = cryptoClass.aesEncryptedString(username); ... values.put(TrackUserContentProvider.name, encUsername);
//TODO Auto-generated method stub
ContentValues values = new ContentValues();
values.put(TrackUserContentProvider.name, username);
//inserts content into the Content Provider to track the logged in user's list
Uri uri = getContentResolver().insert(TrackUserContentProvider.CONTENT_UTI, values);
} catch(IOException ex) {
ex.printStackTrace();
}
});
}
@LoginActivity.java
username이 aes암호화 적용 후, put 메소드 입력값으로 들어가, ContentProvider에서 DB에 값 추가됨.
8. 취약한 액티비티 컴포넌트
◆ 액티비티란?
E.g. 로그인 화면 → [로그인 후] → 메인메뉴 → [재생] → 음악듣기
즉, 사용자에게 정보를 보여주거나 데이터를 입력 받는 등의 기능을 제공하기 위해서 사용자와 상호작용 하는 것
◆ 취약점 소개
E.g. 로그인 화면 → 메인메뉴 → [로그인 없이 바로 실행] → 음악듣기
◆ 대응 방안
- AndroidMaifest.xml에 구현되어 있는 android:exported=”true” 속성을 ‘false’로 변경하여 외부노출 금지
- 반드시 필요하다면 Permission 속성을 통한 권한으로 접근제어
- 사용자 인증 절차 추가
<manifest>
<application>
... 중략 ...
<receiver>
android:name=".MyBroadCastReceiver"
android:exported="true"
android:permission="my.app.PERMISSION"
<intent-filter>
<action android:name="theBroadecast">
</action>
</intent-filter>
</receiver>
<activity>
android:name=".ChangePassword"
android:exported="false"
android:permission="ChangePassword"
</activity>
</application>
</manifest>
@manifests
◆ 진단 방법
- AndroidManifest.xml에 있는 <Activity> 컴포넌트 점검
- Activity 컴포넌트가 구현된 해당 클래스의 onCreate() 메소드부터 전체 코드 점검
C:\test>adb shell → am start -n com.android.insecurebankv2/.ChangePassword
//-n 옵션 "패키지명"/."노출된 액티비티의 컴포넌트명"
Starting: Intent < cmp=com.android.insecurebankv2/.ChangePassword >
//BroadCast가 동일하기에 activity의 " android:exported="true"로 설정이 되어있으므로 내부 노출이 된다
<manifest>
<application>
... 중략 ...
<receiver>
android:name=".MyBroadCastReceiver"
android:exported="true"
android:permission="my.app.PERMISSION"
<intent-filter>
<action android:name="theBroadecast">
</action>
</intent-filter>
</receiver>
<activity>
android:name=".ChangePassword"
android:exported="true"
android:permission="ChangePassword"
</activity>
</application>
</manifest>
@manifests
- adb로는 무조건 실행되므로 권한 검사를 할 수 없기 때문에 Drozer를 사용하여 진단한다.
dz> run app.package.attacksurface com.android.insecurebankv2
dz> run app.activity.info -a com.android.insecurebankv2
//노출된 컴포넌트들이 출력된다
dz> run app.activity.start --component com.android.insecurebankv2 com.android.insecurebankv2.ChangePassword
//run app.activity.start를 통해 액티비티를 실행한다
dz> run app.activity.start --component com.android.insecurebankv2 com.android.insecurebankv2.ChangePassword --extra string uname jack
//이때, Activity를 호출하는 경우 name 부분이 비어있으면 password를 입력해도 Activity가 실행되지 않는다.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
set ContentView(R.layout.motivity_change_password);
//Get Server details from Shared Preference file
serverDetails = PreferenceManager.getDefaultSharedPreferences(this);
serverip = serverDetails.getString("serverip", null);
serverport = serverDetails.getString("serverport", null);
changePassword_text = (EditText) findViewById(R.id.editText_newPassword);
Intent intent = getIntent();
uname = intent.getStringExtra("uname"); //Activity를 실행할 때 uname이 전달된다
System.out.printIn("newpassword="+uname);
textView_Username = (TextView) findViewById(R.id.textView_Username);
textView_Username.setText(uname); //setText()로 문자열을 넣어준다
//Manage the change password button click
changePassword_button = (Button) findViewById(R.id.button_newPasswordSubmit);
changePassword_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//TODO Auto-generated method stub
new RequestChangePasswordTask().execute(uname); //클래스 RequestChangePasswordTask()를 통해 서버로 데이터를 전송한다
}
});
}
class RequestChangePasswordTask extends AsyncTask < String, String, String > {
@Overrid
protected String doInBackground(String...parms) {
try{
postData(params[0]);
} catch (InvaildKeyExeception | NoSuchAlgorithmException | NoSuchPaddingException | InvalidA...
//TODO Auto-generated method stub
e.printStackTrace();
}
return null;
}
@Changepassword.java
9. 하드코드 된 중요 정보
◆ 취약점 소개
- 어떤 데이터가 코드 내에 그대로 입력된 것을 하드 코딩 되었다고 함.
- 중요 정보가 소스코드에 그대로 노출되어 있다면 소스코드 노출 시 중요 정보가 그대로 제3자에게 노출될 가능성.
- 개발 시 개발자가 편의를 위하여 입력받아야 할 정보를 소스코드 내에 바로 입력함으로써 실행 시 UI 상에서 입력하지 않고 바로 실행하도록 하는 것도 하드 코딩된 취약점 중 하나.
- 인시큐어뱅크 앱에서는 총 3곳에서 하드코딩 된 취약점을 발견할 수 있음.
◆ 진단 방법
- 코드 분석 시 암호화 클래스 부분을 상세 분석.
- 중요 정보 문자열 검색을 통해 검토 및 조치. Find > Found Occurences: Jack의 비밀번호 “Jack@123$”을 검색
public class CryptoClass {
//The super secret key used by the encryption function
String key = "This is the super secret key 123"; //"This is the super secret key 123"가 암호화 키에 해당되며, 그대로 노출되어 있다.
//The initialization vector used by the encryption function
byte[] ivBytes = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
String plainText;
byte[] cipherData;
String base64Text;
String cipherText;
/*
The function that handles the aes256 encryption
ivBytes: Initialization vector used by the encryption function
keyBytes: Key used as input by the encryption function
textBytes: Plaintext input to the encryption function
*/
public static byte[] aes256encrypt(byte[] ivBytes, byte[] keyBytes[], byte[] textBytes[])
throws UnsupportedEncodingException,
NoSuchAlgorithmException,
NoSuchPaddingException,
}
@CrytoClass.Java
10. 취약한 암호화 구현
◆ 취약점 소개
- 중요한 데이터가 취약한 암호화 방식으로 저장되어 제3자가 암호화된 데이터를 문제없이 해독 가능한 취약점
- E.g. 암호화된 데이터 → 데이터 유출 → 제3자에 의해 복호화 → 복호화된 데이터
◆ 대응 방안
- 문제는 대칭키가 노출되는 것이 아닌 모든 단말기에 설치되는 어플리케이션의 대칭키가 같다는 것.
- 다른 단말기에 설치된 어플리케이션의 대칭키가 같다면 데이터 유출 시 데이터 복호화가 가능.
- 따라서, 단말기마다 고유의 대칭키를 갖도록 조치.
public class CryptoClass {
// The super secret key used by the encryption function
//변경 전: String key = "This is the super secret key 123";
/*변경 후:*/ String key = "null";
// The initialization vector used by the encryption function
byte[] ivBytes = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
String plainText;
byte[] cipherData;
String base64Text;
String cipherText;
//클래스 새로 정의
public CryptoClass(Context ctx){
TelephonyManager manager (TelephonyManager)ctx.getSystemService(Context.TELEPHONY_SERVICE);
//어플리케이션 컨텍스트를 컨텍스트를 이용해서 가져온다
key = manager.getDeviceId() + Build.DEVICE;
if (key.length() != 32){
int i = 32 - key.length();
for (; i!=0; i-=1) {
key += "0";
}
Log.i("LOG",key);
}
//32자리로 키를 맞춰준다
}
/*
...
*/
//이후 컨텍스트 내용을 모두 수정한다.
//수정 전: CryptoClass crypt = newCryptoClass();
//수정 후:// CryptoClass crypt = newCryptoClass(getApplicationContext());
◆ 진단 방법
- 소스코드에서 초기화 벡터값 추출
- 소스코드에서 대칭키 추출
- 암호화 모드 확인: EBC / CBC / CFB / OFB
- 암호화 비트 확인: 128 / 256
- 코드에 인코딩이 되어있는 경우 인코딩 방식 확인
- 암호화/복호화 툴 제작 또는 사이트에서 대칭 키로 암호화된 데이터 복호화
- Base64 Encode & Decode: https://www.base64decode.org/
- AES Tool(전문가): http://aes.online-domain-tools.com/
- AES Tool: http://aesencryption.net/
- 기본 암호화 모드: CBC
- 벡터값: 00
- 복호화 시 기본 base64 디코딩 제공
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name='superSecurePassword'>tyrof6jLedNWZw/e/a98EQ==
</string>
<string name='superSecurePassword'>Fupu7GCRhqWoxviAuixpMg==
</string>
</map>
//aesEncryptedString로 암호화된 데이터 예시 [E.g. tyrof6jLedNWZw/e/a98EQ==, Fupu7GCRhqWoxviAuixpMg==]
@mySharedPreferences.xml | 암호화된 데이터를 확인 가능
private void saveCreds(String username, String password) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
// TODO Auto-generated method stub
SharedPreferences mySharedPreferences;
mySharedPreferences = getSharedPreferences(MYPREFS, Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = mySharedPreferences.edit();
rememberme_username = username;
rememberme_password = password;
//String base64Username = new String(Base64.encodeToString(rememberme_username.getBytes(), 4));
CryptoClass crypt = new CryptoClass();;
//암호화 클래스를 사용한다.
superSecurePassword = crypt.aesEncryptedString(rememberme_password);
//aesEncryptedString를 통해 패스워드와 유저네임을 암호화한 후 저장한다
editor.putString("EncryptedUsername", base64Username);
editor.putString("superSecurePassword", superSecurePassword);
editor.commit();
//encrypt된 데이터를 저장한다
}
@DoLogin.Java
- 탐색: keyBytes 중심으로
public static byte[] aes256encrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes)
throws UnsupportedEncodingException, ... BadPaddingException {
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = null;
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
return cipher.doFinal(textBytes);
}
- 소스코드에서 대칭 키 추출: byte[] keyBytes = key.getBytes("UTF-8");
public String aesEncryptedString(String theString) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
// TODO Auto-generated method stub
byte[] keyBytes = key.getBytes("UTF-8");
//UTF-8로 된 Byte로 인코딩
plainText = theString;
cipherData = CryptoClass.aes256encrypt(ivBytes, keyBytes, plainText.getBytes("UTF-8"));
cipherText = Base64.encodeToString(cipherData, Base64.DEFAULT);
return cipherText;
}
- 소스코드에서 초기화 벡터값 추출: byte[] ivBytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
public class CryptoClass {
// The super secret key used by the encryption function
String key = "This is the super secret key 123";
// The initialization vector used by the encryption function
byte[] ivBytes = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
String plainText;
byte[] cipherData;
String base64Text;
String cipherText;
- 암호화 모드 확인: cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
public static byte[] aes256encrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes)
throws UnsupportedEncodingException, ... BadPaddingException {
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = null;
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
return cipher.doFinal(textBytes);
}
- 암호화 비트 확인: 256
public class CryptoClass {
// The super secret key used by the encryption function
String key = "This is the super secret key 123";
//32자리 = 256bit
- 코드에 인코딩이 되어있는 경우 인코딩 방식 확인:
public String aesEncryptedString(String theString) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
// TODO Auto-generated method stub
byte[] keyBytes = key.getBytes("UTF-8");
plainText = theString;
cipherData = CryptoClass.aes256encrypt(ivBytes, keyBytes, plainText.getBytes("UTF-8"));
//cipherData는 전송할때 바이너리 형식이므로 데이터 전송 시 문제 발생 가능하다
cipherText = Base64.encodeToString(cipherData, Base64.DEFAULT);
//이에 cipherText 변수에 Base64 인코딩을 시도한다
return cipherText;
}
=> [E.g. tyrof6jLedNWZw/e/a98EQ==, Fupu7GCRhqWoxviAuixpMg==]는 Base64 인코딩된 문장
- 암호화/복호화 툴 제작 또는 사이트에서 대칭 키로 암호화된 데이터 복호화:
@CryptoClass.java | 암호화 클래스
11. (보충) Transfer 버그픽스 수정
1. Username에 옳지 않은 값이 출력되는 상황
HttpPost httppost = new HttpPost(protocol + serverip + ":" + serverport + "/getaccounts");
SharedPreferences settings = getSharedPreferences(MYPREFS2, 0);
final String username = settings.getString("EncryptedUsername", null);
/*버그 픽스 시작*/
CryptoClass crypt = new CryptoClass(getApplicationContext());
try{
usernameBase64ByteString = crypt.aesDecryptedString(username);
} catch(Exception ex){
ex.printStackTrace();
}
//주석 처리
/*byte[] usernameBase64Byte = Base64.decode(username, Base64.DEFAULT);
try {
usernameBase64ByteString = new String(usernameBase64Byte, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
/*버그 픽스 끝*/
final String password = settings.getString("superSecurePassword", null);
try {
// Stores the decrypted form of the password from the locally stored shared preference file
passNormalized = getNormalizedPassword(password);
} catch (InvalidKeyException | UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
2. UserID, Username이 잘못된 형태로 전달이 되고 있는 상황
@Override
protected String doInBackground(String...params) {
String str = "";
str = "dinesh";
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(protocol + serverip + ":" + serverport + "/dotransfer");
SharedPreferences settings = getSharedPreferences(MYPREFS2, 0);
final String username = settings.getString("EncryptedUsername", null);
/*버그 픽스 시작*/
CryptoClass crypt = new CryptoClass(getApplicationContext());
try{
usernameBase64ByteString = crypt.aesDecryptedString(username);
} catch(Exception ex){
ex.printStackTrace();
}
//주석 처리
/*byte[] usernameBase64Byte = Base64.decode(username, Base64.DEFAULT);
try {
usernameBase64ByteString = new String(usernameBase64Byte, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
/*버그 픽스 끝*/
final String password = settings.getString("superSecurePassword", null);
try {
// Stores the decrypted form of the password from the locally stored shared preference file
passNormalized = getNormalizedPassword(password);
} catch (InvalidKeyException | UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
@DoTransfer.java
12. 취약한 로깅 메커니즘
◆ 취약점 소개
- 로그(Log)는 프로그램 구동 시 프로그램의 현재 상태, 처리하는 데이터 정보 의미.
- 로그를 통해 관리자나 개발자는 중요한 정보를 제공받을 수 있으며, 특히 프로그램에 버그(취약점)가 있을 때 이를 유지보수 하는데 사용할 수 있음.
- 취약한 로깅 메커니즘은 이러한 로그에 노출되어서는 안되는 중요한 데이터 또는 민감한 데이터가 로그로 남기는 경우를 말함.
◆ 대응 방안
- 앱 배포 시 사용되는 로그 관련 코드를 제거.
- 로그를 출력하는 유틸리티 클래스를 제작.
◆ 진단 방법
- 로그 수집기를 실행하고 앱의 여러가지 기능 사용
- 로그 수집기에서 단어 검색을 통한 중요 데이터 또는 민감 데이터 검색
- 안드로이드 스튜디오에서 제공하는 Logcat을 사용하여 진단
- 소스코드에서 로그 관련 코드 상세 분석
- 안드로이드 로그의 등급
- V(Verbose): 중요하지 않은 정보
- I(Info): 일반 정보
- D(Debug): 디버그 정보
- W(Warning): 광고 정보
- E(Error): 에러 정보
- F(Fatal): 중요한 정보
- S(Slient): 가장 높은 우선 순위의 정보
1. Logfilter 실행
C:\android_edu\tools\android-logviewer>java -jar Logfilter_1.8.jar
2. 이후 cmd에서 PID 검색 후 Logfilter에서 PID 번호로 탐색
C:\...>adb shell ps
USER PID PPID USIZE RSS WCHAN PC NAME // 두번째 열이 PID값에 해당한다.
root 1 0 292 208 c0099f1c 0000c410 S /init
...
u0_a46 15154 27986 166188 44052 ffffffff 40033a40 S com.android.insecurebankv2
3. AndroidStudio
3-1. 메소드 제작
//로그는 대체로 System.out이라는 메소드로 출력되므로 System.out.printIn을 탐색한다
@LogUtil.java
package com.android.insecurebankv2;
/*
Created by Tester on 'YY/MM/DD'
*/
public class LogUtil {
public static boolean isDebug = true;
public static LogOut(String str){
if(isDebug == true) {
//모든 로그에서 isDebug라는 값으로 로깅 여부에 대해 체크 가능
System.out.print(str);
//str로 인자를 넘겨서 로그를 출력한다
}
}
//로그 유틸리티 추가도 가능
/*
public static void LogD(String Str) {
if(isDebug == true) {
Log.d("TAG",str);
}
}
public static void LogI(String Str) {
if(isDebug == true) {
Log.i("TAG",str);
}
}
*/
}
3-2. 로그를 출력하는 메서드를 유틸리티 클래스로 변경
3-2-1. System.out.printIn를 검색 후 변경
@ChangePassowrd.java
//System.out.printIn 변경
{
...
if (TextUtils.isEmpty(phoneNumber.toString().trim())) {
//System.out.printIn("Phone number invalid'); -> 해당 부분 주석 처리
LogUtil.LogOut("Phone number invalid');
}
else {
...
}
...
}
@DoTransfer.java
@LogUtil.java
@MyBroadCastReceiver.java
@ViewStatement.java
3-2-2. Log.를 검색 후 log.d, log.i로 출력하는 모든 문자 검색 후 변경
@CryptoClass.java
{
...
{
...
{
...
int i = 32 - key.length();
for(; i != 0; i -= 1) {
key += "0";
}
}
//Log.i ; ("Log", key); -> 해당 부분 주석 처리
LogUtil.LogOut(key);
}
}
@DoLogin.java
{
...
{
...
{
result = result.replace('\n', );
if (result != null) {
if (result.index0f("Correct Credentials") != -1) {
//Log.d("Successful Login:", ", account=" + username + ":" + password);
LogUtil.LogOut("Successful Login: , account=" + username + ":" + password);
saveCreds(username, password);
trackUserLogins();
Intent pL = new Intent(getApplicationContext(), PostLogin.class);
pL.putExtra("uname", username);
...
}
...
}
}
}
}
13. 안드로이드 페이스트보드 취약점
◆ 취약점 소개
- 사용자의 중요한 데이터 (암호, 계좌번호 등)가 메모리에 노출되어 있는 취약점
◆ 대응 방안
- 중요한 데이터는 가급적 복사하지 않고 직접 입력
- 앱 UI 설계 시 중요한 데이터는 복사하지 못하도록 Password Text Edit View로 제작
◆ 진단 방법
- 진단 대상 안드로이드 앱에서 취약하거나 또는 중요한 항목을 복사
- 페이스트보드 검사
C:\...>adb shell su <user> service call clipboard 2 s16 com.android.insecurebankv2
//<user>는 userid를 의미한다. 즉, adb shell ps 명령어를 통해 출력된 결과 중 USER 값읍 입력하면 된다.
//s16은 string으로 값을 불러오겠다는 것을 의미한다.
//노출된 계좌번호
Result: Parcel<
0x00000000: 00000000 00000000 00000000 00000000 '/...........'
0x00000010: 00000000 00000000 00000000 00000000 '/....t.e.x.t.'
0x00000020: 00000000 00000000 00000000 00000000 '/.plain.....'
0x00000030: 00000000 00000000 00000000 00000000 '/...........'
0x00000040: 00000000 00000000 00000000 00000000 '/.9.9.9.9.9.'
0x00000050: 00000000 00000000 00000000 00000000 '/9..........'
0x00000060: 00000000 '/... '
14. 애플리케이션 패칭 취약점
◆ 취약점 소개
- 클라이언트 어플리케이션 보안이 요구되는 현 시점에서 가장 문제가 많은 취약점 중 한가지
- 안드로이드의 클라이언트 코드를 변경하여 비정상적인 작동을 유도하도록 APK 파일을 변조 및 수정 ⇒ 리패키징
- 서버 인증이 아닌 클라이언트 단의 인증을 우회함으로써 여러가지 인증 절차를 무력화 시킬 수 있음
◆ 대응 방안
- 배포용 APK 소스코드에 프로가드(Proguard)를 적용. >build.gradle 파일에서 minifyEnable 속성 true 변경
- 난독화 솔루션을 사용.
- 에러기반 난독화: apkprotect
- 코드 난독화: proguard
- 멀티덱스 난독화: 외부 상용 솔루션
- 문자열 난독화: 외부 상용 솔루션
- 앱의 Signing 키 검증을 사용.
keytool -list -printcert -jarfile apkfilename.apk
#프로가드 적용
buildTypes{
release {
false true
//minifyEnalbed true로 변경 후 sync now 실행 시, proguard가 적용된 APK 파일 빌드
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro...
}
}
=> 이후 클래스, 변수, 메소드 이름 등이 변경된 것을 확인할 수 있다
@build.gradle
#에러기반 난독화 | apkprotect
-> dex2jar 도구 에러를 유발시켜 사용하지 못하게 하는 기능
1. app-release_apkcrypt.exe 실행
*THE APK: C:\android_edu\tools\Android-InsecureBankv2-master\InsecureBankv2\app\app-release.apk //app-release.apk의 경로
*NEW NAME: app-release_apkcrypt.exe
2. APK crypt된 파일을 dex2jar 도구를 이용해 byte 코드로 변환
C:\android_edu\tools\Android-InsecureBankv2-master\InsecureBankv2\app>dex2jar app-release_apkcrypt.apk
-> jd-gui 도구를 이용해 파일이 열리지 않는다는 것을 확인할 수 있음
@C:\android_edu\tools\APK Protect PC Edition v1.0\apkcrypt.exe
◆ 진단 방법
- APK 파일에서 자바 코드 추출 ⇒ dex2jar, jd-gui 사용
- 난독화 적용 여부 체크
- 에러기반 난독화: apkprotect
- 코드 난독화: proguard
- 멀티덱스 난독화: 외부 상용 솔루션
- 문자열 난독화: 외부 상용 솔루션
- APK 파일에서 Smali 코드 추출 (자바 코드와 비교 분석)
Cf. Smali는 “java의 어셈블리화”로, 기계어와 명령어가 1대1로 대응하는 코드
- Smali 코드 변조
- APK 파일 리패키징 후 설치 및 테스트
#Smali 코드 추출
C:\\android_edu\\tools\\Android-InsecureBankv2-master\\InsecureBankv2\\app>apktool d app-release.apk
//-d 옵션: decompile(디컴파일)
#Java 코드 추출
C:\\android_edu\\tools\\Android-InsecureBankv2-master\\InsecureBankv2\\app>dex2jar app-release.apk
#Java 바이크 코드 Viewing
: jd-gui 도구 사용
#리패키징 및 테스트
: isDebug에 있는 값에서 false(0)를 true(1)로 변경 후 로그가 보이는 지 재확인
이후 C:\\android_edu\\tools\\Android-InsecureBankv2-master\\InsecureBankv2\\app>apktool d app-release
#Java 바이트 코드로 변환
C:\\android_edu\\tools\\Android-InsecureBankv2-master\\InsecureBankv2\\app\\app-release\\dist>dex2jar app-release.apk
이후 isDebug 속성이 true로 변경된 경우, 정상적으로 리패키징 완료
#Signing
C:\\android_edu\\tools\\Android-InsecureBankv2-master\\InsecureBankv2\\app\\app-release\\dist>C:\\android_edu\\tools\\signing\\signing.bat C:\\android_edu\\tools\\Android-InsecureBankv2-master\\InsecureBankv2\\app\\app-release\\dist\\app-release.apk
: 출력된 비밀번호가 123123이다.
#변조한 apk 파일 설치
C:\\android_edu\\tools\\Android-InsecureBankv2-master\\InsecureBankv2\\app\\app-release\\dist>adb install
15. (보충) 애플리케이션 패칭 응용
멀티덱스 난독화
#소스코드 추출
1. C:\\android_edu\\malware>apktool d naver.apk
2. C:\\android_edu\\malware>dex2jar naver.apk
3. C:\\android_edu\\malware>adb install naver.apk
4. 이후 jd-gui.exe로 파일 열기
- naver_dex2jar.jar | com\android\systemsetting\FtApp.class
- 아이콘이 사라지는 기능이 코드에 존재하지 않음.
- androidmainfest.xml에서 main activity(소스코드의 진입점)이 보이지 않음.
0. 설정에서 기기관리자 권한 해제
1. C:\android_edu\malware>adb uninstall com.android.expsetting
2. FtApp 클래스 내부에 delete가 들어간 부분 제거
3. C:\android_edu\malware>apktool b naver.apk
//Q. smali 코드에서 패칭을 시도하는 이유
//A. 자바 파일로 추출 시, 완전한 코드가 아니므로 컴파일 후 재빌드 시 Java 파일로 변환하면서 에러 발생 가능
4. C:\android_edu\malware>apktool b naver.apk
//복호화 파일이 생기는 경로: "/data/data/"+'package name'
5. 앱 실행 (실행해야 코드가 나타나고 앱이 지워지지 않는다)
6. C:\android_edu\malware>adb shell
root@android:/ #cd /data/data/com.android.expsetting
root@android:/data/data/com.android.expsetting # ls
ls
cache
database
lib
x
x.zip
root@android:/data/data/com.android.expsetting # adb pull /data/data/com.android.expsetting .\
//로컬 PC로 파일을 가져온다
7. C:\android_edu\malware\naver\dist>dex2jar classes.dex
//압축 해제한 class_dex2jar.jar 파일에서 찾지 못했던 코드들이 숨겨져 있는 것을 확인할 수 있다.
16. 개발자 백도어 취약점
◆ 취약점 소개
- 개발 백도어란 개발 단계 시 개발자가 편의를 위해 개발자 자신만이 들어갈 수 있는 계정이나 인증 우회 방법.
- 주로 개발 단계 시 사용하지만 잘못된 빌드 프로세스로 배포용 어플리케이션 또는 서버에 개발 백도어 코드가 삽입되면 보안에 중대한 취약점이 발생.
◆ 대응 방안
- 배포용 어플리케이션 빌드 전 개발 백도어 코드 제거
- 서버 애플리케이션 배포 전 개발 백도어 코드 제거
◆ 진단 방법
- 클라이언트 부분에서 로그인 부분의 소스코드를 상세 분석
- 서버 부분에서 로그인 처리 부분의 소스코드를 상세 분석
- 코드 분석을 바탕으로 백도어 사용 후 검증
{
...
{
...
//하단 부분 주석 처리
/*
if (username.equals("devadmin")) {
httppost2.setEntity(new UrlEncodedFormEntity(nameValuePairs));
//Execute HTTP Post Request
responseBody = httpclient.execute(httppost2);
} else {
*/
//하단 명령어는 정상적인 로그인 절차를 수행하는 코드
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
//Execute HTTP Post Request
responseBody = httpclient.execute(httppost);
//}
...
}
@DoLogin
'''
The function provides login methchanism to a developer user during development phase
'''
//하단 부분 주석처리
'''
@app.route('/devlogin', methods=['POST'])
def devlogin():
user=request.form['username']
Responsemsg="Correct Credentials"
data = {"message" : Responsemsg, "user" : user}
print makejson(data)
return makejson(data)
'''
if __name__ == '__main__':
port = DEFAULT_PORT_NO
options, args = getopt.getopt(sys.argy[1:], "", "port=="])
for op, argl in options:
if op == "--help":
usageguid()
sys.exit(2)
elif op == "--port":
port = int(arg1)
dispatch = wsgiserver.WSGIPathInfoDispatcher({'/': app})
...
@Server의 app.py
17. 루트 노출 및 우회 취약점
◆ 취약점 소개
- 루팅이란?
안드로이드는 보안 목적으로 기본적으로 루트 권한을 사용자가 획득할 수 없도록 막아둠.
사용자가 루트권한을 획득하는 것.
- 루팅된 단말기는 앱에서 허용하지 않은 동작 수행하므로 보안에 취약.
그래서 앱에선 루팅 탐지 로직, 실행 차단 로직이 있으나, 해당 조치를 우회.
◆ 진단 방법
- 루팅 탐지 로직 - 해당 파일 존재여부
/system/bin/su
/system/xbin/su
/sustem/app/superuser.apk ; su 프로그램 다운로드 및 숨김 역할.
/data/data/com.noshufou.android.su
-인시큐어뱅크의 경우
소스코드 .java 있다면) 프로그램 Anroid studio에서 "su", "superuser" 문자열 검색.
PostLogin.class 파일 > doesSUexist() 메서드에서 su 파일,
> doessuperuserapkexist() 메소드에서 superuser.apk 파일 존재 확인.
public void ShowRootStatus() {
if (doesSuperuserApkExist("/system/app/Superuser.apk") || doesSUexist() {
this.root_status.setText("Rooted Device!");
} else {
this.root_status.setText("Device not Rooted!!");
}
}
private boolean doesSUexist() {
Process process = null;
try{
process = Runtime.getRuntime().exec(new String[]{"/system/xbin/which","su"});
if (new BufferedReader(new InputStreamReader(precess.getInputStream())).ReadLi
if (process != null) {
pricess.destrou();
}
.apk만 있다면) dex2jar insecure.apk로 .java 파일 추출, 디컴파일 선행.
- Tool
-Android Studio: 최근 안드로이드 개발 및 분석 시 사용.
-Eclipse: 자바, 안드로이드 개발 및 분석에도 유용.
-app-release.apk AndroidManifest.xml res폴더만 남겨두고, DoLogin.java 분석.
-분석시 유용한 기능.
- 문자열 검색 시, 하이라이팅. 더블클릭 시 동일 문자열 다음위치로 이동.
- F3 단축키, 메서드들 정의 위치 이동. Open Declaration
- Search > File Search > 'Super'(Ctrl+h) 모든 프로젝트 범위 대상으로 검색 가능
- 리패키징(문자열 삭제)으로 루트 탐지 로직 우회
insecurebankv2.apk 파일에서 smali 파일 추출.
프로그램 Notepadd++, insecurebankv2 smali폴더 postligin.java파일에서,
Superuser/su 문자열 난독화 예) abcSuper123456
프로그램 삭제 후 재다운로드 결과, 루팅 탐지 실패결과 확인.
◆ 대응 방안
- 루팅 탐지 시 앱 종료 코드 추가 - 실습 Only.
if(isrooted==true)
android.os.Process.killProcess(android.os.Process.myPid()) // 조건문 아래 해당 명령문 추가!
- 멀티 덱스 난독화 솔루션 사용 ( 리패키징할 Superuser/su 못 찾도록)
- 문자열 기반 난독화 솔루션 사용
18. 파라미터 조작
◆ 취약점 소개
- 클라이언트와 서버가 통신할 때 중간에 패킷을 가로채서 파라미터를 변조하는 취약점
- 정상적인 요청 값을 공격자가 변조하여 정보 유출 등의 피해가 발생
- 파라미터 조작을 통해 인증 우회도 가능
◆ 인시큐어뱅크 앱에서 실습
- 인시큐어뱅크 로그인 후 비밀번호 변경 기능을 사용할 때 발생하는 취약점으로, 다른 사용자의 비밀번호 변경이 가능한 취약점
- 실제 모의해킹에서 충분히 발생할 수 있는 취약점 중에 하나
- 대량의 사용자 비밀번호 변경으로 개인정보 및 금융정보 등을 획득할 수 있는 크리티컬한 취약점
◆ 대응 방안
- 파라미터 값을 암호화하여 조작 불가능하도록 해야 함
- 세션 값 검증을 통해 다른 사용자 계정에 대한 조작이 불가능하도록 해야 함
- 파라미터 조작을 통한 입력 값에 대한 유효성 검증은 서버에서 검증하도록 해야 함
- 비밀번호 변경 기능을 사용할 때 아이디로만 인증하는 것이 아닌 이전 비밀번호도 포함하여 인증하도록 강화해야 함
- 비밀번호 변경 시 통신은 HTTP가 아닌 HTTPS로 통신하도록 암호화 적용이 필수
19. (보충) 파라미터 조작
◆ 취약점 소개
- Password 틀려도 인증을 우회하는 방법 > 프로그램 Reply 공격 "Wrong Password" String 변경
◆ 대응 방안
- Reponse 속 ["message": "Correct Credentials", "user": "dinest"} 메세지 전체 암호화 소스코드 변경
20. 취약한 비밀번호 변경 로직
◆ 취약점 소개
- 인시큐어뱅크 앱의 비밀번호 변경 기능 사용 시 취약한 인증으로 인해 제3자가 비밀번호 변경이 가능한 취약점. (취약한 액티비티에서 다룸)
- 실제 배포되는 앱에 해당 취약점이 있다면 제3자가 대량의 사용자 비밀번호 변경을 통해 중요정보 및 민감정보를 획득할 수 있는 중대한 취약점.
◆ 진단 방법
- 패킷 캡처하는 환경 세팅
- 앱 구동 후 주요 기능 확인.
- 비밀번호 변경 기능
- 사용자 정보 변경 가능
- 문자 인증 기능
- 캡처된 패킷의 인증정보 및 세션 등 검토
- (선택, 모의해킹) 파라미터 변조 / 재생공격 등을 통해 캡처된 패킷에 대한 인증 및 세션 검토.
◆ 대응 방안
- 중요정보 및 민감정보를 얻어낼 수 있는 주요기능에 대한 인증 강화.
- 인시큐어뱅크에 구현된 비밀번호 변경은 사용자의 아이디만을 통해 인증하므로 변경 전 비밀번호를 입력하게 하여 인증을 강화한다. (실습)
- 비밀번호는 중요데이터에 속하므로 전송 시 평문이 아닌 반드시 암호화를 적용하여 전송. (실습)
# InsecureBankv2\app\src\main\java\com\android\Insecurebankv2\ChangePassword
# 144번째 줄
CryptoClass cryptoClass = new CryptoClass(getApplicationContext());
String currentPassword = currentPassword_text.getText().toString();
String changePassword = changePassword_text.get
21. 중요 정보 메모리 노출 취약점
◆ 취약점 소개
- 앱에서 사용하는 중요한 정보들은 암호화 적용, 메모리로 올라오면 평문으로 노출되는 취약점
- 중요한 정보가 암호화되어 있더라도 메모리에 올라가면서 복호화되는 점을 이용.
◆ 진단 방법
- 프로그램 Android Studio > Tool > Android > Android Device Moniter 실행
*안드로이드 스튜디오3.1에서 지원중단, 안드로이드 스튜디오3.2에서 삭제
- 진단 대상 앱 설치 후 중요정보 사용하는 기능 실행
- 앱의 프로세스를 Android Device Moniter 툴로 Heap 메모리 덤프
- 메모리 덤프 결과 분
◆ 대응 방안
- 메모리 (변수)에 중요정보를 저장할 때는 반드시 암호화해서 저장 조치.
- AndroidManifest.xml 파일에 있는 android:debugable 속성 "false"로 지정.
22. 애플리케이션 디버깅 취약점 & 런타임 조작
◆ 취약점 소개
◆ 진단 방법
◆ 대응 방안
23. 취약한 HTTP 전송
◆ 취약점 소개
- 본래 HTTP는 보안을 고려햐어 설계되지 않은 프로토콜로 보안에 대한 결함이 존재
- 같은 네트워크 상에서 제 3자에 의해 스니핑 당할 경우 암호화되지 않은 HTTP의 데이터는 평문 그대로 노출될 수 밖에 없음
◆ 진단 방법
- 웹 프록시 구동 후 단말기에서 패킷을 받아올 수 있는 환경을 구성
- 어플리케이션 구동 후 주요 기능 사용
- 통신 구간 중 중요 정보 및 세션 정보가 사용되는 통신 구간에서 HTTPS가 사용되는지 확인
◆ 대응 방안
- 중요한 정보가 HTTP 패킷에 포함되어 잇을 경우 암호화하도록 함
- 세션과 같이 HTTP 자체에 암호화를 사용해야 하는 경우 반드시 SSL 통신을 하도록 함
24. 중복 로그인
◆ 취약점 소개
- 서로 다른 단말기에서 중복으로 로그인을 할 수 있는 기능
- 중복 로그인은 상황에 따라 취약점으로 분류(e.g.필요하지 않은 기능이라면)
- 악의적인 사용자가 다른 사용자의 계정을 사용할 수 있으며, 노출된 계정에 대해 계속 무방비 상태로 방치
◆ 대응 방안
- 중복 로그인이 되지 않도록 서버에서 세션관리를 진행함
- 중복 로그인이 발생되었을 경우 사용자에게로 SMS 또는 메일과 같은 알림 수단으로 알리도록 함
25. 취약한 컨텐트 프로바이더
◆ 취약점 소개
- 안드로이드에는 총 4종류의 컴포넌트 존재
- Activity
- Service
- Broadcast Receiver
- Content Provider
- 컨텐트 프로바이더는 현재 어플리케이션이 가진 데이터를 외부의 어플리케이션에 제공해주는 역할을 함
- 예)페이스북이 주소록의 컨텐트 프로바이더를 사용하여 친구를 추천하는 기능을 제공함.
- 취약한 컨텐트 프로바이더는 잘못된 접근권한으로 외부의 다른 어플리케이션이 내부의 주한 데이터에 엑세스할 수 있는 취약점
◆ 진단 방법
- AndroidManifest.xml 파일에서 <provider>태그의 속성 중 android:exported 속성이 “true”로 되어있는지 확인
- drozer을 사용하여 진단
# 명령을 이용하여 노출된 content provider 항목 수 확인
run.app.pachage.attacksurface com.android.insecurebankv2
# 노출된 프로바이더의 정보를 확인
run [app.provider.info](http://app.provider.info) -a com.android.insecurebankv2`
# 접근 가능한 URI를 확인
run.scanner.provider.finduris -a com.android.insecurebankv2
◆ 대응 방안
- AndroidManifest.xml 파일에서 <provider> 태그의 android:exported 속성을 “false”로 설정
- 외부와의 데이터 교환이 필요할 경우, Permission 속성을 통한 권한으로 접근제한
26. 안드로이드 키보드 캐시 취약점
◆ 취약점 소개
- 안드로이드에서 과거에 입력되었던 정보를 유추할 수 있는 취약점
- 사용자가 중요정보를 클립보드에 저장하면 이러한 정보를 획득할 수 있는 취약점
◆ 진단 방법
- 진단 대상이 되는 앱 실행 후 중요정보를 복사할 수 있는 기능이 있는지 확인
- org.rojekti.clipper와 같은 클립보드에 접근할 수 있는 앱을 설치한 후 중요정보 복사시 중요정보가 노출되는지 확인
마스킹 처리가 된 비밀번호의 경우
- EditText 뷰의 값을 복사, 붙여넣기 할 수 없도록 android:editable 속성에 false 값을 줌
- 중요한 값은 반드시 마스킹 처리
'4-2. 2024-1 심화 스터디 > 안드로이드 모의해킹' 카테고리의 다른 글
[7주차] 블레이드러너 - 안드로이드 모의해킹 (0) | 2024.06.01 |
---|---|
[6주차] 블레이드러너 - 안드로이드 모의해킹 (0) | 2024.05.16 |
[5주차] 블레이드러너 - 안드로이드 모의 해킹 (0) | 2024.05.14 |
[2주차] 블레이드러너 - 안드로이드 모의해킹 (1) | 2024.03.24 |
[1주차] 블레이드러너 - 안드로이드 모의해킹 (0) | 2024.03.22 |