我正在使用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)
{
答案 0 :(得分:6)
我知道已经晚了9个月,但在研究我自己的解决方案时,我遇到了这个问题。如果其他人也遇到过这种情况,这就是我所理解的考虑/方法。
使用您在上面列出的方法可以让您对MITM攻击持开放态度。上面的方法是使用SSL进行连接并检查证书是否有效。但是,它不会检查证书是否适用于您的服务器。因此,上述方法将允许任何有效证书被接受为有效。因此,像Charles(http://www.charlesproxy.com)这样的程序可以让您(或任何人)看到您的https网络流量,只要他们能够充当您的应用和服务器之间的代理。
为了防止这种情况发生,您需要打开SSL Pinning(这里的好文章:http://blog.lumberlabs.com/2012/04/why-app-developers-should-care-about.html)。这样做需要SSL连接来自具有特定证书(您嵌入在应用程序中)的服务器或具有特定公钥(您也嵌入应用程序中)。
幸运的是,使用AFNetworking这很容易做到。只需设置
defaultSSLPinningMode = AFSSLPinningModeCertificate
或
defaultSSLPinningMode = AFSSLPinningModePublicKey
通过上述方法,仍有可能有人下载应用程序并在应用程序包中插入自己的证书或公钥并重新签名应用程序。我不知道执行此操作的确切步骤,但此处列出了问题:https://github.com/AFNetworking/AFNetworking/issues/1286。
在我看来,防止这种情况的最佳方法是在使用SSL Pinning的基础上加密应用程序和服务器之间的通信。我目前正在寻找RNCryptor(https://github.com/rnapier/RNCryptor)
我想最终归结为应用程序正在做什么以及数据共享的适当级别的工作量。
希望有帮助,查尔斯。
答案 1 :(得分:0)
假设kAPIHost
是https://
网址,那么您应该都很好。
实际上,您所能做的就是建立与服务器具有可信授权证书的已知良好服务器地址的连接。 (由Thawte,VeriSign等提供)这有点像说“我怎么能确定邮递员没有重定向我的邮件?”您不能,但您可以做的是使用加密(即加密证书,SSL等)来阻止邮递员阅读您的邮件内容,然后将回复验证为真正来自您期望的实体。这就是SSL存在的事情(存在可信证书等)
如果您不信任主流证书提供实体,那么您几乎可以预先共享秘密并使用基于共享密码的加密。简而言之,SSL对于其他所有人来说已经足够好了......希望它对你来说已经足够了。