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 Pinning(这里的好文章: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 Pinning 的基础上加密应用程序和服务器之间的通信。我目前正在为此寻找 RNCryptor ( https://github.com/rnapier/RNCryptor )

我想最终归结为考虑到您的应用程序正在做什么以及它正在共享的数据,适当的工作量是多少。

希望有帮助,查尔斯。

于 2013-11-02T10:46:45.057 回答
0

假设kAPIHost是一个https://URL,你应该一切都好。

实际上,您所能做的就是与服务器具有受信任的权威证书的已知良好服务器地址建立连接。(由 Thawte、VeriSign 等提供。)这有点像在说“我怎么能确定邮递员没有重定向我的邮件?” 您不能,但您可以做的是使用密码学(即密码证书、SSL 等)来防止邮递员读取您的邮件内容,并随后将响应验证为真正来自您期望的实体。这就是 SSL 存在的目的(在存在可信证书等的情况下)

如果您不信任提供主流证书的实体,那么您几乎只能预先共享一个秘密并使用基于共享秘密的加密。简而言之,SSL 对几乎所有其他人来说已经足够好了……希望它对你来说已经足够好了。

于 2013-01-05T21:02:38.077 回答