Translated ['src/mobile-pentesting/android-app-pentesting/android-applic

This commit is contained in:
Translator 2025-07-28 14:17:49 +00:00
parent 39c86cb25f
commit e8f5883e90

View File

@ -4,55 +4,55 @@
## Android Security Model
**두 개의 레이어가 있습니다:**
**두 개의 계층이 있습니다:**
- **OS**는 설치된 애플리케이션을 서로 격리합니다.
- **애플리케이션 자체**는 개발자가 **특정 기능을 노출**하고 애플리케이션 기능을 구성할 수 있게 합니다.
### UID Separation
**각 애플리케이션은 특정 사용자 ID가 할당됩니다**. 이는 앱 설치 중에 이루어지며, **앱은 자신의 사용자 ID가 소유한 파일이나 공유 파일과만 상호작용할 수 있습니다**. 따라서 앱 자체, OS의 특정 구성 요소 및 루트 사용자만 앱 데이터를 접근할 수 있습니다.
**각 애플리케이션은 특정 사용자 ID가 할당됩니다**. 이는 앱 설치 중에 이루어지며, **앱은 자신의 사용자 ID가 소유한 파일이나 공유 파일과만 상호작용할 수 있습니다**. 따라서 앱 자체, OS의 특정 구성 요소 및 루트 사용자만 앱 데이터를 접근할 수 있습니다.
### UID Sharing
**두 개의 애플리케이션 동일한 UID를 사용하도록 구성될 수 있습니다**. 이는 정보를 공유하는 데 유용할 수 있지만, 그 중 하나가 손상되면 두 애플리케이션의 데이터가 모두 손상될 수 있습니다. 그래서 이러한 행동은 **권장되지 않습니다**.\
**두 개의 애플리케이션 동일한 UID를 사용하도록 구성될 수 있습니다**. 이는 정보를 공유하는 데 유용할 수 있지만, 그 중 하나가 손상되면 두 애플리케이션의 데이터가 모두 손상될 수 있습니다. 그래서 이러한 행동은 **권장되지 않습니다**.\
**동일한 UID를 공유하려면 애플리케이션은 매니페스트에서 동일한 `android:sharedUserId` 값을 정의해야 합니다.**
### Sandboxing
**Android 애플리케이션 샌드박스**는 **각 애플리케이션을 별도의 사용자 ID로 별도의 프로세스로 실행할 수 있게 합니다**. 각 프로세스는 자신의 가상 머신을 가지고 있어, 앱의 코드는 다른 앱과 격리되어 실행됩니다.\
Android 5.0(L)부터 **SELinux**가 시행됩니다. 기본적으로 SELinux는 모든 프로세스 상호작용을 거부하고, 그들 간의 **예상되는 상호작용만 허용하는 정책을 생성했습니다**.
**Android 애플리케이션 샌드박스**는 **각 애플리케이션을 별도의 사용자 ID로 별도의 프로세스로 실행**할 수 있게 합니다. 각 프로세스는 자신의 가상 머신을 가지고 있어, 앱의 코드는 다른 앱과 격리되어 실행됩니다.\
Android 5.0(L)부터 **SELinux**가 시행됩니다. 기본적으로 SELinux는 모든 프로세스 상호작용을 거부하고, 그들 간의 **예상되는 상호작용만 허용하는 정책을 생성니다**.
### Permissions
애플리케이션을 설치할 때 **앱이 권한을 요청하면**, 앱은 **AndroidManifest.xml** 파일의 **`uses-permission`** 요소에 구성된 권한을 요청하는 것입니다. **uses-permission** 요소는 **name** **속성** 내에서 요청된 권한의 이름을 나타냅니다. 또한 **maxSdkVersion** 속성이 있어, 지정된 버전보다 높은 버전에서는 권한 요청을 중합니다.\
안드로이드 애플리케이션은 처음에 모든 권한을 요청할 필요는 없으며, **동적으로 권한을 요청할 수 있지만** 모든 권한은 **매니페스트에 선언되어야 합니다**.
애플리케이션을 설치할 때 **앱이 권한을 요청하면**, 앱은 **AndroidManifest.xml** 파일의 **`uses-permission`** 요소에 구성된 권한을 요청하는 것입니다. **uses-permission** 요소는 **name** **속성 내에서 요청된 권한의 이름을 나타냅니다.** 또한 **maxSdkVersion** 속성이 있어, 지정된 버전보다 높은 버전에서는 권한 요청을 중합니다.\
안드로이드 애플리케이션은 처음에 모든 권한을 요청할 필요는 없으며, **동적으로 권한을 요청할 수 있지만 모든 권한은 매니페스트에 **명시되어야 합니다.**
앱이 기능을 노출할 때, **지정된 권한을 가진 앱만 접근할 수 있도록 제한할 수 있습니다**.\
권한 요소는 세 가지 속성을 가집니다:
- 권한의 **이름**
- 관련 권한을 그룹화할 수 있는 **permission-group** 속성
- 관련 권한을 그룹화할 수 있는 **permission-group** 속성.
- 권한이 부여되는 방식을 나타내는 **protection-level**. 네 가지 유형이 있습니다:
- **Normal**: 앱에 **알려진 위협이 없을 때** 사용됩니다. 사용자가 **승인할 필요가 없습니다**.
- **Dangerous**: 요청하는 애플리케이션에 **상승된 접근**을 부여하는 권한을 나타냅니다. **사용자에게 승인을 요청합니다**.
- **Signature**: **구성 요소를 내보내는 것과 동일한 인증서로 서명된 앱만** 권한을 부여받을 수 있습니다. 이는 가장 강력한 보호 유형입니다.
- **SignatureOrSystem**: **구성 요소를 내보내는 것과 동일한 인증서로 서명된 앱이나** **시스템 수준 접근으로 실행되는 앱만** 권한을 부여받을 수 있습니다.
- **SignatureOrSystem**: **구성 요소를 내보내는 것과 동일한 인증서로 서명된 앱이나 **시스템 수준 접근으로 실행되는 앱만** 권한을 부여받을 수 있습니다.
## Pre-Installed Applications
이 앱들은 일반적으로 **`/system/app`** 또는 **`/system/priv-app`** 디렉토리에서 발견되며, 그 중 일부는 **최적화되어** 있습니다(심지어 `classes.dex` 파일을 찾지 못할 수도 있습니다). 이러한 애플리케이션은 때때로 **너무 많은 권한으로 실행되고** 있기 때문에 확인할 가치가 있습니다(루트로).
이 앱들은 일반적으로 **`/system/app`** 또는 **`/system/priv-app`** 디렉토리에서 발견되며, 일부는 **최적화**되어 있습니다 (심지어 `classes.dex` 파일을 찾지 못할 수도 있습니다). 이러한 애플리케이션은 때때로 **너무 많은 권한으로 실행되고 있기 때문에** 확인할 가치가 있습니다 (루트로).
- **AOSP** (Android OpenSource Project) **ROM**과 함께 제공되는 것들
- 장치 **제조업체**에 의해 추가된 것들
- **전화 제공업체**에 의해 추가된 것들(그들로부터 구매한 경우)
- **전화 제공업체**에 의해 추가된 것들 (그들로부터 구매한 경우)
## Rooting
물리적 안드로이드 장치에 루트 접근을 얻으려면 일반적으로 **1개 또는 2개의 취약점을 이용해야** 하며, 이는 **장치** **버전**에 **특정**입니다.\
물리적 안드로이드 장치에 루트 접근을 얻으려면 일반적으로 **1개 또는 2개의 취약점을 **악용해야 합니다**, 이는 **장치**와 **버전**에 **특정**입니다.\
익스플로잇이 성공하면, 일반적으로 리눅스 `su` 바이너리가 사용자의 PATH 환경 변수에 지정된 위치인 `/system/xbin`에 복사됩니다.
su 바이너리가 구성되면, 다른 안드로이드 앱이 `su` 바이너리와 인터페이스하여 **루트 접근 요청을 처리**합니다. 예를 들어 **Superuser****SuperSU**(Google Play 스토어에서 사용 가능)와 같은 앱이 있습니다.
su 바이너리가 구성되면, 다른 안드로이드 앱이 `su` 바이너리와 인터페이스하여 **루트 접근 요청을 처리**합니다. 예를 들어 **Superuser**와 **SuperSU** (Google Play 스토어에서 사용 가능)와 같은 앱이 있습니다.
> [!CAUTION]
> 루팅 과정은 매우 위험하며 장치를 심각하게 손상시킬 수 있습니다.
@ -60,17 +60,17 @@ su 바이너리가 구성되면, 다른 안드로이드 앱이 `su` 바이너리
### ROMs
**커스텀 펌웨어를 설치하여 OS를 교체하는 것이 가능합니다**. 이를 통해 오래된 장치의 유용성을 확장하거나 소프트웨어 제한을 우회하거나 최신 안드로이드 코드에 접근할 수 있습니다.\
**OmniROM** **LineageOS**는 사용하기에 가장 인기 있는 두 가지 펌웨어입니다.
**OmniROM** **LineageOS**는 사용하기에 가장 인기 있는 두 가지 펌웨어입니다.
**장치를 루팅할 필요가 없는 경우도 있습니다**. **일부 제조업체는** 잘 문서화되고 안전한 방식으로 부트로더 잠금을 해제할 수 있도록 허용합니다.
**커스텀 펌웨어를 설치하기 위해 장치를 루팅할 필요는 항상 없습니다**. **일부 제조업체는** 잘 문서화되고 안전한 방식으로 부트로더 잠금을 해제하는 것을 허용합니다.
### Implications
장치가 루팅되면, 어떤 앱이든 루트 접근을 요청할 수 있습니다. 악성 애플리케이션이 이를 얻으면 거의 모든 것에 접근할 수 있으며, 전화기를 손상시킬 수 있습니다.
장치가 루팅되면, 어떤 앱이든 루트 접근을 요청할 수 있습니다. 악성 애플리케이션이 이를 얻으면 거의 모든 것에 접근할 수 있으며, 전화기를 손상시킬 수 있습니다.
## Android Application Fundamentals <a href="#2-android-application-fundamentals" id="2-android-application-fundamentals"></a>
- 안드로이드 애플리케이션의 형식은 _APK 파일 형식_이라고 합니다. 본질적으로 **ZIP 파일**입니다(파일 확장자를 .zip으로 변경하면 내용을 추출하고 볼 수 있습니다).
- 안드로이드 애플리케이션의 형식은 _APK 파일 형식_으로 언급됩니다. 본질적으로 **ZIP 파일**입니다 (파일 확장자를 .zip으로 변경하면 내용을 추출하고 볼 수 있습니다).
- APK 내용 (포괄적이지 않음)
- **AndroidManifest.xml**
- resources.arsc/strings.xml
@ -79,15 +79,15 @@ su 바이너리가 구성되면, 다른 안드로이드 앱이 `su` 바이너리
- META-INF/
- 여기에서 인증서가 위치합니다!
- **classes.dex**
- 기본적으로 애플리케이션이 실행하는 컴파일된 Java(또는 Kotlin) 코드를 나타내는 Dalvik 바이트코드를 포함합니다.
- 기본적으로 애플리케이션이 실행하는 컴파일된 Java (또는 Kotlin) 코드를 나타내는 Dalvik 바이트코드를 포함합니다.
- lib/
- CPU 아키텍처에 따라 하위 디렉토리로 분리된 네이티브 라이브러리를 포함합니다.
- `armeabi`: ARM 기반 프로세서 코드
- `armeabi-v7a`: ARMv7 및 그 이상의 프로세서 코드
- `x86`: X86 프로세서 코드
- `armeabi`: ARM 기반 프로세서를 위한 코드
- `armeabi-v7a`: ARMv7 및 그 이상의 프로세서를 위한 코드
- `x86`: X86 프로세서를 위한 코드
- `mips`: MIPS 프로세서 전용 코드
- assets/
- 앱에 필요한 다양한 파일을 저장하며, 추가 네이티브 라이브러리나 DEX 파일을 포함할 수 있으며, 때때로 악성 코드 작성자가 추가 코드를 숨기기 위해 사용합니다.
- 앱에 필요한 다양한 파일을 저장하며, 추가 네이티브 라이브러리나 DEX 파일을 포함할 수 있으며, 때때로 악성 코드 작성자가 추가 코드를 숨기기 위해 사용합니다.
- res/
- resources.arsc에 컴파일되지 않은 리소스를 포함합니다.
@ -99,7 +99,7 @@ su 바이너리가 구성되면, 다른 안드로이드 앱이 `su` 바이너리
## Intents
인텐트는 안드로이드 앱이 구성 요소 간 또는 다른 앱과 통신하는 주요 수단입니다. 이러한 메시지 객체는 앱 간 또는 구성 요소 간에 데이터를 전달할 수 있으며, HTTP 통신에서 GET/POST 요청이 사용되는 방식과 유사합니다.
인텐트는 안드로이드 앱이 구성 요소 간 또는 다른 앱과 통신하는 주요 수단입니다. 이러한 메시지 객체는 앱 간 또는 구성 요소 간에 데이터를 전달할 수 있으며, HTTP 통신에서 GET/POST 요청이 사용되는 방식과 유사합니다.
따라서 인텐트는 기본적으로 **구성 요소 간에 전달되는 메시지**입니다. 인텐트는 **특정 구성 요소나 앱으로 지향될 수 있으며**, **특정 수신자 없이 전송될 수도 있습니다**.\
간단히 말해 인텐트는 다음과 같이 사용될 수 있습니다:
@ -120,7 +120,7 @@ su 바이너리가 구성되면, 다른 안드로이드 앱이 `su` 바이너리
안드로이드 구성 요소(활동/서비스/콘텐츠 제공자/브로드캐스트 수신자)의 중요한 측면은 그들의 가시성 또는 **공개 상태**입니다. 구성 요소가 **`exported`** 속성이 **`true`**로 설정되어 있거나 매니페스트에 인텐트 필터가 선언되어 있으면, 해당 구성 요소는 공개로 간주되며 다른 앱과 상호작용할 수 있습니다. 그러나 개발자는 이러한 구성 요소를 명시적으로 비공개로 유지하여 다른 앱과 의도치 않게 상호작용하지 않도록 할 수 있는 방법이 있습니다. 이는 매니페스트 정의에서 **`exported`** 속성을 **`false`**로 설정하여 달성됩니다.
또한, 개발자는 특정 권한을 요구하여 이러한 구성 요소에 대한 접근을 추가로 보안할 수 있는 옵션이 있습니다. **`permission`** 속성을 설정하여 지정된 권한을 가진 앱만 구성 요소에 접근할 수 있도록 강제할 수 있으며, 이는 누가 상호작용할 수 있는지에 대한 추가 보안 및 제어 계층을 추가합니다.
또한, 개발자는 특정 권한을 요구하여 이러한 구성 요소에 대한 접근을 더욱 안전하게 할 수 있는 옵션이 있습니다. **`permission`** 속성을 설정하여 지정된 권한을 가진 앱만 구성 요소에 접근할 수 있도록 하여, 누가 상호작용할 수 있는지에 대한 추가 보안 및 제어를 추가할 수 있습니다.
```java
<activity android:name=".MyActivity" android:exported="false">
<!-- Intent filters go here -->
@ -132,9 +132,9 @@ su 바이너리가 구성되면, 다른 안드로이드 앱이 `su` 바이너리
```java
Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
```
**이전 선언된 인텐트의 Action은 ACTION_SEND이며, Extra는 mailto Uri입니다(Extra는 인텐트가 기대하는 추가 정보입니다).**
**이전**에 선언된 인텐트의 **액션**은 **ACTION_SEND**이고, **엑스트라**는 mailto **Uri**입니다(엑스트라는 인텐트가 기대하는 추가 정보입니다).
**이 인텐트는 다음 예와 같이 매니페스트 내에 선언되어야 합니다:**
이 인텐트는 다음 예와 같이 매니페스트 내에 선언되어야 합니다:
```xml
<activity android:name="ShareActivity">
<intent-filter>
@ -143,13 +143,13 @@ Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
</intent-filter>
</activity>
```
An intent-filter는 메시지를 수신하기 위해 **action**, **data** 및 **category**와 일치해야 합니다.
인텐트 필터는 메시지를 수신하기 위해 **action**, **data** 및 **category**와 일치해야 합니다.
"Intent resolution" 프로세스는 각 메시지를 수신해야 할 앱을 결정합니다. 이 프로세스는 **priority attribute**를 고려하며, 이는 i**ntent-filter declaration**에서 설정할 수 있고, **더 높은 우선 순위를 가진 것이 선택됩니다**. 이 우선 순위는 -1000에서 1000 사이로 설정할 수 있으며, 애플리케이션은 `SYSTEM_HIGH_PRIORITY` 값을 사용할 수 있습니다. **충돌**이 발생하면 "choser" 창이 나타나 **사용자가 결정할 수 있습니다**.
"인텐트 해상도" 프로세스는 각 메시지를 수신할 앱을 결정합니다. 이 프로세스는 **우선 순위 속성**을 고려하며, 이는 **인텐트 필터 선언**에서 설정할 수 있고, **더 높은 우선 순위를 가진 것이 선택됩니다**. 이 우선 순위는 -1000에서 1000 사이로 설정할 수 있으며, 애플리케이션은 `SYSTEM_HIGH_PRIORITY` 값을 사용할 수 있습니다. **충돌**이 발생하면 "선택기" 창이 나타나 **사용자가 결정할 수 있습니다**.
### Explicit Intents
### 명시적 인텐트
명시적 인텐트는 타겟하는 클래스 이름을 지정합니다:
명시적 인텐트는 타겟으로 하는 클래스 이름을 지정합니다:
```java
Intent downloadIntent = new (this, DownloadService.class):
```
@ -161,30 +161,30 @@ context.startService(intent);
```
### Pending Intents
은 다른 애플리케이션이 **당신의 애플리케이션을 대신하여 작업을 수행할 수 있도록** 하며, 당신의 앱의 아이덴티티와 권한을 사용합니다. Pending Intent를 구성할 때는 **의도를 지정하고 수행할 작업을 명시해야** 합니다. **명시된 의도가 명시적이지 않으면** (어떤 의도가 호출할 수 있는지 선언하지 않음) **악의적인 애플리케이션이 피해자 앱을 대신하여 명시된 작업을 수행할 수 있습니다**. 게다가, **작업이 명시되지 않으면**, 악의적인 앱은 **피해자를 대신하여 어떤 작업이든 수행할 수 있습니다**.
은 다른 애플리케이션이 **당신의 애플리케이션을 대신하여 작업을 수행할 수 있게** 해줍니다. Pending Intent를 구성할 때는 **의도와 수행할 작업을 지정해야** 합니다. **선언된 의도가 명시적이지 않으면** (어떤 의도가 호출할 수 있는지 선언하지 않음) **악의적인 애플리케이션이 피해자 앱을 대신하여 선언된 작업을 수행할 수 있습니다**. 게다가, **작업이 지정되지 않으면**, 악의적인 앱은 **피해자를 대신하여 어떤 작업이든 수행할 수 있습니다**.
### Broadcast Intents
이전의 인텐트와 달리, 단일 앱에서만 수신되는 것이 아니라, broadcast intents**여러 앱에서 수신될 수 있습니다**. 그러나 API 버전 14부터는 **메시지를 수신해야 하는 앱을 지정할 수 있습니다** Intent.setPackage를 사용하여.
이전의 의도와 달리, 단일 앱만 수신하는 것이 아니라 방송 의도**여러 앱에서 수신될 수 있습니다**. 그러나 API 버전 14부터는 **메시지를 수신해야 하는 앱을 지정할 수 있습니다**. Intent.setPackage를 사용하여 가능합니다.
또한 **브로드캐스트를 보낼 때 권한을 지정할 수도 있습니다**. 수신 앱은 해당 권한을 가져야 합니다.
또한 방송을 보낼 때 **권한을 지정할 수도 있습니다**. 수신 앱은 해당 권한을 가져야 합니다.
브로드캐스트에는 **두 가지 유형**이 있습니다: **정상** (비동기) 및 **정렬된** (동기). **순서**는 **수신기** 요소 내에서 **구성된 우선 순위**에 기반합니다. **각 앱은 브로드캐스트를 처리, 중계 또는 삭제할 수 있습니다.**
방송에는 **두 가지 유형**이 있습니다: **정상** (비동기) 및 **정렬된** (동기). **순서**는 **수신기** 요소 내에서 **구성된 우선 순위**에 기반합니다. **각 앱은 방송을 처리, 중계 또는 삭제할 수 있습니다.**
`Context` 클래스의 `sendBroadcast(intent, receiverPermission)` 함수를 사용하여 **브로드캐스트**를 **보낼** 수 있습니다.\
`Context` 클래스의 `sendBroadcast(intent, receiverPermission)` 함수를 사용하여 **방송을 보낼 수 있습니다**.\
또한 **`LocalBroadCastManager`**의 **`sendBroadcast`** 함수를 사용하면 **메시지가 앱을 떠나지 않도록** 보장합니다. 이를 사용하면 수신기 구성 요소를 내보낼 필요조차 없습니다.
### Sticky Broadcasts
이러한 종류의 브로드캐스트는 **전송된 후 오랜 시간 동안 접근할 수 있습니다**.\
들은 API 레벨 21에서 사용 중단되었으며 **사용하지 않는 것이 권장됩니다**.\
**이들은 모든 애플리케이션이 데이터를 엿볼 수 있도록 허용하지만, 또한 데이터를 수정할 수 있도록 합니다.**
이러한 종류의 방송은 **전송된 후 오랫동안 접근할 수 있습니다**.\
것은 API 레벨 21에서 사용 중단되었으며 **사용하지 않는 것이 좋습니다**.\
**이들은 모든 애플리케이션이 데이터를 엿볼 수 있게 하지만, 수정할 수도 있습니다.**
"sticky"라는 단어가 포함된 함수(예: **`sendStickyBroadcast`** 또는 **`sendStickyBroadcastAsUser`**)를 발견하면, **영향을 확인하고 제거하려고 시도하십시오**.
"sticky"라는 단어가 포함된 함수(예: **`sendStickyBroadcast`** 또는 **`sendStickyBroadcastAsUser`**)를 발견하면, **영향을 확인하고 제거하도록 시도하세요**.
## Deep links / URL schemes
안드로이드 애플리케이션에서 **딥 링크**는 URL을 통해 직접 작업(Intent)을 시작하는 데 사용됩니다. 이는 활동 내에서 특정 **URL 스킴**을 선언함으로써 이루어집니다. 안드로이드 기기가 **이 스킴을 가진 URL에 접근하려고 할 때**, 애플리케이션 내에서 지정된 활동이 시작됩니다.
안드로이드 애플리케이션에서 **딥 링크**는 URL을 통해 직접 작업(Intent)을 시작하는 데 사용됩니다. 이는 활동 내에서 특정 **URL 스킴**을 선언함으로써 이루어집니다. 안드로이드 장치가 **이 스킴을 가진 URL에 접근하려고 할 때**, 애플리케이션 내에서 지정된 활동이 시작됩니다.
스킴은 **`AndroidManifest.xml`** 파일에 선언되어야 합니다:
```xml
@ -217,7 +217,7 @@ HTML 페이지를 사용하지 않고 [딥 링크를 호출하는 방법](#explo
## AIDL - Android 인터페이스 정의 언어
**Android 인터페이스 정의 언어 (AIDL)**는 Android 애플리케이션에서 **프로세스 간 통신** (IPC)을 통해 클라이언트와 서비스 간의 통신을 용이하게 하기 위해 설계되었습니다. Android에서는 다른 프로세스의 메모리에 직접 접근하는 것이 허용되지 않기 때문에, AIDL은 객체를 운영 체제가 이해할 수 있는 형식으로 마샬링하여 서로 다른 프로세스 간의 통신을 쉽게 합니다.
**Android 인터페이스 정의 언어 (AIDL)**는 Android 애플리케이션에서 **프로세스 간 통신** (IPC)을 통해 클라이언트와 서비스 간의 통신을 용이하게 하기 위해 설계되었습니다. Android에서는 다른 프로세스의 메모리에 직접 접근하는 것이 허용되지 않기 때문에, AIDL은 객체를 운영 체제가 이해할 수 있는 형식으로 변환하여 서로 다른 프로세스 간의 통신을 쉽게 합니다.
### 주요 개념
@ -229,7 +229,7 @@ HTML 페이지를 사용하지 않고 [딥 링크를 호출하는 방법](#explo
## 구성 요소
여기에는 **액티비티, 서비스, 브로드캐스트 수신기 및 프로바이더**가 포함됩니다.
여기에는 **액티비티, 서비스, 브로드캐스트 리시버 및 프로바이더**가 포함됩니다.
### 런처 액티비티 및 기타 액티비티
@ -244,19 +244,19 @@ Android 앱에서 **액티비티**는 화면과 같으며, 앱의 사용자 인
</intent-filter>
</activity>
```
모든 앱이 런처 액티비티를 필요로 하는 것은 아니며, 사용자 인터페이스가 없는 백그라운드 서비스와 같은 앱 그렇습니다.
모든 앱이 런처 액티비티를 필요로 하는 것은 아니며, 사용자 인터페이스가 없는 백그라운드 서비스와 같은 앱은 특히 그렇습니다.
액티비티는 매니페스트에서 "exported"로 표시하여 다른 앱이나 프로세스에서 사용할 수 있도록 만들 수 있습니다. 이 설정은 다른 앱이 이 액티비티를 시작할 수 있도록 허용합니다:
```markdown
<service android:name=".ExampleExportedService" android:exported="true"/>
```
그러나 다른 앱 활동에 접근하는 것이 항상 보안 위험은 아닙니다. 민감한 데이터가 부적절하게 공유될 경우 우려가 발생하며, 이는 정보 유출로 이어질 수 있습니다.
그러나 다른 앱에서 활동에 접근하는 것이 항상 보안 위험은 아닙니다. 민감한 데이터가 부적절하게 공유될 경우 우려가 발생하며, 이는 정보 유출로 이어질 수 있습니다.
활동의 생명 주기 **는 onCreate 메서드로 시작**되며, UI를 설정하고 사용자와의 상호작용을 위해 활동을 준비합니다.
### 애플리케이션 서브클래스
안드로이드 개발에서 앱은 [Application](https://developer.android.com/reference/android/app/Application) 클래스의 **서브클래스**를 생성할 수 있는 옵션이 있지만, 필수는 아닙니다. 이러한 서브클래스가 정의되면 앱 내에서 가장 먼저 인스턴스화되는 클래스가 됩니다. 이 서브클래스에서 구현된 **`attachBaseContext`** 메서드는 **`onCreate`** 메서드 이전에 실행됩니다. 이 설정은 나머지 애플리케이션이 시작되기 전에 초기화를 가능하게 합니다.
안드로이드 개발에서 앱은 [Application](https://developer.android.com/reference/android/app/Application) 클래스의 **서브클래스**를 생성할 수 있는 옵션이 있지만, 필수는 아닙니다. 이러한 서브클래스가 정의되면, 앱 내에서 가장 먼저 인스턴스화되는 클래스가 됩니다. 이 서브클래스에서 구현된 **`attachBaseContext`** 메서드는 **`onCreate`** 메서드 이전에 실행됩니다. 이 설정은 나머지 애플리케이션이 시작되기 전에 초기화를 조기에 수행할 수 있게 합니다.
```java
public class MyApp extends Application {
@Override
@ -274,11 +274,11 @@ super.onCreate();
```
### Services
[Services](https://developer.android.com/guide/components/services)는 **백그라운드 작업자**로, 사용자 인터페이스 없이 작업을 실행할 수 있습니다. 이러한 작업은 사용자가 다른 애플리케이션으로 전환하더라도 계속 실행될 수 있어, 서비스는 **장기 실행 작업**에 필수적입니다.
[Services](https://developer.android.com/guide/components/services)는 **백그라운드 작업자**로, 사용자 인터페이스 없이 작업을 실행할 수 있습니다. 이러한 작업은 사용자가 다른 애플리케이션으로 전환하더라도 계속 실행될 수 있어, **장기 실행 작업**에 필수적입니다.
서비스는 다재다능하며, 다양한 방법으로 시작될 수 있으며, **Intents**가 애플리케이션의 진입점으로서 서비스를 시작하는 주요 방법입니다. `startService` 메서드를 사용하여 서비스가 시작되면, `onStart` 메서드가 작동을 시작하고 `stopService` 메서드가 명시적으로 호출될 때까지 계속 실행됩니다. 또는 서비스의 역할이 활성 클라이언트 연결에 의존하는 경우, `bindService` 메서드를 사용하여 클라이언트를 서비스에 바인딩하고, 데이터 전송을 위해 `onBind` 메서드를 활성화합니다.
Services는 다재다능하며, 다양한 방법으로 시작될 수 있으며, **Intents**가 애플리케이션의 진입점 시작하는 주요 방법입니다. `startService` 메서드를 사용하여 서비스가 시작되면, `onStart` 메서드가 작동을 시작하고 `stopService` 메서드가 명시적으로 호출될 때까지 계속 실행됩니다. 또는 서비스의 역할이 활성 클라이언트 연결에 의존하는 경우, `bindService` 메서드를 사용하여 클라이언트를 서비스에 바인딩하고, 데이터 전송을 위해 `onBind` 메서드를 활성화합니다.
서비스의 흥미로운 응용 프로그램에는 백그라운드 음악 재생이나 사용자와 앱 간의 상호작용을 방해하지 않고 네트워크 데이터 가져오기가 포함됩니다. 또한, 서비스는 **내보내기**를 통해 동일한 장치의 다른 프로세스에서 접근할 수 있도록 만들 수 있습니다. 이는 기본 동작이 아니며 Android Manifest 파일에서 명시적인 구성이 필요합니다:
서비스의 흥미로운 응용 프로그램에는 백그라운드 음악 재생 또는 사용자와 앱 간의 상호작용을 방해하지 않고 네트워크 데이터 가져오기가 포함됩니다. 또한, 서비스는 **내보내기**를 통해 동일한 장치의 다른 프로세스에서 접근할 수 있도록 만들 수 있습니다. 이는 기본 동작이 아니며 Android Manifest 파일에서 명시적인 구성이 필요합니다:
```xml
<service android:name=".ExampleExportedService" android:exported="true"/>
```
@ -286,19 +286,19 @@ super.onCreate();
**Broadcast receivers**는 메시징 시스템에서 리스너 역할을 하여 여러 애플리케이션이 시스템의 동일한 메시지에 응답할 수 있도록 합니다. 앱은 **Manifest**를 통해 또는 **`registerReceiver`** API를 사용하여 앱 코드 내에서 **두 가지 주요 방법**으로 **리시버를 등록**할 수 있습니다. Manifest에서는 브로드캐스트가 권한으로 필터링되며, 동적으로 등록된 리시버는 등록 시 권한을 지정할 수도 있습니다.
**Intent 필터**는 두 등록 방법 모두에서 중요하며, 어떤 브로드캐스트가 리시버를 트리거하는지를 결정합니다. 일치하는 브로드캐스트가 전송되면 리시버의 **`onReceive`** 메서드가 호출되어 앱이 저전압 경고에 대한 반응과 같은 방식으로 적절히 반응할 수 있게 합니다.
**Intent 필터**는 두 등록 방법 모두에서 중요하며, 어떤 브로드캐스트가 리시버를 트리거하는지를 결정합니다. 일치하는 브로드캐스트가 전송되면 리시버의 **`onReceive`** 메서드가 호출되어 앱이 저전력 경고에 따라 행동을 조정하는 등의 방식으로 반응할 수 있게 합니다.
브로드캐스트는 **비동기**일 수 있으며, 모든 리시버에 순서 없이 도달하거나 **동기**일 수 있으며, 리시버가 설정된 우선 순위에 따라 브로드캐스트를 받습니다. 그러나 모든 앱이 자신을 우선 순위로 설정하여 브로드캐스트를 가로챌 수 있는 잠재적인 보안 위험이 있다는 점에 유의해야 합니다.
브로드캐스트는 **비동기**일 수 있으며, 모든 리시버에 순서 없이 도달하거나 **동기**일 수 있으며, 리시버가 설정된 우선 순위에 따라 브로드캐스트를 받습니다. 그러나 모든 앱이 브로드캐스트를 가로채기 위해 자신을 우선시할 수 있으므로 잠재적인 보안 위험을 주의해야 합니다.
리시버의 기능을 이해하려면 해당 클래스 내에서 **`onReceive`** 메서드를 찾아보세요. 이 메서드의 코드는 수신된 Intent를 조작할 수 있으며, 특히 Intent를 수정하거나 삭제할 수 있는 **Ordered Broadcasts**에서 리시버에 의한 데이터 검증의 필요성을 강조합니다.
### Content Provider
**Content Providers**는 앱 간에 **구조화된 데이터**를 **공유**하는 데 필수적이며, 데이터 보안을 보장하기 위해 **권한**을 구현하는 것이 중요합니다. 이들은 앱이 데이터베이스, 파일 시스템 또는 웹을 포함한 다양한 소스의 데이터에 접근할 수 있도록 합니다. **`readPermission`** 및 **`writePermission`**과 같은 특정 권한은 접근 제어에 중요합니다. 또한, 앱의 매니페스트에서 **`grantUriPermission`** 설정을 통해 임시 접근을 부여할 수 있으며, `path`, `pathPrefix`, `pathPattern`과 같은 속성을 활용하여 세부적인 접근 제어를 할 수 있습니다.
**Content Providers**는 앱 간에 **구조화된 데이터**를 **공유**하는 데 필수적이며, 데이터 보안을 보장하기 위해 **권한** 구현의 중요성을 강조합니다. 이들은 앱이 데이터베이스, 파일 시스템 또는 웹을 포함한 다양한 소스의 데이터에 접근할 수 있도록 합니다. **`readPermission`** 및 **`writePermission`**과 같은 특정 권한은 접근 제어에 중요합니다. 또한, 앱의 매니페스트에서 **`grantUriPermission`** 설정을 통해 임시 접근을 부여할 수 있으며, `path`, `pathPrefix`, `pathPattern`과 같은 속성을 활용하여 세부적인 접근 제어를 수행합니다.
입력 검증은 SQL 인젝션과 같은 취약점을 방지하기 위해 매우 중요합니다. Content Providers는 데이터 조작 및 애플리케이션 간의 공유를 용이하게 하는 기본 작업인 `insert()`, `update()`, `delete()`, `query()`를 지원합니다.
**FileProvider**는 파일을 안전하게 공유하는 데 중점을 둔 전문화된 Content Provider입니다. 이는 앱의 매니페스트에 정의되며, `android:exported` 및 폴더 구성에 대한 `android:resource`와 같은 특정 속성을 사용하여 폴더에 대한 접근을 제어합니다. 민감한 데이터가 우연히 노출되지 않도록 디렉토리를 공유할 때 주의가 필요합니다.
**FileProvider**는 파일을 안전하게 공유하는 데 중점을 둔 전문화된 Content Provider입니다. 이는 앱의 매니페스트에 정의되며, 폴더에 대한 접근을 제어하기 위한 특정 속성을 포함하고 있으며, `android:exported``android:resource`가 폴더 구성으로 지정됩니다. 민감한 데이터가 우연히 노출되지 않도록 디렉토리를 공유할 때 주의해야 합니다.
FileProvider에 대한 예시 매니페스트 선언:
```xml
@ -323,14 +323,14 @@ android:resource="@xml/filepaths" />
## WebViews
WebViews는 Android 앱 내의 **미니 웹 브라우저**와 같으며, 웹 또는 로컬 파일에서 콘텐츠를 가져옵니다. 이들은 일반 브라우저와 유사한 위험에 직면하지만, 특정 **설정**을 통해 **위험을 줄이는 방법**이 있습니다.
WebViews는 Android 앱 내의 **미니 웹 브라우저**와 같으며, 웹 또는 로컬 파일에서 콘텐츠를 가져옵니다. 이들은 일반 브라우저와 유사한 위험에 직면하지만, 특정 **설정을 통해 이러한 위험을 줄일 수 있는 방법**이 있습니다.
Android는 두 가지 주요 WebView 유형을 제공합니다:
- **WebViewClient**는 기본 HTML에 적합하지만 JavaScript 경고 기능을 지원하지 않아 XSS 공격 테스트에 영향을 미칩니다.
- **WebViewClient**는 기본 HTML에 적합하지만 JavaScript 경고 기능을 지원하지 않아 XSS 공격 테스트 방식에 영향을 미칩니다.
- **WebChromeClient**는 전체 Chrome 브라우저 경험과 더 유사하게 작동합니다.
중요한 점은 WebView 브라우저가 장치의 주요 브라우저와 **쿠키를 공유하지** 않는다는 것입니다.
중요한 점은 WebView 브라우저가 장치의 주요 브라우저와 **쿠키를 공유하지 않는**다는 것입니다.
콘텐츠를 로드하기 위해 `loadUrl`, `loadData`, `loadDataWithBaseURL`와 같은 방법이 제공됩니다. 이러한 URL 또는 파일이 **안전하게 사용될 수 있는지** 확인하는 것이 중요합니다. 보안 설정은 `WebSettings` 클래스를 통해 관리할 수 있습니다. 예를 들어, `setJavaScriptEnabled(false)`로 JavaScript를 비활성화하면 XSS 공격을 방지할 수 있습니다.
@ -340,7 +340,7 @@ JavaScript "Bridge"는 Java 객체가 JavaScript와 상호작용할 수 있게
파일 접근을 제어하기 위해:
- 파일 접근을 비활성화하는 것(`setAllowFileAccess(false)`)은 파일 시스템에 대한 접근을 제한하며, 특정 자산에 대한 예외가 있어 비민감 콘텐츠에만 사용되도록 보장합니다.
- 파일 접근을 비활성화하는 것(`setAllowFileAccess(false)`)은 특정 자산에 대한 예외를 제외하고 파일 시스템에 대한 접근을 제한하여, 비민감 콘텐츠에만 사용되도록 보장합니다.
## 기타 앱 구성 요소 및 모바일 장치 관리
@ -365,4 +365,104 @@ if (dpm.isAdminActive(adminComponent)) {
dpm.setPasswordMinimumLength(adminComponent, 8);
}
```
## AIDL / Binder 서비스 열거 및 악용
Android *Binder* IPC는 많은 **시스템 및 공급업체 제공 서비스**를 노출합니다. 이러한 서비스는 적절한 권한 검사가 없이 내보내질 때 **공격 표면**이 됩니다 (AIDL 레이어 자체는 *접근 제어*를 수행하지 않습니다).
### 1. 실행 중인 서비스 발견
```bash
# from an adb shell (USB or wireless)
service list # simple one-liner
am list services # identical output, ActivityManager wrapper
```
1. Android 애플리케이션은 Java 또는 Kotlin으로 작성됩니다.
2. Android 앱은 APK 파일 형식으로 배포됩니다.
3. AndroidManifest.xml 파일은 앱의 구성 요소를 정의합니다.
4. 앱의 권한은 AndroidManifest.xml에서 설정됩니다.
5. 앱의 리소스는 res 폴더에 저장됩니다.
```
145 mtkconnmetrics: [com.mediatek.net.connectivity.IMtkIpConnectivityMetrics]
146 wifi : [android.net.wifi.IWifiManager]
```
* **인덱스** (첫 번째 열)은 런타임에 할당됩니다 재부팅 간에 이를 신뢰하지 마십시오.
* **바인더 이름** (예: `mtkconnmetrics`)은 `service call`에 전달될 것입니다.
* 괄호 안의 값은 스텁이 생성된 완전한 **AIDL 인터페이스**입니다.
### 2. 인터페이스 설명자 얻기 (PING)
모든 바인더 스텁은 자동으로 **트랜잭션 코드 `0x5f4e5446`** (`1598968902` 십진수, ASCII "_NTF")를 구현합니다.
```bash
# "ping" the service
service call mtkconnmetrics 1 # 1 == decimal 1598968902 mod 2^32
```
유효한 응답은 `Parcel` 내부에 UTF-16 문자열로 인코딩된 인터페이스 이름을 반환합니다.
### 3. 트랜잭션 호출
구문: `service call <name> <code> [type value ...]`
일반 인수 지정자:
* `i32 <int>` 부호 있는 32비트 값
* `i64 <long>` 부호 있는 64비트 값
* `s16 <string>` UTF-16 문자열 (Android 13+는 `utf16` 사용)
MediaTek 핸드셋에서 uid **1**로 네트워크 모니터링 시작:
```bash
service call mtkconnmetrics 8 i32 1
```
### 4. 알 수 없는 메서드에 대한 무차별 대입
헤더 파일이 없을 때는 **코드를 반복**하여 오류가 다음과 같이 변경될 때까지 진행할 수 있습니다:
```
Result: Parcel(00000000 00000000) # "Not a data message"
```
정상 `Parcel` 응답 또는 `SecurityException`.
```bash
for i in $(seq 1 50); do
printf "[+] %2d -> " $i
service call mtkconnmetrics $i 2>/dev/null | head -1
done
```
서비스가 **proguard**로 컴파일된 경우 매핑을 추측해야 합니다 다음 단계를 참조하세요.
### 5. Mapping codes ↔ methods via onTransact()
인터페이스를 구현하는 jar/odex를 디컴파일합니다 (AOSP 스텁의 경우 `/system/framework`를 확인하세요; OEM은 종종 `/system_ext` 또는 `/vendor`를 사용합니다).
`Stub.onTransact()`를 검색하세요 여기에는 거대한 `switch(transactionCode)`가 포함되어 있습니다:
```java
case TRANSACTION_updateCtaAppStatus: // 5
data.enforceInterface(DESCRIPTOR);
int appId = data.readInt();
boolean ok = data.readInt() != 0;
updateCtaAppStatus(appId, ok);
reply.writeNoException();
return true;
```
이제 프로토타입과 **매개변수 유형**이 명확합니다.
### 6. 누락된 권한 검사 찾기
구현(종종 내부 `Impl` 클래스)은 권한 부여를 담당합니다:
```java
private void updateCtaAppStatus(int uid, boolean status) {
if (!isPermissionAllowed()) {
throw new SecurityException("uid " + uid + " rejected");
}
/* privileged code */
}
```
이러한 논리 또는 특권 UID의 화이트리스트(예: `uid == 1000 /*system*/` )의 부재는 **취약점 지표**입니다.
사례 연구 *MediaTek* `startMonitorProcessWithUid()` (트랜잭션 **8**)은 권한 게이트 없이 Netlink 메시지를 **완전히** 실행하여 비특권 앱이 커널의 Netfilter 모듈과 상호작용하고 시스템 로그를 스팸할 수 있게 합니다.
### 7. 평가 자동화
Binder 정찰을 가속화하는 도구 / 스크립트:
* [binderfs](https://android.googlesource.com/platform/frameworks/native/+/master/cmds/binderfs/) 서비스별 노드가 있는 `/dev/binderfs`를 노출
* [`binder-scanner.py`](https://github.com/adenflare/binder-scanner) 바인더 테이블을 탐색하고 ACL을 출력
* Frida 단축키: `Java.perform(()=>console.log(android.os.ServiceManager.listServices().toArray()))`
---
## References
- [Android Services 101 Pentest Partners](https://www.pentestpartners.com/security-blog/android-services-101/)
- [Android Developer Docs AIDL](https://developer.android.com/guide/components/aidl)
- [Android Developer Docs IBinder](https://developer.android.com/reference/android/os/IBinder)
- [Understanding Binder, Talk @ Google](https://www.youtube.com/watch?v=O-UHvFjxwZ8)
{{#include ../../banners/hacktricks-training.md}}