Parseは、モバイルアプリケーション用の本格的なサーバーインフラストラクチャを迅速に構築できる最も美しいBaaSです。 おそらく、多くの開発者がこの新たなセキュリティの問題と新たな脆弱性を忘れているのは、この単純さのためです。
サービスに精通していない人のために、私たちはそれが何であるかについて短いエクスカーションを取ります。 Parseは、クラウドストレージ、プッシュ通知、独自のAPIの作成、統計の収集、クラッシュログなどのサービスを開発者に提供します。 この調査の一環として、Cloud Coreと呼ばれるデータウェアハウスに興味があります。
Parseのすべてのデータは、完全な関係を確立できるレコード間で、クラス(基本的にはテーブル)に格納されます。
クラスごとに、検索、新しいエントリの追加、既存のエントリの変更などの機能に影響するクライアントアクセス権が構成されます。 デフォルトでは、すべてのアクションが許可されています。 もちろん、いつものように、ほとんどの開発者は、必要なテーブルを設定すると、クライアントのアクセス許可の設定を忘れます。
作業中のプロジェクトの1つでParseと密接に遭遇し、ACL設定をいじくり回したため、他の人のアプリケーションで遊ぶことにしました。 parse.com/customersで直接調査するオブジェクトを選択しました 。 Cubefree-コワーキングの場所を見つけるサービスになりました 。
iOSアプリケーションのParseアカウントに接続するために、2つのキー( アプリケーションIDとクライアントキー)が使用されます。 Cloud Coreのデータに対してアクションを実行するには、まずそのデータを見つける必要があります。 ペンテスト中の多くのルーチンアクションを自動化するスマートIDBユーティリティを使用して、アプリケーションの実行可能ファイルを解読します。 プロセスの進行中に、 NSUserDefaultsを確認します。NSUserDefaultsは、関心のあるキーを格納する可能性が高い場所です。
この場合、すべては完全に無害です-機密データはありません。 復号化されたバイナリに戻り、Objective-Cで記述されたリバースエンジニアリングアプリケーションに特化したHopper逆アセンブラーにフィードします。 AppDelegateのアプリケーションdidFinishLaunchingWithOptions:メソッドでキーの検索を開始します。 Hopperの優れた機能の1つは、メソッドを擬似コードとして提示することです。これにより、解読されたコードを理解するためのしきい値が大幅に低下します。
予想どおり、Parseアカウントへの接続はここで発生します。 これらのキーを使用して、アプリケーションのデータ構造とそれらへのアクセス権を分析します。
次のステップは、Parseテーブルの名前を検索することです。 実際、それらを探す場所は同じスクリーンショットから明らかになります-サーバーに接続した直後に、ルートPFObjectのいくつかの継承クラスでregisterSubclassメソッドを呼び出します。 それらのそれぞれは、 parseClassNameメソッドを必ず実装する必要があります。このメソッドは、対象のサーバー上のテーブルの名前を返します 。
このようにして得られた各クラスの構造を研究します。
PFQuery *query = [PFQuery queryWithClassName:@"ParseClassName"]; [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { NSLog(@"%@", objects); }];
ただし、構造に関する知識だけでは十分ではありません。 アプリケーションの動作にどのように影響するかを理解するには、すべてのParseクラスへのアクセス権を定義する必要があります。 これは非常に簡単に行われます-異なる許可に対応するサーバーへのリクエストを実行し、その結果を分析するだけです。 これらのルーチンアクションを簡素化するために、既知のすべてのクラスへのアクセスレベルを自動的に決定するParse Revealerという簡単なユーティリティを作成しました。
受け取ったデータに基づいて、テーブルを作成できます。
クラス名 | データ構造 | アクセス権 |
---|---|---|
チャットルーム | chatId(文字列)
user1(ユーザー) user2(ユーザー) | GET:False
見つける:True 更新:True 作成:True 削除:偽 フィールドの追加:True |
チェックイン | availableToShareTable(ブール値)
日付(Date) 見えない(bool) statusCheckin(文字列) statusUser(文字列) ユーザー(ユーザー) ワークスペース(ワークスペース) | GET:True
見つける:True 更新:True 作成:True 削除:True フィールドの追加:True |
チャットメッセージ | chatId(文字列)
メッセージ(文字列) 送信者(ユーザー) 未読(bool) | GET:False
見つける:True 更新:True 作成:True 削除:偽 フィールドの追加:True |
通告 | 日付(Date)
sendUser(ユーザー) チェキン ステータス(ブール) タイプ(数値) 受け入れられた(Bool) | GET:True
見つける:True 更新:True 作成:True 削除:偽 フィールドの追加:True |
復習 | 日付(Date)
parkingStatus(番号) powerStatus(数値) soundStatus(数値) ユーザー(PFUser) wifiStatus(数値) ワークスペース(ワークスペース) | GET:True
見つける:True 更新:偽 作成:True 削除:偽 フィールドの追加:True |
ワークスペース | アドレス(文字列)
cc(文字列) 都市(ストリング) 国(文字列) foursquareId(文字列) lat(文字列) lng(文字列) ロケーション(PFGeoPoint) 名前(文字列) postalCode(文字列) 状態(文字列) | GET:True
見つける:True 更新:True 作成:True 削除:偽 フィールドの追加:True |
取得したアクセス権からわかるように、開発者は特定のセキュリティポリシーを実装しましたが、それでも不十分です。 ChatMessageクラスで遊ぶことでどのような結果が得られるかを示します。
最も明らかな脆弱性-オープンチャットのいずれでも、自分のメッセージと他のメッセージの両方を変更できます。 このコードを実行すると、素敵な挨拶が殺人事件に変わります。
PFQuery *query = [PFQuery queryWithClassName:@"ChatMessage"]; [query whereKey:@"message" equalTo:@", !"]; [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { PFObject *object = [objects firstObject]; object[@"message"] = @", !"; [object saveInBackground]; }];
同様に、新しいPFObjectに正しいchatId を提供するだけで、新しいメッセージを追加できます。 ただし、 falseに設定されたDeleteでは、作成されたオブジェクトを削除できないことに注意してください。
さらに深刻な脆弱性は、Parseから受信したデータのマッピングが正しくないことです。 新しく作成されたChatMessageオブジェクトに送信者フィールドがない場合、アプリケーションはクラッシュします。 したがって、これまでに作成されたすべてのウォッチを実行し、それらに無効なメッセージを追加することを妨げるものはありません。アプリケーションはすべてのユーザーからクラッシュします。 これにはすでに、App Storeでの低い評価、ユーザーの流出、およびプロジェクト全体の失敗に悩まされています。
残りのクラスには同様の脆弱性がありますが、すでに現在の調査の範囲外です。
セキュリティに関しては、ここではすべてが非常に透明です。 従う必要があるのはいくつかのルールのみです。
- 作成されたすべてのクラスのアクセスレベルを常に構成します。
- ユーザーが作成したデータについては、ACLを使用して、特定の人々のサークルにのみ変更できるようにします。
- クライアントがプロパティの1つだけを変更する必要がある場合(未読フラグなど)-別のテーブルで選択することを検討する価値があります。 したがって、オブジェクトの他のパラメーターを変更する可能性をバイパスすることが可能になります。
- Parseが常に有効なデータを提供するという事実に依存しないでください。適切なチェックを組み込むことを忘れないでください。
- 理論的には、攻撃者はapplicationIdとclientKeyにアクセスできることを忘れずに、この知識に基づいてセキュリティポリシーを検討してください。
- 前のルールは、コード内の行を難読化することを完全に忘れる必要があるという意味ではありません:)
- 特に難しい場合は、クラウドコードを自由に使用してください。
この調査で機能とアプリケーションが表示される場合は、Parseをscらないでください。前述のように、これはアプリケーションのサーバー側の作成コストを最小限に抑える優れたサービスです。 また、考慮されるすべての脆弱性は、アプリケーション開発者の責任のみです。
便利なリンク:
iOSアプリのその他のセキュリティコンテンツ: