通过看一些文档发现越狱有风险,但是风险还是在可控范围内的,所以touchid用于交易还是可行的。
一越狱存在的问题
理论上iPhone越狱没有安全性可言,所有安装在你手机的APP都以root权限运行,它们可以
•任意读写文件系统数据
•HTTP(S)实时被监测
•重新打包ipa
•暴露的函数符号
•未加密的静态字符
•篡改程序逻辑控制流
•拦截系统框架API
•逆向加密逻辑
•跟踪函数调用过程(objc_msgSend)
•可见视图的具体实现
•伪造设备标识
•可用的URL schemes
runtime任意方法调用
以上安全风险都基于一个前提:安装了一个恶意APP或插件。所以只要自己注意不要下载到这些东西就不会有问题。越狱后不知名的APP就不要下了,特别是那些只有盗版市场有的APP。不知名的盗版市场最好也不好用,cydia的源不要随意添加,下载插件要谨慎。
另外实际上AppStore上的APP在越狱环境下也不是绝对安全的,因为苹果也检测不到这些APP有没有做以上那些不轨之事。对于在盗版市场下载知名APP,似乎跟在AppStore上下载没区别,目前没见到有安装包被注入程序,不像Android市场。像支付宝这样敏感的APP数据是有加密的,就算获取了也没那么容易破解。所以也不用太担心在越狱机器上用它们不安全。虽然越狱后的iPhone有这么高风险,但比Android安全得多,因为市场环境好,没多少恶意APP出现,所以情况还是乐观的,了解清楚情况,只要稍微注意点就没问题,至今没听说有人因越狱了iPhone损失了什么
二越狱防护
一般而言完美越狱的设备,是非常危险的,通过脚本动态库注入,可以修改app的方法实现。所以尽量少越狱,即使越狱也不要随意安装插件。
1越狱检测,很多现在常用检测是判断
/Applications/Cydia.app
/Library/MobileSubstrate/MobileSubstrate.dylib
这两个是否存在,但是黑客现可能会改变这些工具的安装路径,躲过你的判断。
但比较好的办法是通过检测当前程序运行的环境变量:
•voidprintEnv(void)
•{
•char*env = getenv("DYLD_INSERT_LIBRARIES");
•NSLog(@"%s", env);
•}
未越狱设备返回结果是null,越狱设备就各有各的精彩了,尤其是老一点的iOS版本越狱环境。
2敏感交易的时候我们可以做一次校验判断是否正版app,通过二进制文件的验证,来确定app的安全性。
网上的方法是读取沙盒的程序二进制经过md5加密后做一些处理传给服务器验证,这个我也没想好。
3 GDB是大多数hackers的首选,阻止GDB依附是应用的常规办法
•#import
•
•intmain(intargc,charchar*argv[])
•{
•#ifndef DEBUG
•ptrace(PT_DENY_ATTACH,0,0,0);
•#endif
•@autoreleasepool{
•returnUIApplicationMain(argc, argv,nil, NSStringFromClass([WQMainPageAppDelegateclass]));
•}
•}
但遗憾的是,iPhone真实的运行环境是没有sys/ptrace.h抛出的。虽然ptrace方法没有被抛出,但是不用担心,我们可以通过dlopen拿到它。
dlopen:当path参数为0是,他会自动查找$LD_LIBRARY_PATH,$DYLD_LIBRARY_PATH, $DYLD_FALLBACK_LIBRARY_PATH和当前工作目录中的动态链接库.
1#import
2#import
3
4typedefint(*ptrace_ptr_t)(int_request, pid_t _pid, caddr_t _addr,int_data);
5#if !defined(PT_DENY_ATTACH)
6#define PT_DENY_ATTACH 31
7#endif // !defined(PT_DENY_ATTACH)
8
9voiddisable_gdb() {
10void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
11ptrace_ptr_t ptrace_ptr = dlsym(handle,"ptrace");
12ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
13dlclose(handle);
14}
15
16intmain(intargc,charchar*argv[])
17{
18#ifndef DEBUG
19disable_gdb();
20#endif
21@autoreleasepool{
22returnUIApplicationMain(argc, argv,nil, NSStringFromClass([WQMainPageAppDelegateclass]));
23}
}
4敏感的逻辑代码重写为C的代码
把函数名隐藏在结构体里,以函数指针成员的形式存储。
这样做的好处是,编译后,只留了下地址,去掉了名字和参数表,提高了逆向成本和攻击门槛。
也许,程序中存在一个类似这样的类:
•@interfaceXXUtil : NSObject
•
•+ (BOOL)isVerified;
•+ (BOOL)isNeedSomething;
•+ (void)resetPassword:(NSString*)password;
•
@end
改写的程序如下:
•//XXUtil.h
•#import
•
•typedefstruct_util {
•BOOL(*isVerified)(void);
•BOOL(*isNeedSomething)(void);
•void(*resetPassword)(NSString*password);
•}XXUtil_t ;
•
•#define XXUtil ([_XXUtil sharedUtil])
•
•@interface_XXUtil : NSObject
•
•+ (XXUtil_t*)sharedUtil;
•@end
24//XXUtil.m
25#import "XXUtil.h"
26
27staticBOOL_isVerified(void)
28{
29//bala bala ...
30returnYES;
31}
32
33staticBOOL_isNeedSomething(void)
34{
35//bala bala ...
36returnYES;
37}
38
39staticvoid_resetPassword(NSString*password)
40{
41//bala bala ...
42}
43
44staticXXUtil_t* util =NULL;
45@implementation_XXUtil
46
47+(XXUtil_t*)sharedUtil
48{
49staticdispatch_once_t onceToken;
50dispatch_once(&onceToken, ^{
51util = malloc(sizeof(XXUtil_t));
52util->isVerified = _isVerified;
53util->isNeedSomething = _isNeedSomething;
54util->resetPassword = _resetPassword;
55});
56returnutil;
57}
58
59+ (void)destroy
60{
61util ? free(util): 0;
62util =NULL;
63}
@end
最后,根据Xcode的报错指引,把以前这样的调用
[XXUtilisVerified];
对应改成:
XXUtil->isVerified();
5数据保护API
文件系统中的文件、keychain中的项,都是加密存储的。当用户解锁设备后,系统通过UDID密钥和用户设定的密码生成一个用于解密的密码密钥,存放在内存中,直到设备再次被锁,开发者可以通过Data
Protection API来设定文件系统中的文件、keychain中的项应该何时被解密。
1)文件保护
•/*为filePath文件设置保护等级*/
•NSDictionary*attributes = [NSDictionarydictionaryWithObject:NSFileProtectionComplete
•forKey:NSFileProtectionKey];
•[[NSFileManagerdefaultManager]setAttributes:attributes
•ofItemAtPath:filePath
•error:nil];
//文件保护等级属性列表
NSFileProtectionNone//文件未受保护,随时可以访问(Default)
NSFileProtectionComplete//文件受到保护,而且只有在设备未被锁定时才可访问
NSFileProtectionCompleteUntilFirstUserAuthentication//文件收到保护,直到设备启动且用户第一次输入密码
NSFileProtectionCompleteUnlessOpen//文件受到保护,而且只有在设备未被锁定时才可打开,不过即便在设备被锁定时,已经打开的文件还是可以继续使用和写入
2)keychain项保护
1/*设置keychain项保护等级*/
2NSDictionary*query = @{(__bridgeid)kSecClass: (__bridgeid)kSecClassGenericPassword,
3(__bridgeid)kSecAttrGeneric:@"MyItem",
4(__bridgeid)kSecAttrAccount:@"username",
5(__bridgeid)kSecValueData:@"password",
6(__bridgeid)kSecAttrService:[NSBundlemainBundle].bundleIdentifier,
7(__bridgeid)kSecAttrLabel:@"",
8(__bridgeid)kSecAttrDescription:@"",
9(__bridgeid)kSecAttrAccessible:(__bridgeid)kSecAttrAccessibleWhenUnlocked};
10
11OSStatus result = SecItemAdd((__bridge CFDictionaryRef)(query),NULL);
1//keychain项保护等级列表
2kSecAttrAccessibleWhenUnlocked//keychain项受到保护,只有在设备未被锁定时才可以访问
3kSecAttrAccessibleAfterFirstUnlock//keychain项受到保护,直到设备启动并且用户第一次输入密码
4kSecAttrAccessibleAlways//keychain未受保护,任何时候都可以访问(Default)
5kSecAttrAccessibleWhenUnlockedThisDeviceOnly//keychain项受到保护,只有在设备未被锁定时才可以访问,而且不可以转移到其他设备
6kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly//keychain项受到保护,直到设备启动并且用户第一次输入密码,而且不可以转移到其他设备
7kSecAttrAccessibleAlwaysThisDeviceOnly//keychain未受保护,任何时候都可以访问,但是不能转移到其他设备
for example
把一段信息infoStrng字符串写进文件,然后通过Data
Protection API设置保护。
1NSString*documentsPath =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES)firstObject];
2NSString*filePath = [documentsPathstringByAppendingPathComponent:@"DataProtect"];
3[infoStringwriteToFile:filePath
4atomically:YES
5encoding:NSUTF8StringEncoding
6error:nil];
7NSDictionary*attributes = [NSDictionarydictionaryWithObject:NSFileProtectionComplete
8forKey:NSFileProtectionKey];
9[[NSFileManagerdefaultManager]setAttributes:attributes
10ofItemAtPath:filePath
11error:nil];
设备锁屏(带密码保护)后,即使是越狱机,在root权限下cat读取那个文件信息也会被拒绝。
参考链接:
http://blog.csdn.net/yiyaaixuexi/article/category/1302847/1
这个妹子是阿里安全部的,很厉害啊。。。。
微博:程序媛念茜