mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/mobile-pentesting/android-app-pentesting/android-applic
This commit is contained in:
parent
39c86cb25f
commit
e8f5883e90
@ -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}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user