首页
社区
课程
招聘
[转帖]通信安全:IOS客户端证书校验方法
发表于: 2017-11-29 09:40 6124

[转帖]通信安全:IOS客户端证书校验方法

2017-11-29 09:40
6124

随着移动互联网的发展,互联网应用也在与日俱增,传统的金融行业,如银行的手机银行业务,现在热门的互联网金融企业,其移动应用都在不断的更新,同时,移动客户端的安全性也受到了前所未有的威胁,如盗版app,SQL注入,任意用户密码重置等漏洞,但这些漏洞的进一步利用很多情况下都依赖于中间人攻击,也就是客户端与服务端进行通信时未采用安全的https方式进行通信,而是采用不安全的http方式进行通信。本文就https基于SSL安全传输中相关问题进行了探索研究,以便在以后的客户端安全测试当中有一定的帮助。

由于移动互联网发展起始时间比较晚,开发人员也是近几年才发展起来,所以对于技术的水平也参差不齐。很多开发人员在开发初期都进行了比较安全的设计,但是在实现的时候没有很好的发挥其功能,特别是威胁比较大的SSL证书校验。有报道称,在2013年抽样对国内的手机银行客户端进行了SSL证书的安全测试,发现90%的客户端都没有很好的发挥了SSL证书校验的功能。

本文就当前IOS客户端SSL证书校验存在的问题做了阐述和分析,以帮助安全工程服务人员更好的测试ssl证书的安全性。


说到HTTPS通信,首先要说明一下HTTPS的通信原理。HTTPS是基于安全目的的Http通道,其安全基础由SSL层来保证。最初由netscape公司研发,主要提供了通讯双方的身份认证和加密通信方法。现在广泛应用于互联网上安全敏感通讯。

下面为IOS移动客户端其通信过程和证书校验过程可以用如下图过程展示:

第1步:IOS客户端发送一个连接请求给服务器;服务器将自己的证书(包含服务器公钥S_PuKey)、对称加密算法种类及其他相关信息返回客户端。

第2步:客户端检查服务器传送到CA证书是否由自己信赖的CA中心签发。若是,执行4步;否则,给客户提示连接错误或者拒绝连接。

第3步:客户端比较证书里的信息,如证书有效期、服务器域名和公钥S_PK,与服务器传回的信息是否一致,如果一致,则浏览器完成对服务器的身份认证。

第4步:服务器要求客户端发送客户端证书(包含客户端公钥C_PuKey)、支持的对称加密方案及其他相关信息。收到后,服务器进行相同的身份认证,若没有通过验证,则拒绝连接;

第5步:服务器根据客户端发送到密码种类,选择一种加密程度最高的方案,用客户端公钥C_PuKey加密后通知到客户端。

第6步:客户端通过私钥C_PrKey解密后,得知服务器选择的加密方案,并选择一个通话密钥key,接着用服务器公钥S_PuKey加密后发送给服务器;

第7步:服务器接收到客户端传送到消息,用私钥S_PrKey解密,获得通话密钥key。

第8步:接下来的数据传输都使用该对称密钥key进行加密。

由上述过程可以看到,要达到ssl安全通信,服务端和客户端都必有含有有效公私钥证书。

针对当前的市面上的IOS客户端,大多数客户端都采用http的方式进行通信。http通信方式是一种不安全的应用层通信方式,极易遭到中间人攻击。目前市面上的移动app主要有http方式和https方式进行通信,这里不再讨论http通信的优缺点,只讨论https通信方式上遇到的问题和安全加固建议。

缺陷描述:

无ssl证书校验是指虽然客户端与服务端的通信采用https加密通讯,但对ssl证书信任无任何校验,SSL证书形同虚设,无论服务器提供哪一种SSL证书指纹信息,客户端与服务端都可以正常通信,目前市场上80%的APP都没有很好的发挥SSL证书校验功能,甚至很大一部分APP都直接采用没有任何安全校验的http方式,这种客户端很明显的缺陷就是可以对app进行中间人攻击。

缺陷分析:

无证书校验最简单的黑河测试方式是对IOS设备做代理测试(IOS此时未越狱/不进行任何安装证书操作),当我们能抓取到https通信内容时,则证明此app与服务端间的通信未对ssl证书进行校验或者此app直接走http协议进行通信,如下图所示:

查看客户端代码,发现对ssl证书的校验没有开启:

//*配置服务端是否为SSL

#if defined (MODEL_RELEASE)

#define SERVER_SSL YES

#elif defined (MODEL_QUASIPRODUCTION)

#define SERVER_SSL YES

#else

#define SERVER_SSL NO

#endif

//#define SERVER_CHECKSSL YES//校验ssl证书

#define SERVER_CHECKSSL NO //不校验ssl证书

//省略部分代码

NSMutableString *urlString = [NSMutableString stringWithFormat:@”%@://%@”, useSSL ? @”https” : @”http”, self.hostName];

if(self.portNumber != 0)

[urlString appendFormat:@”:%d”, self.portNumber];

if(self.apiPath)

[urlString appendFormat:@”/%@”, self.apiPath];

if(![path isEqualToString:@”/”]) { // fetch for root?

if(path.length > 0 && [path characterAtIndex:0] == ‘/’) // if user passes /, don’t prefix a slash

[urlString appendFormat:@”%@”, path];

else if (path != nil)

[urlString appendFormat:@”/%@”, path];

}

return [self operationWithURLString:urlString params:body httpMethod:method];

}

//省略部分代码

NSMutableDictionary *webInfo = [[NSMutableDictionary alloc]initWithObjectsAndKeys:

[NSString stringWithFormat:@”%ld”,(long)completedOperation.HTTPStatusCode],@”httpStatus”,

completedOperation.responseString,@”WebData”,

nil];

onSuccessBlock([completedOp

以上代码可以说明客户端并没有对ssl证书做信任校验。

安全改进:

根据OWASP官方给出的对于IOS客户端,可以通过以下代码实现SSL证书信任操作:

{

[m_fetchedLabel setText:@””];

NSString* requestString = @”https://www.random.org/integers/?

num=16&min=0&max=255&col=16&base=16&format=plain&rnd=new”;

NSURL* requestUrl = [NSURL URLWithString:requestString];

ASSERT(nil!= requestUrl);

if(!(nil!= requestUrl))

{

[self displayError:@”Failed to create requestString.”];

return;

}

NSURLRequest* request = [NSURLRequest requestWithURL:requestUrl

cachePolicy:NSURLRequestReloadIgnoringLocalCacheData

timeoutInterval:10.0f];

ASSERT(nil!= request);

if(!(nil!= request))

{

[self displayError:@”Failed to create request.”];

return;

}

// Note that the delegate for the NSURLConnection is self, so delegate methods must be defined in this

file

NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

ASSERT(nil!= connection);

if(!(nil!= connection))

{

[self displayError:@”Failed to create connection.”];

return;

}

self.m_fetchedData = [[NSMutableString string] retain];

ASSERT(nil!= m_fetchedData);

}

-(BOOL)connection:(NSURLConnection*)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace

*)space

{

return [[space authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust];

}

– (void)connection:(NSURLConnection*)connection didReceiveAuthenticationChallenge:

(NSURLAuthenticationChallenge*)challenge

{

if ([[[challenge protectionSpace] authenticationMethod] isEqualToString:

NSURLAuthenticationMethodServerTrust])

{

do

{

SecTrustRef serverTrust= [[challenge protectionSpace] serverTrust];

ASSERT(nil!= serverTrust);

if(!(nil!= serverTrust)) break; /* failed */

OSStatus status= SecTrustEvaluate(serverTrust, NULL);

ASSERT(errSecSuccess== status);

if(!(errSecSuccess== status)) break; /* failed */

SecCertificateRef serverCertificate= SecTrustGetCertificateAtIndex(serverTrust, 0);

ASSERT(nil!= serverTrust);

if(!(nil!= serverTrust)) break; /* failed */

CFDataRef serverCertificateData= SecCertificateCopyData(serverCertificate);

ASSERT(nil!= serverCertificateData);

if(!(nil!= serverCertificateData)) break; /* failed */

[(id)serverCertificateData autorelease];

const UInt8* const data= CFDataGetBytePtr(serverCertificateData);


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2020-2-4 22:14 被kanxue编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//