안드로이드 보안

KIM DO YOON·2025년 6월 3일
0

이번글은 안드로이드 보안에 대한 기본 내용을 다루는 글 입니다.

안드로이드 보안 위협 유형

포렌식 공격

공격자가 안드로이드 기기에 물리적으로 접근하여 민감한 정보를 추출하는 공격 방식. 연락처, 통화 기록, 메시지, 검색 기록 또는 삭제된 파일과 같은 데이터를 추출할 수 있다.

코드 실행 공격

안드로이드 OS 또는 설치된 앱의 취약점을 악용하여 기기에서 악성 코드를 실행하는 것을 목표로 하는 공격. 권한 상승, 사용자 데이터에 대한 무단 액세스 도는 전체 장치 제어와 같은 다양한 결과를 초래할 수 있다. 공격자는 드라이브 바이 다운로드 또는 앱 기반 익스플로잇과 같은 방법을 통해 악성코드를 전달한다.

웹 기반 공격

악성 웹사이트 또는 웹 기반 애플리케이션을 통한 공격. WebView를 통해 만들어진 앱에서 웹 취약점을 통해 사용자 및 서버를 공격할 수 있으며, 손상된 웹 사이트를 방문하거나 악의적인 링크를 클릭함으로써 공격할 수 있다.

악성 앱 공격

정상적인 앱의 서명 개인키가 탈취되면 공격자가 악성코드를 삽입한 업데이트 버전을 배포할 수 있다.


안드로이드 시스템 구조와 보안

리눅스 커널 계층

안드로이드는 리눅스 커널을 기반으로 한다. 커널은 전력 및 메모리 관리, 디바이스 드라이버, 프로세스, 네트워킹 및 보안 관리 등을 수행한다. 안드로이드에 추가된 주요 기능으로는 Binder(프로세스 간 통신 메커니즘), Ashmem(안드로이드 공유 메모리), Pmem(프로세스 메모리 할당자), Logger(logcat 지원) 등이 있다.

HAL

HAL은 하드웨어와 소프트웨어의 차이를 추상화하여 하드웨어에 대한 접근을 단순화 한다. 카메라, 화면, 오디오 등 다양한 하드웨어 장치에 대한 접근을 HAL 통해 제공한다. 안드로이드 프레임워크 및 애플리케이션이 하드웨어에 직접 접근하지 않고도 하드웨어를 사용할 수 있도록 한다.

런타임(ART)

안드로이드 5.0 이상에서는 ART가 사용된다. ART 는 자바 바이트코드를 기계어로 컴파일하여 실행 효율을 높이고, 가비지 컬렉션을 사용하여 메모리를 효율적으로 관리한다. 안드로이드 7.0 이후에는 설치시 JIT, 설치 후 ART로 둘다 사용하는 하이브리드 방식을 채택했다.

NDK 와 JNI

NDK는 네이티브 언어로 코드를 실행할 수 있도록 하는 도구이며, JNI는 자바와 C++ 구성요소 간의 통신 채널 역할을 하는 인터페이스 이다. JNI는 성능이 중요한 연산, 기존 C/C++ 라이브러리 활용, 하드웨어 제어 등의 목적으로 사용된다.

안드로이드 부팅 과정과 보안 메커니즘

부팅 과정

안드로이드 부팅 과정은 다음과 같다.
1. Boot ROM
2. Bootloader
3. Kernel
4. Init 프로세스
5. Zygote : 애플리케이션 실행에 필요한 VM 코드 및 메모리 정보를 공유해서 실행 시간을 단축
6. System Server : Zygote에서 최초로 fork 되어 실행되는 안드로이드 애플리케이션 프로세스

루팅과 보안 위험

루팅이란?

루팅은 안드로이드에 적용된 제한들을 제거하기 위한 목적으로 하는 권한 상승 행위
과정
1. Bootloader Unlock : FastBoot Mode 를 통해 부트로더 언락을 수행한다.
2. 커스텀 리커버리 설치
3. 커스텀 롬 설치 : Super SU 가 포함된 커스텀 롬을 설치한다.

루팅과 보안

루팅을 통해 루트 퀀한을 획득하면 시스템 파일에 접근할 수 있게 되며, 취약점이 발생할 수 있다.

안드로이드 보안 메커니즘

샌드박스

안드로이드 샌드박스는 각 앱이 독립된 환경에서 실행되도록 격리하는 보안 메커니즘. 이는 리눅스 커널의 사용자 ID(UID)및 프로세스 격리 기능을 기반으로 구현된다. 안드로이드 시스템은 각 앱을 설치할 때 고유한 UID를 할당하고, 이 UID를 통해 파일 시스템 접근 권한을 제어한다.

샌드 박스는 다음과 같은 계층으로 구성된다.

  • Linux 커널 수준 보안(프로세스 격리, 파일 시스템 권한, UID/GID 기반 접근 제어)
  • 애플리케이션 프레임워크 수준 보안(권한 관리 시스템, 의도적 API 설계)
  • 런타임 수준 보안(가상 머신 격리)

코드 서명

코드 서명은 앱 개발자가 누구인지 나타내기 위한 개발자 자신의 코드서명인증서로 서명하는 것이다. 소프트웨어를 해시하여 코드 서명 값을 생성하고 배포되는 소프트웨어에 포함시킨다. 서명키가 노출되면 악의적인 소프트웨어를 배포할 수 있는 위험이 있다.

키 저장소 시스템

안드로이드 키 저장소 시스템은 암호화 키를 컨테이너에 저장하여 기기에서 키를 추출하기 어렵게 만든다. 키가 키 저장소에 저장되면 키 자료는 내보낼 수 없으며, 암호화 연산에만 사용할 수 있다. 키 저장소 시스템은 사용자 인증이 필요하거나 특정 암호화 모드에서만 사용할 수 있도록 키 사용을 제한할 수 있다.

키 저장소 관련 용어는 다음과 같다.

  • keystore : Java ketstore 파일, 인증서와 비공개 키의 저장소 역할을 하는 바이너리 파일
  • KeyStore : 앱 자체에서 사용하는 암호키 보관을 위한 서비스
  • Ketstroe : 기기에서 암호키를 안전하게 저장하기 위해 사용하는 하드웨어 장치

안드로이드 APK 파일 구조와 안드로이드 개발 관련 개념

APK 파일 구조 분석

APK란?

APK는 안드로이드 애플리케이션의 설치 패키지 파일 형식이다. APK 파일은 zip 형식으로 압축되어 있어 확장자를 .zip으로 변경하면 내부 구조를 확인할 수 있다.

APK 내구 구조 상세 분석

assets 폴더

앱 실행에 필요한 자원들이 저장되는 디렉터리, 주요 용량이 큰 파일들을 보관한다. 예를 들면 동영상, 오디오, 대용량 택스트 파일등이 해당한다. 원본 파일명과 폴더 구조를 그대로 유지하며, AssetManager를 통해 런타임에 접근할 수 있다.

res 폴더

앱 실행에 필요한 resource가 모여있는 디렉터리, assets 에 비해 용량이 작은 파일들을 저장한다. 예를 들면 레이아웃, 문자열, 아이콘, UI 관련 파일들이 여기에 위치하며 빌드 과정에서 컴파일되어 최적화 된다.

META-INF 폴더

인증 서명과 관련한 정보가 담겨 있는 디렉터리 이 폴더에는 다음과 같은 파일들이 포함된다.

  • MANIFEST.MF : APK내 모든 파일의 기본 정보
  • CERT.SF : 모든 파일의 SHA-1 해시값 목록
  • CERT.RSA : 앱의 공개 인증서 정보
    이 폴더에는 APK 무결성과 진위를 보장하여 변조를 방지하는 역할을 한다.

lib 폴더

라이브러 파일(.so)이 저장되는 디렉터리이다. 다양한 CPU 아키텍처 별로 컴파일된 네이티브 코드 라이브러리들이 하위 폴더로 구성된다.

AndroidManifest.xml

애플리케이션의 필수 구성요소 정보, 패키지명, 버전 등 앱의 설치 정보가 저장되는 파일, 안드로드 시스템이 앱을 이해하고 상호작용하기 위한 청사진 역할을 한다.

classes.dex

DEX(Dalvik Executable)은 안드로이드에서 앱을 구동하기 위한 핵심 파일 포맷이다. 안드로이드 가상 머신 달빅이 인식할 수 있도록 Java.class 파일을 바이트 코드로 변환시킨 소스 파일이다.

resources.arsc

리소스 배열이라는 뜻으로, res 폴더의 정보가 컴파일된 형태로 기록되어 있다. 문자열, 스타일, 색상 등의 값들이 효율적인 테이블 형태로 저장되어 런타임 성능을 최적화 한다.

안드로이드 빌드 과정

1단계 : 소스 코드 컴파일

Java 와 Kotlin 소스 코드가 JVM 바이트코드로 컴파일 된다. Java 컴파일러와 Kotlin 컴파일러가 이 작업을 수행한다.

2단계 : 리소스 처리

AAPT(Android Asset Packaging Tool)을 사용해 res/ 디렉터리의 XML파일, 이미지 등을 처리하고 R.java 파일을 생성한다. .res/values 하위 디렉터리 내용은 resources.arsc 파일로 컴파일 된다.

3단계 : DEX 변환

.class 파일을 안드로이드에서 실행 가능한 .dex 파일로 변환한다. 이 과정에서 JVM 바이트코드가 Android 런타임에 최적화된 형태로 변환된다.

4단계 : 패키징 및 서명

모든 구성요소를 하나의 APK 파일로 병합하고 디지털 서명을 추가한다. 마지막으로 zipalign 도구로 APK를 4바이트 경계로 정렬하여 성능을 최적화 한다.

AndroidManifest.xml 핵심 구성요소

1. 고유한 패키지명

앱의 고유 식별자로 사용되며, R.java 클래스의 네임스페이스로도 활용된다. (com.company.appname)

2. 안드로이드 4대 컴포넌트 정의

  • Activity : 사용자 인터페이스를 담당하는 구성 요소
  • Service : 백그라운드 작업을 처리하는 구성 요소
  • Broadcast Reciver : 시스템 이벤트를 수신하는 구성 요소
  • Content Provider : 데이터 공유를 관리하는 구성 요소

3. 권한 정의

앱이 시스템 리소스나 다른 앱의 데이터에 접근하기 위해 필요한 권한들을

<uses-permission>

태그로 선언한다.

4. 공유 UID 정보

android:sharedUserId 속성을 통해 여러 앱이 동일한 사용자 식별자를 공유할 수 있도록 설정가능하지만 API 29 에서 지원이 중단되었음

Activity 생명주기

  1. onCreate(): Activity가 처음 생성될 때 호출되는 함수

  2. onStart(): 사용자에게 보여지기 직전에 호출되며, UI 관련 코드를 초기화

  3. onResume(): 실제로 화면에 보여지는 단계로, 사용자와 상호작용이 가능한 상태

  4. onPause(): 다른 Activity가 포커스를 가져갔을 때 호출

  5. onStop(): 다른 Activity에게 완전히 가려질 때 호출

  6. onRestart(): stop 상태에서 다시 시작될 때 호출

  7. onDestroy(): Activity가 완전히 스택에서 제거될 때 호출

Service: 백그라운드 작업의 담당자

Service는 백그라운드에서 앱을 계속 실행하기 위한 다목적 진입점. 사용자 인터페이스 없이 백그라운드에서 실행되며, 오랫동안 실행되는 작업을 수행하거나 원격 프로세스를 위한 작업을 수행.

Broadcast Receiver: 시스템 이벤트 수신기

Broadcast Receiver는 시스템이 정기적인 사용자 플로우 밖에서 이벤트를 앱에 전달하도록 지원. 앱이 시스템 전체의 브로드캐스트 알림에 응답할 수 있도록 도와주며, 문자 메시지 수신, 배터리 부족 알림 등의 시스템 이벤트를 처리.

Content Provider: 데이터 공유 관리자

Content Provider는 파일 시스템, 데이터베이스, 웹이나 앱이 액세스할 수 있는 다른 모든 영구 저장 위치에 저장 가능한 앱 데이터의 공유에 있어 읽기, 쓰기 권한을 관리하는 역할. 이를 통해 다른 애플리케이션과 안전하게 데이터를 공유할 수 있다.

AAB(Android App Bundle) - 차세대 배포 방식

기존 APK 방식의 한계를 극복하기 위해 구글에서 2018년에 제시한 새로운 형식. AAB는 구글 플레이 앱 게시를 위한 파일이며, 다음과 같은 장점을 제공한다.:

최적화된 APK 생성: 아키텍처, 화면 밀도, 언어에 최적화된 분할 APK를 생성

용량 감소: 기기별로 필요한 리소스만 포함하여 다운로드 용량 최소화

동적 기능 모듈: 필요에 따라 기능을 동적으로 다운로드 가능

profile
안녕하세요 김도윤 입니다.

0개의 댓글