회사에서 상반기 하반기를 나누어 사내 보안팀이 '모의해킹' 팀을 고용하여 회사 내 자체 서비스 App을 모의해킹 한다.
그에 맞춰 이번에 작성하게 될 주제가 선정되었다.
사실 아래에 여러가지 방법들을 소개해줄 예정이지만,
가장 좋은 건 보안업체 SDK 를 사용하여 보안취약점 대응을 하는게 좋다. (우리 회사는 당연히 외부 라이브러리 보안 SDK 사용 중)
우리 회사에서 사용하고 있는 보안 관련 SDK 업체는 라온시큐어, 시큐센, 스틸리언 이 있다.
그 외에 다른 회사들도 있으니 보안은 보안업체에 맞겨 대응을 하고 우리 안드로이드 개발자는 고객을 위한 서비스에 집중을 하면 된다.
위와 같은 보안 관련 SDK 없이 어떤 방법으로 앱 보안 취약점에 대응할 수 있을지 몇 가지 소개하겠다.
사실 아래 방법들은 검색하면 잘 알려져 있고, 그냥 전체적으로 정리 했다고 생각하면 된다.
TL;DR
1. 루팅 탐지
2. 'Su' 루트 실행 권한 있는지 확인
3. 루팅 우회 탐지(프리다)
4. 디버깅 툴 탐지
5. 타 스토어에서 설치된 앱 체크
#1. 루팅 탐지
루팅된 기기에서 사용되는 바이너리 파일 경로에 루팅 탐지 관련 몇 가지 텍스트를 확인해보는 방법이다.
/system/build.prop 파일에 test-keys 값이 존재하는 지 확인
private static Boolean checkTestKey() {
String tag = android.os.Build.TAGS;
return tag != null && tag.contains("test-keys");
}
바이너리 파일 경로에 루팅탐지 관련 텍스트 확인
/**
* 루팅된 기기에서 사용되는 바이너리 파일 경로
*/
private static final String[] binaryPaths = {
"/data/local/",
"/data/local/bin/",
"/data/local/xbin/",
"/sbin/",
"/su/bin/",
"/system/bin/",
"/system/bin/.ext/",
"/system/bin/failsafe/",
"/system/sd/xbin/",
"/system/usr/we-need-root/",
"/system/xbin/",
"/system/app/Superuser.apk",
"/cache",
"/data",
"/dev"
};
private static Boolean checkForBinary(String fileName) {
for (String path : binaryPaths) {
File f = new File(path, fileName);
if (f.exists()) {
return true;
}
}
return false;
}
/**
* 비지박스 루팅 탐지
*/
private static Boolean checkForBusyBoxBinary() {
return checkForBinary("busybox");
}
/**
* Su 루팅 탐지
*/
private static Boolean checkForSuBinary() {
return checkForBinary("su");
}
/**
* 매지스크 루팅 탐지
*/
private static Boolean checkForMagiskBinary() {
return checkForBinary("magisk");
}
#2. 'Su' 루트 실행 권한이 있는지 확인
앱을 루팅하게 되면, Su 실행 권한이 등록이 되어있다.
private static Boolean checkSuExecAuthority() {
Process process = null;
try {
process = Runtime.getRuntime().exec(new String[]{"/system/xbin/which", "su"});
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = in.readLine();
process.destroy();
return line != null;
} catch (Exception e) {
if (process != null) {
process.destroy();
}
return false;
}
}
#3. 루팅 우회 탐지(프리다) 확인
탐지 우회 Hooking 을 하게 되는 경우를 막는 로직이다.
/**
* 프리다 탐지 (탐지 우회 Hooking 막기)
*/
private static boolean checkFrida() {
int pid = android.os.Process.myPid();
try {
String mapsFileContents = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
mapsFileContents = new String(Files.readAllBytes(Paths.get("/proc/"+pid+"/maps")), Charset.defaultCharset());
}
if (mapsFileContents == null) return false;
return mapsFileContents.contains("frida");
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
#4. 디버깅 툴 탐지
/**
* 디버깅 툴 탐지
*/
private static boolean checkDebugger() {
int pid = android.os.Process.myPid();
String status = "proc/" + pid + "/status";
File file = new File(status);
try {
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
while (line != null) {
if (line.contains("TracerPid")) {
String[] split = line.split("\t");
int tracerPid = Integer.parseInt(split[1]);
if (tracerPid != 0) { // '디버깅 툴' 존재.
return true;
}
}
line = br.readLine();
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
return false;
}
#5. 타 스토어에서 앱 설치 확인
구글 스토어에만 올렸는데, 내 앱을 다른 누군가 타 스토어에 올려 악용하는 사례가 있으니 확인한다.
public static List<String> registeredStores = new ArrayList<String>() {
{
add("com.android.vending"); // 구글스토어
}
};
String installer = getPackageManager().getInstallerPackageName(getPackageName());
if (!registeredStores.contains(installer)) {
showAlertMessage(getString(R.string.dialog_forgery));
return;
}
추가로 다양한 스토어 패키지 명을 정리하자면 아래와 같다.
각종 스토어 패키지명
1. Google Play Store (구글 플레이 스토어)
: com.android.vending
2. ONE Store (원스토어)
: SKT / com.skt.skaf.A000Z00040
: KT / com.kt.olleh.storefront
: LG U+ / android.lgt.appstore 또는 comlguplus.appstore
3. Galaxy Apps (갤럭시 앱스)
: com.sec.android.app.samsungapps
4. Samsung Smart Switch (삼성 스마트 스위치)
: com.sec.android.easyMover.Agent
5. Android Package Installer
: com.google.android.packageinstaller
6. Samsung Mate Agent
: com.samsung.android.mateagent