1. 개요
안드로이드 앱 모의해킹에서 HTTPS 트래픽 분석은 기본 중의 기본이다. Burp Suite를 프록시로 구성하고 단말의 네트워크 트래픽을 가로채기 위해서는 Burp의 CA 인증서를 단말이 신뢰하도록 등록해야 한다.
Android 7(Nougat) 이후부터 앱은 기본적으로 사용자가 직접 설치한 인증서(User CA)를 신뢰하지 않는다. 네트워크 보안 설정(network_security_config)으로 명시적으로 허용하지 않는 한, 사용자 인증서로는 HTTPS 트래픽 복호화가 불가능하다. 따라서 인증서를 시스템 인증서(System CA) 로 등록해야 한다.
Android 12 + Magisk 루팅 환경에서 시스템 인증서 등록을 시도했고, 흔히 알려진 tmpfs 마운트 방식이 동작하지 않아 Magisk 모듈 방식으로 해결했다. 시행착오 과정과 최종 해결 방법을 정리한다.
2. 환경
| 항목 | 내용 |
|---|---|
| 단말 OS | Android 12 (SDK 31) |
| 루팅 방법 | Magisk (magic mount) |
| 프록시 도구 | Burp Suite (동일 네트워크 PC) |
| 연결 | ADB USB |
3. 인증서 준비
Burp Suite에서 CA 인증서를 내보내는 방법은 두 가지다.

Proxy → Options → Import/export CA certificate → Certificate in DER format- 또는 프록시 설정 후 브라우저에서
http://burp접속 → CA Certificate 다운로드
여기서는 DER 형식으로 내보낸 파일(0220.der)을 사용했다.
Android 시스템 인증서 경로(/system/etc/security/cacerts/)에 넣는 파일은 특정 형식을 따라야 한다.
- PEM 형식으로 변환된 인증서
- 파일명은
<subject_hash_old>.0형식 (OpenSSL의 구 해시 방식)
# DER → PEM 변환
openssl x509 -inform DER -in 0220.der -out burp_ca.pem
# subject_hash_old 기반 파일명 계산
HASH=$(openssl x509 -inform PEM -subject_hash_old -in burp_ca.pem | head -1)
echo "Hash: $HASH"
# Hash: 9a5ba575
# 파일명 변경
cp burp_ca.pem ${HASH}.0
subject_hash_old를 써야 하는 이유
Android는 인증서 파일을 찾을 때 OpenSSL의 구 해시(-subject_hash_old) 기반 파일명을 사용한다. 신규 해시(-subject_hash)로 생성하면 시스템이 인증서를 인식하지 못한다.
4. 시행착오 — tmpfs 마운트 방식
일반적으로 알려진 방식은 /system/etc/security/cacerts/ 위에 tmpfs를 마운트하고 인증서를 복사하는 방법이다.
# 기존 인증서 백업
adb shell su -c "cp /system/etc/security/cacerts/* /data/local/tmp/cacerts_backup/"
# tmpfs 마운트
adb shell su -c "mount -t tmpfs tmpfs /system/etc/security/cacerts"
# 백업 복원 + 새 인증서 추가
adb shell su -c "cp /data/local/tmp/cacerts_backup/* /system/etc/security/cacerts/"
adb shell su -c "cp /data/local/tmp/9a5ba575.0 /system/etc/security/cacerts/"
adb shell su -c "chmod 644 /system/etc/security/cacerts/*"
마운트 자체는 성공하고 파일도 복사됐지만, Burp 인증서가 인식되지 않았다.
원인 확인을 위해 파일 상태를 점검했다.
adb shell su -c "ls -laZ /system/etc/security/cacerts/9a5ba575.0"
-rwxr-xr-x 1 root root u:object_r:tmpfs:s0 1326 ... 9a5ba575.0
문제는 두 가지였다.
① SELinux 컨텍스트 불일치
정상적인 시스템 인증서의 SELinux 컨텍스트는 u:object_r:system_security_cacerts_file:s0이어야 한다. tmpfs 위에 복사된 파일은 u:object_r:tmpfs:s0로 지정되어 시스템이 신뢰하지 않는다.
② setenforce 0 차단
SELinux를 Permissive로 전환해 컨텍스트 제한을 우회하려 했지만, Magisk가 SafetyNet 우회를 위해 setenforce를 가로막아 실제로는 적용되지 않았다.
adb shell su -c "setenforce 0; echo exit:$?"
# exit:0 ← 성공처럼 보이지만...
adb shell su -c "getenforce"
# Enforcing ← 실제로는 그대로
Magisk는 루트 셸에서 setenforce 0의 종료 코드를 0으로 위장하지만, 시스템 SELinux 상태는 변경하지 않는다. 이 때문에 tmpfs 위 파일의 컨텍스트를 chcon으로 수정하는 것도 막힌다.
결론적으로 tmpfs 방식은 이 환경에서 동작하지 않는다.
5. 해결 방법 — Magisk 모듈 방식
Magisk는 부팅 시 모듈 디렉토리(/data/adb/modules/)에 등록된 system/ 하위 파일을 실제 /system 경로에 bind mount한다. Magisk 데몬 자체는 u:r:magisk:s0 SELinux 컨텍스트로 동작하기 때문에, 모듈을 통한 마운트 시 올바른 SELinux 컨텍스트와 권한이 적용된다.
5.1 모듈 디렉토리 구조
/data/adb/modules/burp_ca_cert/
├── module.prop
├── post-fs-data.sh
└── system/
└── etc/
└── security/
└── cacerts/
└── 9a5ba575.0
5.2 설치 과정
1. 인증서를 단말로 전송
adb push 9a5ba575.0 /data/local/tmp/9a5ba575.0
2. 모듈 디렉토리 생성 및 인증서 배치
adb shell su -c "mkdir -p /data/adb/modules/burp_ca_cert/system/etc/security/cacerts"
adb shell su -c "cp /data/local/tmp/9a5ba575.0 /data/adb/modules/burp_ca_cert/system/etc/security/cacerts/9a5ba575.0"
3. module.prop 작성
Magisk가 모듈을 인식하기 위해 필수적인 파일이다.
# 로컬에서 파일 생성 후 push
printf 'id=burp_ca_cert\nname=Burp CA Certificate\nversion=v1\nversionCode=1\nauthor=pentest\ndescription=Burp Suite CA as system CA\n' > /tmp/module.prop
adb push /tmp/module.prop /data/local/tmp/module.prop
adb shell su -c "cp /data/local/tmp/module.prop /data/adb/modules/burp_ca_cert/module.prop"
직접 쓰기가 안 되는 이유
/data/adb/ 경로는 Magisk 데몬이 관리하는 영역으로, SELinux 정책상 일반 루트 셸에서 직접 파일을 생성하거나 권한을 변경할 수 없다. 파일 복사는 허용되지만 chmod, ls 등 일부 명령은 차단된다. /data/local/tmp/를 경유해서 cp로 복사하는 방법으로 우회한다.
4. post-fs-data.sh 작성
부팅 시 Magisk가 실행하는 스크립트다. 인증서의 권한과 SELinux 컨텍스트를 올바르게 설정한다.
printf '#!/system/bin/sh\nCERT=/system/etc/security/cacerts/9a5ba575.0\nchmod 644 $CERT 2>/dev/null\nchown root:root $CERT 2>/dev/null\nchcon u:object_r:system_security_cacerts_file:s0 $CERT 2>/dev/null\n' > /tmp/post-fs-data.sh
adb push /tmp/post-fs-data.sh /data/local/tmp/post-fs-data.sh
adb shell su -c "cp /data/local/tmp/post-fs-data.sh /data/adb/modules/burp_ca_cert/post-fs-data.sh"
post-fs-data.sh 실행 권한
Magisk는 이 스크립트를 /system/bin/sh /path/to/post-fs-data.sh 형식으로 실행한다. 파일에 실행 비트(+x)가 없어도 sh가 직접 해석하므로 동작에 문제없다.
5. 재부팅
adb reboot으로 Magisk 활성화
adb reboot
6. 결과 확인
재부팅 후 ADB 연결이 복구되면 인증서 상태를 확인한다.
adb shell su -c "ls -laZ /system/etc/security/cacerts/9a5ba575.0"
-rw-r--r-- 1 root root u:object_r:system_security_cacerts_file:s0 1326 ... 9a5ba575.0
adb shell su -c "mount | grep cacerts"
/dev/block/sda34 on /system/etc/security/cacerts/9a5ba575.0 type f2fs (ro,lazytime,seclabel,...)
인증서 내용이 의도한 Burp CA와 동일한지 MD5로 교차 검증한다.
# 단말
adb shell su -c "cat /system/etc/security/cacerts/9a5ba575.0 | md5sum"
# 65bb83dcdf5664adb9138325f40de496
# 로컬
md5sum 9a5ba575.0
# 65bb83dcdf5664adb9138325f40de496 9a5ba575.0
해시가 일치하면 정상 등록된 것이다. 이후 Burp Suite 프록시를 통해 HTTPS 트래픽 스니핑이 가능한 상태가 된다.
7. 정리
Android 12 + Magisk 환경에서 Burp CA 인증서를 시스템 인증서로 영구 등록하는 과정을 요약하면 다음과 같다.
- Burp에서 DER 형식으로 CA 인증서 내보내기
openssl로 PEM 변환 및subject_hash_old기반 파일명 생성/data/adb/modules/<id>/system/etc/security/cacerts/경로에 배치module.prop,post-fs-data.sh작성adb reboot로 재부팅- SELinux 컨텍스트 및 파일 권한 확인
tmpfs 방식은 Android 12에서 Magisk의 SELinux 정책으로 인해 컨텍스트 설정이 차단되어 인증서 인식에 실패한다. Magisk 모듈 방식은 Magisk 데몬이 직접 마운트를 처리하므로 올바른 컨텍스트가 자동으로 적용되고, 재부팅 후에도 유지된다.
'Security > └ 안드로이드 취약점 진단' 카테고리의 다른 글
| [Frida android] 17.6.0 계측 구조 변경 - ptrace에서 proc/mem 기반으로 (1) | 2026.02.20 |
|---|---|
| Flutter HTTPS 통신 Intercept 위한 로직 분석 (0) | 2025.10.24 |
| [JADX-AI-MCP] jadx 와 MCP 연동하여 APK 분석하기 (0) | 2025.09.29 |
| [Androidmeda] LLM Powered Deobfuscation for Android Apps (1) | 2025.09.10 |
| [Fridump3] Frida 17 이상 버전에서 Not a function 에러 해결 (1) | 2025.08.13 |
