2. 안드로이드 보안 기초
[안드로이드 운영체제 입문] https://product.kyobobook.co.kr/detail/S000213637137
이 글은 해당 책과 자료를 참고하고 제가 추가로 공부한 내용으로 작성하였습니다.
안드로이드 설계 원칙
어떤 아키텍처를 만들 때 지켜야 할 보안적 관점론 이야기이다.
다른 것과 크게 다르지는 않다.
스마트폰은 웨어러블 기기나 사물 인터넷 기기를 연결하고 동작과 제어를 하며 광점위한 연결성이 생겼다.
소프트웨어 설계 원칙으로 로버트 마틴이 말한 다섯 가지 원칙인 SOLID 원칙을 지켜야 한다.
S : 단일 책임의 원칙 (Sigle Responsibility Principle)
하나의 클래스는 하나의 책임만 가져야 한다는 것으로 클래스가 여러가지 역할을 수행하면 코드가 복잡해진다.
또한 인증과 DB 접근 기능이 하나의 클래스에 있다면 하나의 취약점이 파급력이 더 커지는 결과를 낳을 수 있다.O : 개방 폐쇄의 원칙 (Open Close Principle)
기존의 코드를 변경하지 않고 새로운 기능을 추가할 수 있도록 설계해야한다.
새로운 기능을 추가할 때 기존의 코드를 바꾸면서 다른 사용하고 있는 곳에 영향을 미치므로, 새로운 취약점이 생길 수 있다.L : 리스코프 치환 원칙 (Liscov Substitution Principle)
인터페이스나 부모 클래스를 사용하는 곳에서 자식 클래스를 사용해도 문제가 발생하면 안된다는 것이다.
자식 클래스가 잘못된 오버로딩을 하거나, 자식 클래스에만 특별한 기능을 추가해서 부모 클래스를 사용하던 곳에서
대체할 수 없게 되거나 잘못된 상속 관계로 호환성을 지키지 못할 때 등이 있다.I : 인터페이스 분리 원칙 (Interface Segregation Principle)
각 인터페이스는 단독으로 동작해야 한다는 것으로 사용하지 않는 인터페이스를 구현하면 안된다.
하나의 큰 인터페이스를 상속 받기보다는 구체적이고 작은 단위로 분리시켜 필요한 것만 사용해야 한다.D : 의존 역전 원칙 (Dependency Inversion Principle)
의존 관계는 추상화에 의존해야 하며 구체적인 구현에 의존해서는 안된다는 것이다.
예를 들어 DB 접근 추상 클래스가 특정한 구체적인 DB에 의존한다면 우선 다른 DB 접근할 때 해당 코드를 사용할 수 없고
특정 DB에서 발생한 취약점이 전체 앱에 영향을 미치게 된다.
이 기본 원칙은 코드의 활용성을 높이고, 보안 취약점을 없애는데 큰 도움이 된다.
위협 모델링
위협 모델링은 시스템이나 앱에 영향을 미칠 수 있는 위협을 식별하는 과정이다.
우선 시스템, 앱, 데이터 등에 영향을 미칠 수 있는 위협(OS, 아키텍처)을 확인한다.
이 때 앱에서 신뢰 경계를 설정해서 보호해야 할 주요 자산을 식별할 수 있다.
사용자 정보, 암호화키, 세션값 같은 데이터가 외부로부터 접근이 되지 않도록 보호가 필요하다.
위협 분석 과정에서는 잠재적 영향과 공격 가능한 경로를 분석하고, 상호작용을 파악한다.
그렇게 위협을 판단하면 심각도와 가능성을 평가해서 우선순위를 정해 공격을 시도한다.
안드로이드 운영체제 구조
안드로이드 운영체제는 사용자, 애플리케이션, 운영체제로 구성된다.
안드로이드 앱은 권한을 요구하고 정보를 처리하며 운영체제는 시스템 명령을 실행한다.
보통 취약점 진단을 할 때는 애플리케이션 수준에서 진행하고, 코드, 권한, 통신 구간 등을 분석한다.
커널 계층
사진에서 가장 하위에 존재하는 것은 리눅스 기반의 커널이다.
커널은 하드웨어 <-> 소프트웨어 간의 인터페이스 역할을 하고 관리를 한다.
메모리, 프로세스, 단말 드라이버 등 관리를 하고 스레드, 메모리 관리는 리눅스의 원리를 따른다.
Hardware Abstraction 계층
카메라, 블루투스 같은 하드웨어 장치와 안드로이드 운영체제 간의 인터페이스 역할을 한다.
각각의 하드웨어를 추상화해서 앱 프레임워크에 제공한다.
하드웨어 장치에 대해 드라이버를 제공하고, 앱은 하드웨어를 제어할 수 있다.
이렇게 추상화된 인터페이스를 이용하면 하드웨어와 관련된 복잡한 작업을 하지 않을 수 있다.
다양한 제조사에서 단말기를 만들기에 하나의 하드웨어 표준이 정해져 있지 않기에
프레임워크를 호출하고, 안드로이드 시스템은 이 계층을 통해서 하드웨어 모듈을 로드해서 사용한다.
참고 : https://source.android.com/docs/core/architecture/hal?hl=ko
https://source.android.com/docs/core/architecture/hidl?hl=ko
Android 8.0 이전에는 c나 c++로 작성된 .so파일을 직접 참조하는 방식이어서 호환성에 문제가 있었고
8.0이후로 HIDL 기반으로 바뀌었다.
위의 내용처럼 하드웨어 장치나 특정 프로토콜에 종속되지 않은 프레임워크로 통신을 한다.
HIDL이란 /dev/hwbinder를 통해서 프레임워크 <-> 벤더사 프로세스 통신을 가능하게 하는 언어이다.
이렇게 만든 .hal 파일을 /vender 파티션에 둠으로써 시스템과 하드웨어의 독립성을 확보한다.
Android 11.0 이후로는 AIDL을 사용해서 JAVA <-> C++ 호환성을 올리고 HIDL보다 개선된 성능으로 한다.
AIDL이란 Android 인터페이스 정의 언어로 사용자가 IPC를 추상화 할 수 있도록 하는 도구이다.
아직 흐름을 이해하기에는 어려워서 관련한 내용에 대해서는 추후에 기회가 되면 다뤄보겠습니다.
안드로이드 런타임 계층
안드로이드 운영체제의 실행 환경을 관리하는 곳으로 JVM 기반의 환경인 Dalvik을 사용하다가 이제는 ART를 사용한다.
ART 방식은 앱 설치 시 미리 기계어로 해석해놓고 실행할 때 바로 되도록 성능을 향상시켰다.
하지만 용량이 커지는 문제가 있어서 미리 하는 방법과 실행 시간에 하는 방법을 조합해서 사용한다.
Native 라이브러리
C, C++로 작성된 여러 라이브러리로 성능이 중요한 작업을 수행하며 여러 작업을 처리할 수 있게 한다.
하드웨어 라이브러리, DB, OpenGL 같은 그래픽 등 앱에 필수적인 라이브러리와 개발자가 필요에 따라서
추가한 코드들을 안드로이드 NDK를 통해서 사용할 수 있다.
JAVA 프레임워크 계층
어플리케이션과 프레임워크를 소통하게 해주는 역할로 API는 앱이 OS와 하드웨어를 쉽게 쓰도록 도와준다.
또, Activity Manager, Provider, View System 같은 프레임워크도 해당 계층에 있습니다.
시스템 앱
안드로이드에 이미 설치된 전화, 메시지, 카메라 같은 기능으로 앱과 시스템 앱을 연계해서 기능을 확장한다.
각 구성 요소는 안드로이드 앱의 실행과 하드웨어 간 상호작용을 담당한다.
안드로이드 운영체제 기술
샌드박스 실행
안드로이드 앱은 샌드박스를 통해 각각 독립된 환경에서 실행된다.
이 말은 각 앱이 다른 앱이나 자원에 접근하려면 명시적인 권한 요청이 필요한 것이고, 이렇게 정보를 보호한다.
루팅
루팅은 최고 권한을 얻는 것으로 OS의 모든 부분에 접근할 수 있어서 시스템 파일을 수정하거나 보안을 우회할 수 있다.
사용자는 루팅을 통해서 권한을 얻을 수 있고 악용이 가능하다.
권한
위에서 본 것 처럼 자원과 단말에 접근해 기능을 수행할 수 있도록 하는 권한이다.
특정 권한을 요청할 때 사용자가 권한에 대한 승인을 하고, 카메라, 연락처, 블루투스 등이 여기에 포함된다.
사용자는 앱이 과한 권한을 요청하지 않는지 확인을 해야한다.
저장소
안드로이드 앱은 다양한 저장소 옵션으로 데이터를 관리하고, 여부에 따라 저장할 위치가 달라진다.
앱 내부에서 사용하는 파일을 내부 저장소에 저장할 때는 권한이 필요하지 않고, 외부 저장소에는 권한이 필요하다.
이미지, 오디오, 비디오 같은 미디어 파일은 MediaStore API로 접근할 수 있다.
다른 앱의 파일에 접근하려면 READ_EXTERNAL, WRITE_EXTERNAL의 권한이 필요하다.
앱에서 접근할 때는 문서 및 파일, Jetpack Preferences(share Preferences, PreferenceDataStore)나
데이터베이스 (Room 라이브러리)에 접근할 때는 특별한 권한이 필요하지 않다.
리눅스 시스템의 /bin, /etc, /home처럼 안드로이드에도 경로가 있고 시스템 파티션과 데이터 파티션이 있다.
시스템 파티션에는 OS 및 시스템 앱이 있고, 데이터 파티션에는 사용자 데이터가 저장된다.
경로 | 설명 |
---|---|
/boot | 부트로더와 커널이 저장된 파티션. 기기 부팅 시 가장 먼저 실행됨. |
/system | 안드로이드 운영체제의 주요 파일(프레임워크, 앱 등)이 저장된 영역. |
/recovery | 복구 모드 실행용 파티션. 펌웨어 초기화, 업데이트 설치 등에 사용됨. |
/data | 사용자 데이터(앱, 설정, 계정 정보 등)가 저장됨. 포맷 시 초기화됨. |
/cache | 시스템과 앱의 임시 데이터 저장소. OTA 업데이트 중에도 사용됨. |
/misc | 디바이스 설정 관련 부트 정보(예: 부팅 모드 플래그 등)가 저장됨. |
/sdcard | 내부 저장소 또는 외장 SD 카드. 사용자 파일(사진, 영상 등) 저장용. |
안드로이드는 세분화된 권한 관리 시스템을 가지고, 시스템 파티션은 루트 권한을 가져야만 접근할 수 있다.
또 앱이 설치되는 경로와 사용자 데이터의 경로가 달라서 데이터를 격리해서 관리한다.
이렇게 적절한 저장소 사용 방식과 앱 간 격리 및 권한을 관리하면 보안성이 올라가게 된다.