iOS Pentesting
Tip
AWSハッキングを学び、実践する:
HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
iOS 基礎
テスト環境
このページでは、iOS simulator、emulators、および jailbreaking に関する情報を確認できます:
初期解析
基本的な iOS テスト操作
テスト中は、いくつかの操作が推奨されます(デバイスへの接続、ファイルの読み書き/アップロード/ダウンロード、ツールの使用など)。したがって、これらの操作のいずれかを実行する方法が不明な場合は、次のページを読み始めてください:
Tip
次のステップでは アプリがデバイスにインストールされており、かつアプリの IPA ファイル をすでに取得している必要があります。
取得方法については Basic iOS Testing Operations を参照してください。
基本的な静的解析
興味深い iOS - IPA ファイル用のデコンパイラの例:
IPA ファイルに対して自動的な Static Analysis を実行するには、ツール MobSF の使用を推奨します。
バイナリに存在する保護の識別:
- PIE (Position Independent Executable): 有効な場合、アプリケーションは起動ごとにランダムなメモリアドレスにロードされ、初期メモリアドレスを予測しにくくします。
otool -hv <app-binary> | grep PIE # It should include the PIE flag
- Stack Canaries: スタックの整合性を検証するために、関数呼び出し前にスタック上に“canary”値を配置し、関数終了時に再検証します。
otool -I -v <app-binary> | grep stack_chk # It should include the symbols: stack_chk_guard and stack_chk_fail
- ARC (Automatic Reference Counting): 一般的なメモリ破損の脆弱性を防ぐ仕組み
otool -I -v <app-binary> | grep objc_release # It should include the _objc_release symbol
- Encrypted Binary: バイナリは暗号化されているべきです
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # The cryptid should be 1
敏感/不安全な関数の識別
- 弱いハッシュアルゴリズム
# On the iOS device
otool -Iv <app> | grep -w "_CC_MD5"
otool -Iv <app> | grep -w "_CC_SHA1"
# On linux
grep -iER "_CC_MD5"
grep -iER "_CC_SHA1"
- 安全でない乱数関数
# On the iOS device
otool -Iv <app> | grep -w "_random"
otool -Iv <app> | grep -w "_srand"
otool -Iv <app> | grep -w "_rand"
# On linux
grep -iER "_random"
grep -iER "_srand"
grep -iER "_rand"
- 安全でない ‘Malloc’ 関数
# On the iOS device
otool -Iv <app> | grep -w "_malloc"
# On linux
grep -iER "_malloc"
- 安全でない/脆弱な関数群
# On the iOS device
otool -Iv <app> | grep -w "_gets"
otool -Iv <app> | grep -w "_memcpy"
otool -Iv <app> | grep -w "_strncpy"
otool -Iv <app> | grep -w "_strlen"
otool -Iv <app> | grep -w "_vsnprintf"
otool -Iv <app> | grep -w "_sscanf"
otool -Iv <app> | grep -w "_strtok"
otool -Iv <app> | grep -w "_alloca"
otool -Iv <app> | grep -w "_sprintf"
otool -Iv <app> | grep -w "_printf"
otool -Iv <app> | grep -w "_vsprintf"
# On linux
grep -R "_gets"
grep -iER "_memcpy"
grep -iER "_strncpy"
grep -iER "_strlen"
grep -iER "_vsnprintf"
grep -iER "_sscanf"
grep -iER "_strtok"
grep -iER "_alloca"
grep -iER "_sprintf"
grep -iER "_printf"
grep -iER "_vsprintf"
一般的な Jailbreak 検出方法
- ファイルシステムチェック:
/Applications/Cydia.appや/Library/MobileSubstrate/MobileSubstrate.dylibのような一般的な jailbreak ファイルやディレクトリの存在を確認する。 - サンドボックス違反: 非 Jailbroken デバイスではブロックされるはずのファイルシステムの制限領域にアクセスしようとする。
- API チェック:
fork()のような禁止された呼び出しやsystem()を使って /bin/sh が存在するかを確認できるかどうかをチェックする。 - プロセスチェック:
Cydia、Substrate、sshのような既知の jailbreak 関連プロセスの存在を監視する。 - カーネルエクスプロイト: jailbreak に一般的に使われるカーネルエクスプロイトの存在をチェックする。
- 環境変数:
DYLD_INSERT_LIBRARIESのような jailbreak の兆候を示す環境変数を検査する。 - ライブラリチェック: アプリプロセスにロードされているライブラリを確認する。
- スキームの確認:
canOpenURL(URL(string: "cydia://"))のようなスキームチェック。
一般的なアンチデバッグ検出方法
- デバッガ存在チェック:
sysctlやその他の方法を使ってデバッガがアタッチされているかを確認する。 - アンチデバッグ API:
ptraceやSIGSTOPのようなアンチデバッグ API の呼び出しを探す(例:ptrace(PT_DENY_ATTACH, 0, 0, 0))。 - タイミングチェック: 特定の操作にかかる時間を測定し、デバッグの兆候となる差異を探す。
- メモリチェック: 既知のデバッガアーティファクトや改変がないかメモリを検査する。
- 環境変数: デバッグセッションを示す可能性のある環境変数をチェックする。
- Mach ポート: mach exception ports がデバッガによって使用されているかを検出する。
アンチデバッグ & アンチタンパー技術(重ね合わせによるチェック)
実際のアプリは事前実行(pre-exec)、アタッチ時(on-attach)、継続的チェックを重ねることが多いです。検出すべき一般的なパターン(およびテスト中に中和する方法):
- Private API のサイドチャネルフィンガープリント: private launch API(例:
SBSLaunchApplicationWithIdentifierAndURLAndLaunchOptions)が、戻りコード/ログに基づいてインストール済みバンドルID(com.opa334.TrollStore、org.coolstar.SileoStore、com.tigisoftware.Filzaなど)をプローブするために悪用されます。呼び出しをフックして引数/戻り値を消毒し、クリーンなデバイスをエミュレートします。 - コード署名状態による自己証明:
csops()とCS_OPS_ENTITLEMENTS_BLOBがエンタイトルメントを読み取り、予期しない値で終了します。これをリソースの CRC32/MD5、証明書検証、LC_ENCRYPTION_INFO_64のような Mach-O メタデータとの整合性チェックと組み合わせて、再署名やパッチを検出します。これらのルーチンにインストルメントを入れ、解析中に「期待される」結果を返すようにします。 - アタッチ時にプロセスを終了させる:
ptrace(PT_DENY_ATTACH)とabort()/exit()の組み合わせ。終了パスを無効化するか、ptraceをフックして拒否せずに成功するようにして回避します。 - クラッシュフォレンジクスの破壊: クラッシュ前に CPU レジスタを上書きしてバックトレースを破壊します。クラッシュログに頼るのではなく、検出経路の早い段階でブレークポイント/フックを行う方が良いです。
- Jetsam による終了: 意図的なメモリプレッシャーで jetsam をトリガーし、通常のクラッシュログが得られないようにする。検出ロジック周辺の大きな割り当てを探し、それらを制限/短絡してログを保持します。
- 遅延強制を伴う継続チェック: ハートビートタイマーが検出を再実行し後で強制する。タイマー/dispatch source をトレースし、遅延キルパスをバイパスしてプロセスを生存させます。
基本的な動的解析
MobSF が行う dynamic analysis を確認してください。さまざまなビューを移動して操作する必要がありますが、多くのクラスにフックを行い、作業が完了するとレポートを生成します。
インストール済みアプリの列挙
インストール済みアプリの bundle identifier を特定するには、コマンド frida-ps -Uai を使用してください。
$ 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
基本的な Enumeration & Hooking
アプリケーションのコンポーネントを enumerate the components of the application する方法と、objection を使ってメソッドやクラスを簡単に hook methods and classes する方法を学びます:
IPA の構造
IPA file の構造は本質的に zipped package と同じです。拡張子を .zip に変更すると、中身を decompressed して内容を確認できます。この構造内で、Bundle はインストール可能な完全なパッケージ化されたアプリケーションを表します。内部にはアプリケーションのリソースを格納する <NAME>.app というディレクトリがあります。
Info.plist: このファイルはアプリケーションの特定の構成情報を保持します。_CodeSignature/: このディレクトリには署名を含む plist ファイルがあり、バンドル内のすべてのファイルの整合性を保証します。Assets.car: アイコンなどのアセットファイルを格納する圧縮アーカイブです。Frameworks/: このフォルダにはアプリケーションのネイティブライブラリが格納され、.dylibや.frameworkファイルの形で含まれることがあります。PlugIns/: ここにはアプリの拡張(.appexファイルとして知られる)が含まれる場合がありますが、常に存在するわけではありません。 *Core Data: オフラインでの恒久的なデータ保存、一時データのキャッシュ、単一デバイス上での undo 機能を追加するために使用されます。同一 iCloud アカウント内の複数デバイスでデータを同期するために、Core Data は自動的にスキーマを CloudKit コンテナにミラーします。PkgInfo:PkgInfoファイルは、アプリケーションまたはバンドルの type と creator コードを指定する別の方法です。- en.lproj, fr.proj, Base.lproj: これらは特定の言語向けのリソースを含むロケールパックであり、サポートされていない言語の場合のデフォルトリソースを提供します。
- Security:
_CodeSignature/ディレクトリはデジタル署名を通じてバンドル内のすべてのファイルの整合性を検証することで、アプリのセキュリティにおいて重要な役割を果たします。 - Asset Management:
Assets.carファイルは圧縮を使用してグラフィックアセットを効率的に管理し、アプリのパフォーマンス最適化とサイズ削減に寄与します。 - Frameworks and PlugIns: これらのディレクトリは iOS アプリケーションのモジュール性を示しており、再利用可能なコードライブラリ(
Frameworks/)を含めたり、アプリ機能を拡張したり(PlugIns/)できます。 - Localization: この構造は複数言語をサポートしており、特定の言語パックを含めることでグローバルな展開を容易にします。
Info.plist
Info.plist は iOS アプリケーションの基盤として機能し、key-value ペアの形式で主要な構成データをカプセル化します。このファイルはアプリケーションだけでなく、バンドルされたアプリ拡張やフレームワークにも必須です。XML またはバイナリ形式のいずれかで構造化されており、アプリの権限からセキュリティ構成に至るまで重要な情報を保持します。利用可能なキーの詳細については、Apple Developer Documentation を参照してください。
このファイルをより扱いやすい形式で扱いたい場合、macOS 上の plutil(バージョン 10.2 以降でネイティブに利用可能)や Linux 上の plistutil を使用して簡単に XML に変換できます。変換コマンドは次のとおりです:
- For macOS:
$ plutil -convert xml1 Info.plist
- Linux向け:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
Info.plist ファイルが明らかにする無数の情報の中で、特に注目すべきエントリにはアプリの許可文字列(UsageDescription)、カスタム URL スキーム(CFBundleURLTypes)、および App Transport Security の設定(NSAppTransportSecurity)があります。これらのエントリは、UTExportedTypeDeclarations / UTImportedTypeDeclarations のようなエクスポート/インポートされたカスタムドキュメントタイプとともに、ファイルを調べるか単純な grep コマンドを使うことで容易に見つけられます:
$ grep -i <keyword> Info.plist
データパス
iOS環境では、ディレクトリはシステムアプリケーションとユーザーインストールアプリケーション向けにそれぞれ割り当てられます。システムアプリは/Applicationsディレクトリに配置され、ユーザーインストールされたアプリは/var/mobile/containers/Data/Application/の下に置かれます。これらのアプリには128-bit UUIDとして知られる一意の識別子が割り当てられており、ディレクトリ名がランダムであるため手動でアプリのフォルダを特定するのは困難です。
Warning
iOSではアプリはサンドボックス化される必要があるため、各アプリは**
$HOME/Library/Containers内にアプリのCFBundleIdentifier**をフォルダ名としたフォルダを持ちます。ただし、両方のフォルダ(data & container folders)には、両者を
MCMetadataIdentifierキーで関連付ける**.com.apple.mobile_container_manager.metadata.plist**というファイルがあります)。
ユーザーインストールアプリのインストールディレクトリの特定を容易にするため、objection toolは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
または、find コマンドを使用して、/private/var/containers 内でアプリ名を検索できます:
find /private/var/containers -name "Progname*"
psやlsofといったコマンドは、それぞれアプリのプロセスを特定したり開いているファイルを一覧表示したりするためにも利用でき、アプリケーションのアクティブなディレクトリパスに関する洞察を提供します:
ps -ef | grep -i <app-name>
lsof -p <pid> | grep -i "/containers" | head -n 1
バンドルディレクトリ:
- AppName.app
- これは以前IPAで見たApplication Bundleで、重要なアプリケーションデータ、静的コンテンツ、およびアプリケーションのコンパイル済みバイナリを含みます。
- このディレクトリはユーザーに表示されますが、 ユーザーは書き込めません。
- このディレクトリ内のコンテンツは バックアップされません。
- このフォルダの内容は コード署名を検証する ために使用されます。
データディレクトリ:
- Documents/
- ユーザー生成データをすべて含みます。これらのデータはアプリのエンドユーザーによって生成されます。
- ユーザーに表示され、 ユーザーは書き込めます。
- このディレクトリ内のコンテンツは バックアップされます。
- アプリは
NSURLIsExcludedFromBackupKeyを設定することでパスをバックアップ対象から除外できます。 - Library/
- ユーザー固有ではないファイル を含みます。例として caches, preferences, cookies, および property list (plist) 設定ファイルがあります。
- iOSアプリは通常
Application SupportとCachesのサブディレクトリを使用しますが、アプリはカスタムのサブディレクトリを作成できます。 - Library/Caches/
- 半永続的なキャッシュファイル を含みます。
- ユーザーには見えず、 ユーザーは書き込めません。
- このディレクトリ内のコンテンツは バックアップされません。
- アプリが実行されておらずストレージが不足している場合、OSはこのディレクトリ内のファイルを自動的に削除することがあります。
- Library/Application Support/
- アプリの実行に必要な 永続的な ファイル を含みます。
- 非表示 で ユーザー、およびユーザーは書き込めません。
- このディレクトリ内のコンテンツは バックアップ されます。
- アプリは
NSURLIsExcludedFromBackupKeyを設定することでパスをバックアップ対象から除外できます。 - Library/Preferences/
- アプリケーション再起動後も 保持される プロパティを保存するために使用されます。
- 情報は暗号化されず、アプリケーションサンドボックス内の [BUNDLE_ID].plist というplistファイルに保存されます。
NSUserDefaultsを使用して格納されたすべてのキー/値ペアはこのファイルにあります。- tmp/
- このディレクトリはアプリ起動間で持続する必要のない 一時ファイル を書き込むために使用します。
- 非永続的なキャッシュファイルを含みます。
- 非表示 ユーザーからは見えません。
- このディレクトリ内のコンテンツはバックアップされません。
- アプリが実行されておらずストレージが不足している場合、OSはこのディレクトリ内のファイルを自動的に削除することがあります。
Let’s take a closer look at iGoat-Swift’s Application Bundle (.app) directory inside the Bundle directory (/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.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
Binary Reversing
<application-name>.app フォルダの中に <application-name> というバイナリファイルが見つかります。これは実行されるファイルです。You can perform a basic inspection of the binary with the tool 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
バイナリの逆アセンブル
text section を逆アセンブルする:
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 segmentを出力するには、次のコマンドを使用します:
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 です。
データストレージ
iOS がデバイスにデータをどのように保存するかについては、次のページを参照してください:
Warning
次の情報の保存場所は、アプリのインストール直後、アプリの全機能を確認した後、さらにはあるユーザからログアウトして別のユーザでログインした後にも確認する必要があります。
目的は、アプリケーションの保護されていない機密情報(パスワード、トークン)、現在のユーザおよび過去にログインしていたユーザの情報を見つけることです。
Plist
plist ファイルは構造化された XML ファイルで、キーと値のペアを含みます。これは永続データを格納する方法であり、時にはこれらのファイルに機密情報が含まれていることがあります。アプリをインストールした直後や集中的に使用した後に、これらのファイルを確認して新しいデータが書き込まれていないかをチェックすることを推奨します。
plist ファイルにデータを永続化する最も一般的な方法は、NSUserDefaults の使用です。この plist ファイルはアプリのサンドボックス内の Library/Preferences/<appBundleID>.plist に保存されます。
The NSUserDefaults class provides a programmatic interface for interacting with the default system. The default system allows an application to customize its behaviour according to user preferences. Data saved by NSUserDefaults can be viewed in the application bundle. This class stores データをplist ファイルに格納しますが、少量のデータを扱うことを想定しています。
このデータには信頼されたコンピュータから直接アクセスできなくなっていますが、バックアップを行うことでアクセス可能です。
objection の ios nsuserdefaults get を使って、NSUserDefaults に保存された情報をダンプできます。
アプリケーションが使用するすべての 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ユーザー向け: まず libplist-utils をインストールし、plistutil を使ってファイルを変換してください:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
Objection セッション内: モバイルアプリを解析する際、特定のコマンドで plist ファイルを直接変換できます:
ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>/Library/Preferences/com.some.package.app.plist
Core Data
Core Data はアプリケーション内のオブジェクトのモデルレイヤーを管理するためのフレームワークです。Core Data can use SQLite as its persistent store、がフレームワーク自体はデータベースではありません。
CoreData はデフォルトでデータを暗号化しません。しかし、追加の暗号化レイヤーを CoreData に追加することができます。詳細は GitHub Repo を参照してください。
アプリケーションの SQLite Core Data 情報はパス /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support にあります
もし SQLite を開いて機密情報にアクセスできる場合、それは設定ミスを見つけたことになります。
-(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");
}
}
YapDatabase
YapDatabase は SQLite の上に構築されたキー/バリュー ストアです。
YapDatabase は sqlite データベースでもあるため、前のセクションで示したコマンドで見つけることができます。
Other SQLite Databases
アプリケーションが独自の sqlite データベースを作成するのは一般的です。これらには 保存している 機密 データ があり、暗号化されずに残されている場合があります。したがって、アプリケーションのディレクトリ内のすべてのデータベースを確認することは常に重要です。データが保存されているアプリケーションのディレクトリ(/private/var/mobile/Containers/Data/Application/{APPID})に移動してください。
find ./ -name "*.sqlite" -or -name "*.db"
Firebase Real-Time Databases
開発者は Firebase Real-Time Databases を通じて、データを保存および同期することができます。データは JSON 形式で保存され、接続されたすべてのクライアントにリアルタイムで同期されます。
Firebase データベースの誤設定を確認する方法は以下を参照してください:
Realm databases
Realm Objective-C and 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にネイティブに対応するよう設計されており、データをシームレスに同期する機能を提供します。
デバイス上の潜在的な Couchbase データベースを特定するには、以下のディレクトリを確認してください:
ls /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/
Cookies
iOSはアプリのCookieを各アプリフォルダ内の**Library/Cookies/cookies.binarycookiesに保存します。ただし、開発者はこれらをkeychainに保存することを選ぶ場合があります。というのも、前述のcookieファイルはバックアップから取得可能である**ためです。
cookieファイルを調査するにはthis python scriptを使うか、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"
}
]
Cache
デフォルトでは NSURLSession は、HTTP requests and responses in the Cache.db のようなデータを Cache.db データベースに保存します。トークン、ユーザー名、またはその他の機密情報がキャッシュされている場合、このデータベースには sensitive data が含まれている可能性があります。キャッシュされた情報を見つけるには、アプリのデータディレクトリ (/var/mobile/Containers/Data/Application/<UUID>) を開き、/Library/Caches/<Bundle Identifier> に移動してください。WebKit cache is also being stored in the Cache.db ファイルにも保存されています。Objection は sqlite connect Cache.db コマンドでデータベースを開いて操作できます。as it is a normal SQLite database.
このデータはリクエストやレスポンスに機密情報を含む可能性があるため、recommended to disable Caching this data。以下にこれを実現するいくつかの方法を示します:
- ログアウト後にキャッシュされたレスポンスを削除することが推奨されます。これは Apple が提供する
removeAllCachedResponsesメソッドで行えます。以下のように呼び出せます:
URLCache.shared.removeAllCachedResponses()
このメソッドは Cache.db ファイルからすべてのキャッシュされたリクエストとレスポンスを削除します。
- cookie の利点を利用する必要がない場合は、URLSession の .ephemeral 設定プロパティを使用することを推奨します。これにより cookies と Caches の保存が無効になります。
An ephemeral session configuration object is similar to a default session configuration (see default), except that the corresponding session object doesn’t store caches, credential stores, or any session-related data to disk. Instead, session-related data is stored in RAM. The only time an ephemeral session writes data to disk is when you tell it to write the contents of a URL to a file.
- Cache は Cache Policy を .notAllowed に設定することでも無効化できます。これによりメモリ上でもディスク上でもいかなる形でも Cache の保存が無効になります。
Snapshots
ホームボタンを押すと、iOS はアプリの切り替えをスムーズに行うために takes a snapshot of the current screen します。しかし、現在の画面に sensitive data が表示されている場合、それらは saved されて image に残ります(これは persists across reboots)。これらのスナップショットは、ホームボタンをダブルタップしてアプリ間を切り替える際にもアクセスできます。
iPhone が jailbroken でない限り、これらのスクリーンショットを見るには attacker が access を持ち、device のロックが unblocked されている必要があります。デフォルトでは、最後のスナップショットはアプリのサンドボックスの Library/Caches/Snapshots/ または Library/SplashBoard/Snapshots フォルダに保存されます(trusted computers は iOX 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:
@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 が常に現在のビューを上書きするため、機密データの leak を防ぎます。
Keychain
iOS keychain へのアクセスと管理には、Keychain-Dumper のようなツールがあり、jailbroken デバイスに適しています。さらに、Objection は同様の目的で ios keychain dump コマンドを提供します。
認証情報の保存
NSURLCredential クラスは、NSUserDefaults や他のラッパーを介さずに、機密情報を直接 keychain に保存するのに最適です。ログイン後に資格情報を保存するには、以下の Swift コードを使用します:
NSURLCredential *credential;
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];
これらの保存された資格情報を抽出するために、Objection のコマンド ios nsurlcredentialstorage dump が使用されます。
カスタムキーボードとキーボードキャッシュ
iOS 8.0 以降、ユーザはカスタムキーボード拡張をインストールでき、これらは Settings > General > Keyboard > Keyboards で管理できます。これらのキーボードは機能を拡張しますが、キー入力のログ取得や外部サーバへのデータ送信のリスクを伴います(ネットワークアクセスを要求するキーボードについてはユーザに通知されます)。アプリは機密情報の入力に対してカスタムキーボードの使用を制限することができ、また制限すべきです。
セキュリティ推奨事項:
- セキュリティ強化のため、サードパーティ製キーボードを無効にすることが推奨されます。
- デフォルトの iOS キーボードの autocorrect や自動候補表示機能は、
Library/Keyboard/{locale}-dynamic-text.datまたは/private/var/mobile/Library/Keyboard/dynamic-text.datに機密情報を保存する可能性があります。これらのキャッシュファイルは定期的に機密データがないか確認するべきです。キャッシュをクリアするには、Settings > General > Reset > Reset Keyboard Dictionary からキーボード辞書をリセットすることが推奨されます。 - ネットワークトラフィックを傍受することで、カスタムキーボードがキー入力をリモートに送信しているかどうかを確認できます。
Preventing Text Field Caching
The UITextInputTraits protocol は autocorrection や secure text entry を管理するプロパティを提供しており、機密情報のキャッシュを防ぐために重要です。例えば、自動補正を無効にし、secure text entry を有効にすることは次のように実行できます:
textObject.autocorrectionType = UITextAutocorrectionTypeNo;
textObject.secureTextEntry = YES;
さらに、開発者はテキストフィールド、特にパスワードやPINなどの機密情報を入力するフィールドが、キャッシュを無効にするために autocorrectionType を UITextAutocorrectionTypeNo に、secureTextEntry を YES に設定していることを確認するべきです。
UITextField *textField = [[UITextField alloc] initWithFrame:frame];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
Logs
デバッグ時にはしばしばloggingが用いられます。リスクとして、logs は機密情報を含む可能性があります。以前は iOS 6 およびそれ以前のバージョンで logs がすべてのアプリから参照可能であったため、機密データの leak のリスクがありました。現在、アプリは自分の logs のみへアクセスするよう制限されています。
これらの制限にもかかわらず、ロック解除されたデバイスに物理的にアクセスできる攻撃者は、デバイスをコンピュータに接続してlogs を読むことでこれを悪用できます。アプリをアンインストールした後でも logs はディスク上に残ることに注意してください。
リスクを軽減するために、アプリと徹底的に操作して、すべての機能や入力を確認し、意図せず機密情報がログに記録されていないかを確認することが推奨されます。
アプリのソースコードをレビューして潜在的な leaks を探す際は、組み込み関数では NSLog、NSAssert、NSCAssert、fprintf のようなキーワードや、カスタム実装における Logging や Logfile の言及など、事前定義されたおよびカスタムのログ記述の両方を探してください。
システム Logs の監視
アプリは機密になり得るさまざまな情報をログに記録します。これらの logs を監視するには、次のようなツールやコマンドを使用します:
idevice_id --list # To find the device ID
idevicesyslog -u <id> (| grep <app>) # To capture the device logs
役立ちます。さらに、Xcode はコンソールログを収集する方法を提供します:
- Xcode を開く。
- iOS デバイスを接続する。
- Window -> Devices and Simulators に移動する。
- デバイスを選択する。
- 調査している問題を再現する。
- Open Console ボタンを使って新しいウィンドウでログを表示する。
より高度なログ取得では、デバイスのシェルに接続して socat を使用することで、リアルタイムのログ監視が可能になります:
iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
続いてログ活動を監視するためのコマンドが示されており、これは問題の診断やログ内の潜在的な data leakage を特定する際に非常に有用です。
バックアップ
Auto-backup features は iOS に組み込まれており、iTunes (up to macOS Catalina)、Finder (from macOS Catalina onward)、または iCloud を通じてデバイスのデータコピーを作成できます。これらのバックアップはほとんどすべてのデバイスデータを含みますが、Apple Pay の詳細や Touch ID の設定などの高度に機密性の高い要素は除外されます。
セキュリティリスク
バックアップに installed apps and their data が含まれることで、潜在的な data leakage の問題や、backup modifications could alter app functionality といったリスクが生じます。これらのリスクを軽減するため、任意のアプリのディレクトリやそのサブディレクトリに機密情報をプレーンテキストで保存しないことが推奨されます。
バックアップからファイルを除外する方法
Documents/ および Library/Application Support/ 内のファイルはデフォルトでバックアップされます。開発者は NSURL setResourceValue:forKey:error: と NSURLIsExcludedFromBackupKey を使用して、特定のファイルやディレクトリをバックアップ対象から除外できます。この手法は機密データがバックアップに含まれるのを防ぐために重要です。
脆弱性のテスト
アプリのバックアップセキュリティを評価するには、まず Finder を使って creating a backup を行い、次に Apple’s official documentation のガイダンスに従ってバックアップを見つけます。バックアップを解析して、アプリの挙動に影響を与えるような機密データや設定の改変が可能かどうかを確認してください。
機密情報はコマンドラインツールや 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>
For dealing with encrypted backups, Python scripts available in DinoSec’s GitHub repo, like backup_tool.py and backup_passwd.py, may be useful, albeit potentially requiring adjustments for compatibility with the latest iTunes/Finder versions. The iOSbackup tool is another option for accessing files within password-protected backups.
Modifying App Behavior
An example of altering app behavior through backup modifications is demonstrated in the Bither bitcoin wallet app, where the UI lock PIN is stored within net.bither.plist under the pin_code key. Removing this key from the plist and restoring the backup removes the PIN requirement, providing unrestricted access.
Summary on Memory Testing for Sensitive Data
アプリのメモリに格納された機密情報を扱う場合、そのデータの露出時間を最小限にすることが重要です。メモリ内容を調査する主なアプローチは二つあります:メモリダンプを作成すること と リアルタイムでメモリを解析すること。どちらの方法にも課題があり、ダンプや解析の過程で重要なデータを見逃す可能性があります。
Retrieving and Analyzing a Memory Dump
For both jailbroken and non-jailbroken devices, tools like objection and Fridump allow for the dumping of an app’s process memory. Once dumped, analyzing this data requires various tools, depending on the nature of the information you’re searching for.
To extract strings from a memory dump, commands such as strings or rabin2 -zz can be used:
# Extracting strings using strings command
$ strings memory > strings.txt
# Extracting strings using rabin2
$ rabin2 -ZZ memory > strings.txt
特定のデータ型やパターンの検索を含む、より詳細な解析には、radare2 は豊富な検索機能を提供します:
$ r2 <name_of_your_dump_file>
[0x00000000]> /?
...
実行時メモリ解析
r2fridaは、memory dumpを作成せずに、アプリのメモリをリアルタイムで検査するための強力な代替手段を提供します。このツールは、実行中のアプリケーションのメモリ上で直接検索コマンドを実行できるようにします:
$ r2 frida://usb//<name_of_your_app>
[0x00000000]> /\ <search_command>
破綻した暗号化
不適切な鍵管理プロセス
一部の開発者は機密データをローカルストレージに保存し、コード内にハードコーディング/予測可能な鍵で暗号化します。これは避けるべきで、リバースエンジニアリングにより攻撃者が機密情報を抽出できる可能性があります。
安全でない、または廃止されたアルゴリズムの使用
開発者は承認のチェックやデータの保存・送信に廃止されたアルゴリズムを使用すべきではありません。これらのアルゴリズムには RC4、MD4、MD5、SHA1 などがあります。例えばパスワードの保存にハッシュを使用する場合、ソルトを付けたブルートフォースに耐性のあるハッシュを使用するべきです。
チェック
主なチェック項目は、コード内にハードコーディングされたパスワード/シークレットがないか、またそれらが予測可能でないか、コードが何らかの弱い****暗号アルゴリズムを使用していないかを確認することです。
いくつかの暗号****ライブラリを自動的に監視するために、objectionを使うことができる点は覚えておくと便利です:
ios monitor crypt
For more information about iOS cryptographic APIs and libraries access https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography
Local Authentication
Local authentication は重要な役割を果たします。特に暗号化手法を用いてリモートエンドポイントへのアクセスを保護する場合に重要です。ここでの本質は、適切に実装されていないと Local authentication の仕組みが回避される可能性がある、という点です。
Apple の Local Authentication framework と keychain は、それぞれユーザー認証ダイアログの提供とシークレットデータの安全な取り扱いのための堅牢な API を開発者に提供します。Secure Enclave は Touch ID の指紋 ID を保護し、Face ID は生体データを漏えいさせることなく顔認識に依存します。
Touch ID / Face ID を統合するために、開発者は次の2つの API のいずれかを選択できます:
LocalAuthentication.framework: 生体認証データへのアクセスなしでハイレベルなユーザー認証を提供します。Security.framework: より低レベルの keychain サービスへのアクセス用で、シークレットデータを生体認証で保護します。様々な open-source wrappers が keychain へのアクセスを簡素化します。
Caution
However, both
LocalAuthentication.frameworkandSecurity.frameworkpresent vulnerabilities, as they primarily return boolean values without transmitting data for authentication processes, making them susceptible to bypassing (refer to Don’t touch me that way, by David Lindner et al).
Implementing Local Authentication
ユーザーに認証を促すには、開発者は LAContext クラスの evaluatePolicy メソッドを使用し、次のいずれかを選択します:
deviceOwnerAuthentication: Touch ID またはデバイスのパスコードを要求し、どちらも有効でない場合は失敗します。deviceOwnerAuthenticationWithBiometrics: Touch ID のみを要求します。
認証の成功は evaluatePolicy のブール返り値で示され、これは潜在的なセキュリティ上の欠陥を示唆します。
Local Authentication using Keychain
iOS アプリで local authentication を実装するには、認証トークンなどのシークレットデータを安全に保存するために keychain APIs を使用します。このプロセスにより、デバイスのパスコードや Touch ID のような生体認証を用いて、データがユーザーのみアクセス可能であることが保証されます。
keychain は SecAccessControl 属性でアイテムを設定する機能を提供しており、ユーザーが Touch ID またはデバイスのパスコードで正常に認証されるまでそのアイテムへのアクセスを制限します。この機能はセキュリティ強化において重要です。
以下に、これらのセキュリティ機能を活用して文字列を keychain に保存および取得する方法を示す Swift と Objective-C のコード例を示します。これらの例は、Touch ID 認証を必須とするアクセス制御の設定方法と、デバイスにパスコードが設定されている場合にのみデータが設定されたデバイスでアクセス可能であることを確保する手順を具体的に示しています。
// From https://github.com/mufambisi/owasp-mstg/blob/master/Document/0x06f-Testing-Local-Authentication.md
// 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
}
これで Keychain から保存したアイテムを要求できます。Keychain サービスはユーザーに認証ダイアログを表示し、適切な指紋が提供されたかどうかに応じて data または nil を返します。
// 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
}
検出
アプリ内で使用されているフレームワークは、アプリのバイナリにリンクされている共有動的ライブラリの一覧を解析することで検出できます。これは otool を使用して行えます:
$ otool -L <AppName>.app/<AppName>
アプリでLocalAuthentication.frameworkが使用されている場合、出力には以下の両方の行が含まれます(LocalAuthentication.frameworkは内部でSecurity.frameworkを使用していることを覚えていてください):
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
/System/Library/Frameworks/Security.framework/Security
もしSecurity.frameworkが使用されている場合、二番目のものだけが表示されます。
Local Authentication Framework Bypass
Objection
Objection Biometrics Bypassはthis GitHub pageにあり、LocalAuthenticationメカニズムを回避するための手法が提供されています。
この手法の中核はFridaを利用してevaluatePolicy関数を操作し、実際の認証の成功に関係なく常にTrueを返すようにすることです。これは、欠陥のある生体認証プロセスを回避するのに特に有用です。
このバイパスを有効にするには、次のコマンドを使用します:
...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
このコマンドは、Objection がタスクを登録し、evaluatePolicy チェックの結果を実質的に True に変更する一連の動作を開始します。
Frida
以下は DVIA-v2 application における 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"];
});
}
}
Local Authentication の bypass を達成するため、Frida script が作成されます。
このスクリプトは evaluatePolicy チェックを狙い、そのコールバックをインターセプトして success=1 を返すようにします。
コールバックの挙動を変更することで、認証チェックは実質的に bypass されます。
以下のスクリプトは evaluatePolicy メソッドの結果を変更するためにインジェクトされます。コールバックの結果を常に成功を示すように変更します。
// 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スクリプトを注入して生体認証をバイパスするには、次のコマンドを使用します:
frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js
IPCを介した機密機能の露出
Custom URI Handlers / Deeplinks / Custom Schemes
iOS Custom URI Handlers / Deeplinks / Custom Schemes
Universal Links
UIActivity Sharing
UIPasteboard
App Extensions
WebViews
Serialisation and Encoding
iOS Serialisation and Encoding
ネットワーク通信
通信が暗号化されていない状態で行われていないこと、またアプリケーションがサーバーのTLS certificateを正しく検証していることを確認することが重要です。
この種の問題をチェックするには、Burpのようなプロキシを使用できます:
ホスト名チェック
TLS certificateを検証する際の一般的な問題の一つは、証明書が信頼された CAによって署名されているかを確認するが、証明書のホスト名がアクセスしているホスト名と一致するかを確認しないことです。
この問題をBurpで検証するには、iPhoneでBurp CAを信頼した後、別のホスト名用にBurpで新しい証明書を作成して使用することができます。アプリケーションが依然として動作する場合、そのアプリは脆弱です。
Certificate Pinning
アプリが正しくSSL Pinningを使用している場合、証明書が期待されるものでなければアプリは動作しません。テスト時には、Burpが自身の証明書を返すため問題になる可能性があります。
jailbrokenデバイス内でこの保護を回避するには、アプリケーションSSL Kill Switchをインストールするか、Burp Mobile Assistantをインストールできます。
また、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によって悪用される危険な仕組みであるため、自動更新に使用されているメソッド(ある場合)を確認し、テストすることを推奨します。 その目的のためにアプリの過去バージョンをダウンロードして試すことができます。
サードパーティ
3rd party SDKs に伴う大きな課題は、その機能に対する細かい制御の欠如です。開発者はSDKを統合してそのすべての機能(潜在的なセキュリティ脆弱性やプライバシーの懸念を含む)を受け入れるか、あるいはその利点をまったく放棄するかの選択を迫られます。多くの場合、開発者自身がこれらのSDK内の脆弱性を修正できません。さらに、SDKがコミュニティ内で信頼を獲得すると、中にはマルウェアを含むものも出てきます。
サードパーティSDKが提供するサービスには、ユーザー行動のトラッキング、広告表示、ユーザー体験の向上などが含まれることがあります。しかしこれは、開発者がこれらのライブラリによって実行されるコードを完全に把握していない可能性を生み、プライバシーおよびセキュリティ上のリスクにつながります。サードパーティサービスに共有する情報は必要最小限に限定し、機密データが露出しないようにすることが重要です。
サードパーティサービスの実装は通常、スタンドアロンのライブラリかフルSDKのいずれかの形式で行われます。ユーザーのプライバシーを保護するため、これらのサービスと共有するデータは個人識別情報(PII)の開示を防ぐために匿名化されるべきです。
アプリが使用しているライブラリを特定するには、otool コマンドを使用できます。このツールはアプリケーション本体と、そのアプリが使用する各共有ライブラリに対して実行し、追加のライブラリを発見します。
otool -L <application_path>
興味深い脆弱性とケーススタディ
Air Keyboard Remote Input Injection
Itunesstored Bookassetd Sandbox Escape
Zero Click Messaging Image Parser Chains
参考資料と追加リソース
- https://blog.calif.io/p/taking-apart-ios-apps-anti-debugging
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering
- iOS & Mobile App Pentesting - INE
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0057/
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0058/
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0059/
- https://mas.owasp.org/MASTG/iOS/0x06d-Testing-Data-Storage
- https://coderwall.com/p/kjb3lw/storing-password-in-keychain-the-smart-way
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0055/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0053
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0060/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0058
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0060
- https://mas.owasp.org/MASTG/Android/0x05f-Testing-Local-Authentication/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-AUTH/MASTG-TEST-0064
- https://medium.com/securing/bypassing-your-apps-biometric-checks-on-ios-c2555c81a2dc
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0054
- 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
Tip
AWSハッキングを学び、実践する:
HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。


