1

AFNetworking を使用して SSL 経由でデータを送信しています。中間者攻撃を防ぐにはどうすればよいですか? 他のサーバーではなく、自分のサーバーにデータを送受信していることを確認するにはどうすればよいですか?

これが私のコードです:

    @implementation API

@synthesize user;

#pragma mark - Singleton methods
/**
 * Singleton methods
 */
+(API*)sharedInstance
{
    static API *sharedInstance = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        sharedInstance = [[self alloc] initWithBaseURL:[NSURL URLWithString:kAPIHost]];
    });

    return sharedInstance;
}

#pragma mark - init
//intialize the API class with the destination host name

-(API*)init
{
    //call super init
    self = [super init];

    if (self != nil) {
        //initialize the object
        user = nil;

        [self registerHTTPOperationClass:[AFJSONRequestOperation class]];

        [self setDefaultHeader:@"Accept" value:@"application/json"];
    }

    return self;
}

-(BOOL)isAuthorized
{
    return [[user objectForKey:@"id"] intValue]>0;
}



-(void)commandWithParams:(NSMutableDictionary*)params
                    path: (NSString *) pathstr
            onCompletion:(JSONResponseBlock)completionBlock
{
    NSMutableURLRequest *apiRequest =
    [self multipartFormRequestWithMethod:@"POST"
                                    path: pathstr
                              parameters: params
               constructingBodyWithBlock: ^(id <AFMultipartFormData>formData)
               {
                   //TODO: attach file if needed
               }];

    AFJSONRequestOperation* operation = [[AFJSONRequestOperation alloc] initWithRequest: apiRequest];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        //success!
        completionBlock(responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        //failure :(

        NSLog(@"%@", error);
        completionBlock([NSDictionary dictionaryWithObject:[error localizedDescription] forKey:@"error"]);
    }];

    [operation start];

}
@end

そして、私は呼び出します:

[[API sharedInstance] commandWithParams: params
                                   path: @"user/registration"
                           onCompletion:^(NSDictionary *json)
 {
4

2 に答える 2

6

9か月遅れていることはわかっていますが、この質問に対する独自の解決策を調査しているときに、このSOの質問に出くわしました。他の人もそれに遭遇した場合に備えて、ここに私が理解している考慮事項/アプローチがあります。

  1. 上記のアプローチを使用すると、MITM 攻撃を受けやすくなります。上記のアプローチでは、接続に SSL を使用し、証明書が有効であることを確認します。ただし、証明書がサーバー用であるかどうかはチェックされません。したがって、上記のアプローチにより、有効な証明書を有効なものとして受け入れることができます。そのため、Charles ( http://www.charlesproxy.com ) のようなプログラムを使用すると、アプリとサーバーの間でプロキシとして機能できる場合、https ネットワーク トラフィックを (または誰でも) 見ることができます。

  2. これを防ぐには、SSL ピニングをオンにする必要があります (良い記事はこちら: http://blog.lumberlabs.com/2012/04/why-app-developers-should-care-about.html )。これが行うことは、特定の証明書 (アプリに埋め込む) または特定の公開鍵 (アプリにも埋め込む) を持つサーバーからの SSL 接続を要求することです。

  3. 幸いなことに、AFNetworking を使用すると、これを非常に簡単に行うことができます。簡単に設定

    defaultSSLPinningMode = AFSSLPinningModeCertificate
    

    また

    defaultSSLPinningMode = AFSSLPinningModePublicKey
    

    AFHTTPClient で。次に、関連する証明書または公開鍵をアプリのバンドルに追加します。

  4. 上記のアプローチでは、誰かがアプリをダウンロードし、独自の証明書または公開鍵をアプリのバンドルに挿入して、アプリを再署名する可能性がまだあります。これを行うための正確な手順はわかりませんが、問題の概要はhttps://github.com/AFNetworking/AFNetworking/issues/1286にあります。

  5. 私の考えでは、これを防ぐ最善の方法は、SSL ピニングを使用する上でアプリとサーバー間の通信を暗号化することです。私は現在、これについて RNCryptor を検討しています ( https://github.com/rnapier/RNCryptor )

最終的には、アプリが何をしていて、データが共有されているかを考えると、適切なレベルの作業が必要になると思います。

役に立てば幸いです、チャールズ。

于 2013-11-02T10:46:45.057 に答える
0

kAPIHostがURL であると仮定すると、https://すべて問題ないはずです。

実際にできることは、サーバーが信頼できる機関の証明書を持っている既知の適切なサーバー アドレスに接続することだけです。(Thawte、VeriSign などによって提供されます。) 「郵便配達員が私のメールをリダイレクトしていないことをどのように確認できますか?」と言っているようなものです。できませんが、できることは、暗号化 (つまり、暗号化証明書、SSL など) を使用して、郵便配達員がメールの内容を読み取らないようにし、その後、応答が本当に期待するエンティティからのものであることを認証することです。これは、SSL が行うことです (信頼できる証明書が存在する場合など)。

主流の証明書提供エンティティを信頼しない場合は、秘密を事前に共有し、共有秘密ベースの暗号化を使用することになります。要するに、SSL は他のほとんどすべての人にとって十分に優れています。うまくいけば、それで十分です。

于 2013-01-05T21:02:38.077 に答える