iOS安全编码规范

一.本地数据安全规范

1.本地存储密码、敏感数据加密:

本地存储:NSUserDefaults存储、plist文件存储、归档存储、CoreData存储时候,不能存储明文密码和敏感数据(如:用户手机号、姓名、邮箱、身份证、银行卡等敏感信息)。

原因:
iTunes会备份应用Documents目录,越狱手机通过iTools工具等可以直接查看应用的Documents、Library/Caches、Tmp及其他所有目录存储信息,而这些存储都在这些目录下。
错误示范:

[data setObject:_userNameTF.text forKey:@"username"];
[data setObject:_passwordTF.text forKey:@"password"];

正确示范:

[data setObject:[AES encode:_userNameTF.text] forKey:@"username"];
[data setObject:[AES encode:_passwordTF.text] forKey:@"password"];

2. 数据库存储:

使用数据库存储,需要对密码敏感数据等加密,或者整库加密

原因:
数据库,一般存储在Documents路径下的特殊文件,格式一般为.db或者.sqlite,导出后使用特殊工具即可查看如DB Browser for sqlite 和 SQLiteStudio。
正确示例

// 对数据库进行加密 SAFE_KEY: 为打开数据库密码
sqlite_key(db, SAFE_KEY.cString(using: String.Encoding.utf8), Int32(SAFE_KEY.characters.count))

3. keychain存储:

keychain的密码、证书、密钥、数字身份等存储必须加密存储

原因
Keychain的数据库内容使用了设备唯一的硬件密钥进行加密,该硬件密钥无法从设备上导出,存储内容比上面两个安全很多,但是攻击者还是可以通过越狱该设备,以及一些步骤读取到keychain里明文信息。
错误示例

+(void)saveUserName:(NSString *)userName andSavePassWord:(NSString *)password
    {
      NSMutableDictionary *usernamepasswordKVPairs = [[NSMutableDictionary alloc] initWithCapacity:42];
      [usernamepasswordKVPairs setObject:password forKey:KEY_PASSWORD];
      [usernamepasswordKVPairs setObject:userName forKey:KEY_USERNAME];
      [CJFKeychain save:KEY_IN_KEYCHAIN data:usernamepasswordKVPairs];
    }

正确示例

+(void)saveUserName:(NSString *)userName andSavePassWord:(NSString *)password
    {
      NSMutableDictionary *usernamepasswordKVPairs = [[NSMutableDictionary alloc] initWithCapacity:42];
      [usernamepasswordKVPairs setObject:[AES encode:password] forKey:KEY_PASSWORD];
      [usernamepasswordKVPairs setObject:[AES encode:userName] forKey:KEY_USERNAME];
      [CJFKeychain save:KEY_IN_KEYCHAIN data:usernamepasswordKVPairs];
    }

4.剪切板:

在使用剪切板的时候,使用应用级剪切板,在应用退出时候清空剪切板。
错误示例

// 获取系统级别的剪切板,保存在系统文件内,应用间共享
    -(void)realyCopy() {
      pasteboard = [UIPasteboard generalPasteboard];
      [pasteboard setString:@"复制的字符串内容"];
    }

正确示例

// 自定义的剪切板,在应用内共享,退出程序后就会被清除
    -(void)realyCopy() {
      pasteboard = [UIPasteboard pasteboardWithName:@"test" create: YES];
      [pasteboard setString:@"复制的字符串内容"];
    }
// 获取一个应用级别的剪切板,相当于自定义的剪切板,只是name为空,在应用内共享,退出程序后就会被清除
    -(void)realyCopy() {
      pasteboard = [UIPasteboard pasteboardWithUniqueName];
      [pasteboard setString:@"复制的字符串内容"];
    }

5. 系统键盘

①禁用了自动纠正功能的文本框:设置UITextView/UITextField 属性autocorrectionType 为. no类型 。
②密码输入框被一定要设置为密码输入类型:设置UITextView/UITextField 属性isSecureTextEntry为true。
③手机号、金钱输入框设置为数字键盘:设置UITextView/UITextField属性 keyboardType为数字键盘。
④还有些敏感的信息输入以上无法满足:自定义键盘。

6.应用进入后台时高斯模糊:

应用在进入后台挂起时,Window层增加一层高斯模糊,或添加一个遮挡页面。
原因:
当应用进入后台时,系统会自动在当前应用的页面截屏并存储到手机内,如果当前页面涉及敏感信息时,被攻击会造成泄密。如下图生成的两张图片路径:

1.png

二.HTTPS

  1. 所有网络请求都用SSL/TLS加密传输,即HTTPS和WSS等。

  2. 在使用AFNetworking网络框架,必须配置证书验证,避免中间人伪造攻击。所以我们必须使用AFSSLPinningModeCertificate对证书进行完整校验。

三.UIWebView漏洞

  1. XSS漏洞

    ①、对输入框内的数据进行关键词过滤(如“script”字符串),避免输入恶意脚本语言。

    ②、在加载网页的内容之前,会用dataWithContentsOfURL方法将加载的网页的内容提取出来放入NSData中,在使用loadHTMLString之前可以对NSData的内容过滤,编码等等。

    示例

- (void)test {
      NSString *urlStr = @"https://www.baidu.com";
      NSURL *url = [NSURL URLWithString:urlStr];
      NSData *data = [NSData dataWithContentsOfURL:url];
      NSString *htmlStr = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"script" withString:@""];
    }

四.Xcode

  1. 开发人员必须从App Store下载安装Xcode,或者从apple官网下载:https://developer.apple.com/download/more

    原因:

    2015年的xcode后门事件,原因就是从非官方渠道下载的xcode,被导入恶意代码会上传产品自身的部分基本信息,包括安装时间、应用id,应用名称、系统版本以及国家和语言等。

2.png

五.逆向工程反编译APP

  1. 你想反编译防止:

    ①、所有使用密码、敏感信息字符串地方都为密文,调用方法解密使用,不能直接明文存储。

    ②、编译构建时,对类名、方法名做混淆替换。

    ③、加固:使用第三方安全SDK来解决以上问题(网易盾、几维安全等)。

六.检测越狱和反调试

  1. 检测越狱:

①、判断是否存在越狱文件

    /Applications/Cydia.app
    /Library/MobileSubstrate/MobileSubstrate.dylib
    /bin/bash
    /usr/sbin/sshd
    /etc/apt

②、判断cydia的URL scheme

- (BOOL)isOpenCydia{
      return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://"]];
    }

③、检测到越狱状态时候,禁止网络访问,清除本地缓存数据、数据库数据等。

  1. 反调试

    使用库来阻止GDB依附,从而达到阻止攻击者破解代码后,对我们的程序进行调试

#import   
    #import   

    typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);  
    #if !defined(PT_DENY_ATTACH)  
    #define PT_DENY_ATTACH 31  
    #endif // !defined(PT_DENY_ATTACH)  

    void disable_gdb() {  
      void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);  
      ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");  
      ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);  
      dlclose(handle);  
    }  

    int main(int argc, charchar *argv[])  
    {  
    #ifndef DEBUG  
      disable_gdb();  
    #endif  
      @autoreleasepool {  
          return UIApplicationMain(argc, argv, nil, NSStringFromClass([WQMainPageAppDelegate class]));  
      }  
    }

你可能感兴趣的:(iOS安全编码规范)