일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 인앱결제
- PagingLib
- databinding
- Kotlin
- paging
- 테스트 자동화
- 동영상
- MediaPlayer
- rx
- android13
- node.js
- SWIFTUI
- node
- MediaSession
- MotionLayout
- Android 13
- Koin
- mvvm
- Reactive
- Animation
- SwiftUI Tutorial
- Observable
- junit
- GCP
- liveData
- list
- google play
- Android
- mysql
- RxKotlin
- Today
- Total
봄날은 갔다. 이제 그 정신으로 공부하자
내가 만든 앱은 내가 지키자! (앱 위변조 방지) 3/3 본문
개요
앱이 위변조 되는 상황은 두 가지로 볼 수 있습니다.
첫째는 크래커가 내 앱을 디컴파일 후 변조 후 재빌드해서 사용하는 상황이고
둘째는 내 앱을 다운로드 받아 중국의 샤오미 마켓과 같은 다른 마켓에 앱을 등록하는 상황으로 나눌 수 있습니다.
이 번 글에서는 두가지 상황을 방지하는 방법에 대해 설명 하도록 하겠습니다.
첫번째 “크래커가 내 앱을 디컴파일 후 변조 후 재빌드해서 사용하는 상황”
이것을 방지하기 위해 사용되는 것이 앱 서명 키의 Hash key를 사용하는 것 입니다.
앱 서명 키란? 앱을 마켓에 배포하기 위해 배포 빌드를 할 때 앱 서명에 사용되는 키로
크래커가 디컴파일해서 앱을 재빌드 할 경우, 크래커는 내앱의 서명키를 알수 없어,
크래커가 만든 앱은 내가 배포한 앱과는 다른 서명키로 빌드가 되므로 서로 다른 Hash key를 가지게 됩니다.
그러므로 앱 실행 시(또는 화면 전환 시 그리고 API 호출 시 등과 같은 상황에) 앱 서명키의 Hash key를 확인해 다른 경우,
앱을 종료해주도록 처리한다면 간단하게 크래커의 앱이 내 서비스를 사용하는 것을 막을 수 있습니다.
앱 서명 키의 Hash key를 알아내는 방식은 아래와 같습니다.
val packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
val signature = packageInfo.signatures[0]
val messageDigest = MessageDigest.getInstance("SHA")
messageDigest.update(signature.toByteArray())
val signatureString = String(Base64.encode(messageDigest.digest(), Base64.DEFAULT))
하지만 위 내용 중 일부가 andorid P 버전부터 deplecated 되었기 때문에 28 이상부터는 아래와 같이 Hash Key를 구해야 합니다.
val packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNING_CERTIFICATES)
val signature = packageInfo.signingInfo.apkContentsSigners[0]
val messageDigest = MessageDigest.getInstance("SHA")
messageDigest.update(signature.toByteArray())
val signatureString = String(Base64.encode(messageDigest.digest(), Base64.DEFAULT))
이렇게 구한 Hash key(signatureString)를 앱 실행 시 또는 API 호출 시마다 서버에 저장된 서명 키와 비교한다면 크래커가 위변조한 앱의 서비스 접근을 막을 수 있습니다.
두번째 “내 앱을 다운로드 받아 다른 마켓에 등록하는 경우” 입니다.
이 경우는 앱을 건드린게 아니므로 서명 키는 동일합니다.
이 경우에는 인스톨러의 identifier를 체크하는 방식을 사용해야 합니다.
내가 앱을 배포한 마켓(인스톨러)의 identifier가 아니면 앱을 종료하는 방식으로 사용한다면 내가 등록하지 않은 마켓에 앱이 등록되는 경우, 앱이 실행되는 것을 막을 수 있습니다.
아래 코드는 앱이 구글 플레이스토어에서 다운로드되었는지 확인하는 코드 예시 입니다.
val installer = activity.getPackageManager().getInstallerPackageName(activity.getPackageName())
installer?.startsWith("com.android.vending")
'보안' 카테고리의 다른 글
패스워드 암호화에 적합한 해시 함수들 (0) | 2021.12.29 |
---|---|
패스워드 암호화 (2) | 2021.12.22 |
내가 만든 앱은 내가 지키자! (루팅감지, 디버깅감지) 2/3 (1) | 2021.11.15 |
내가 만든 앱은 내가 지키자! (시큐어 코딩, 난독화) 1/3 (1) | 2021.11.10 |
개인 정보의 종류와 개인 정보 수집 & 제공 동의서 작성 방법 (0) | 2021.04.13 |