使用 AFNetworking 防止中间人攻击
Posted
技术标签:
【中文标题】使用 AFNetworking 防止中间人攻击【英文标题】:Prevent Man in the Middle attack with AFNetworking 【发布时间】:2013-01-05 20:45:33 【问题描述】:我正在使用 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)
【问题讨论】:
你无法真正阻止攻击的人。但是,您可以阻止攻击本身。 如果您使用 SSL 和由受信任的机构签署的证书,那么,AFAIK,这几乎可以防止中间人附加。看看en.wikipedia.org/wiki/… 【参考方案1】:我知道这已经晚了 9 个月,但我在研究我自己的解决方案时遇到了这个 SO 问题。以防其他人也遇到它,这就是我理解的注意事项/方法。
使用上述方法会使您容易受到 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
在您的 AFHTTPClient 上。然后将相关证书或公钥添加到您的应用程序包中。
使用上述方法,仍然有可能有人下载应用程序并将他们自己的证书或公钥插入应用程序的捆绑包中并退出应用程序。我不知道执行此操作的确切步骤,但此处概述了问题:https://github.com/AFNetworking/AFNetworking/issues/1286。
在我看来,防止这种情况发生的最好方法是在使用 SSL Pinning 的基础上加密应用程序和服务器之间的通信。我目前正在为此寻找 RNCryptor (https://github.com/rnapier/RNCryptor)
我想最终归结为考虑到您的应用正在做什么以及它正在共享的数据,适当的工作量是多少。
希望对您有所帮助,查尔斯。
【讨论】:
您最终是如何实施第 5 步的?分别加密您通过 AFHTTPClient 传递的参数字典中的每个参数? @powerj1984 我最终使用了 RNCryptor,然后实际上实现了两种不同的方式来为我的 API 发送/接收数据。我可以单独发送/接收所有参数(发送大约 6 个参数)。我还可以发送一组串联的参数。这样做的原因是我发现旧 android 手机上的 RNCryptor 算法需要一段时间才能运行(几秒钟),所以连接方法不是运行 6 次,而是运行一次。【参考方案2】:假设kAPIHost
是一个https://
URL,你应该一切都好。
真的,您所能做的就是连接到服务器具有受信任的权威证书的已知良好服务器地址。 (由 Thawte、VeriSign 等提供。)这有点像说“我怎么能确定邮递员没有重定向我的邮件?”您不能,但您可以做的是使用密码学(即密码证书、SSL 等)来防止邮递员读取您的邮件内容,然后验证响应是否真正来自您期望的实体。这就是 SSL 存在的目的(在存在受信任的证书等情况下)
如果您不信任提供主流证书的实体,那么您几乎只能预先共享密钥并使用基于共享密钥的加密。简而言之,SSL 对几乎所有其他人来说都足够好......希望它对你来说已经足够好了。
【讨论】:
以上是关于使用 AFNetworking 防止中间人攻击的主要内容,如果未能解决你的问题,请参考以下文章
如何防止 PHP、csrf、xsrf 中的表单重放/中间人攻击