30

我正在了解NSSecureCodingApple 在 iOS 6 中引入的协议。

据我目前的理解,每当一个类对自身的实例进行编码/解码时,都应该使用它,以防止替换攻击。

我想知道在其他情况下使用它是否合适。

具体来说,如果一个类NSCoding通过编码/解码其实例变量而不是其自身的整个实例来遵守,那么它仍然是可取的实现NSSecureCoding吗?


编辑

假设我有一个实现NSCoding如下的类

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.aString forKey:@"aMeaningfulString"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    if((self = [super init])) {
        self.aString = [decoder decodeObjectForKey:@"aMeaningfulString"];
    }
    return self;
}

并假设不涉及 XPC。此类的实例将存档在存储在磁盘上的 plist 中。

安全方面,使用-decodeObjectOfClass:forKey:与 相比 有什么好处-decodeObjectForKey:吗?

4

3 回答 3

27

具体来说,如果一个类通过编码/解码其实例变量而不是其自身的整个实例来符合 NSCoding,那么实现 NSSecureCoding 是否仍然是可取的?

这取决于您的应用程序的需求。对于任何旧应用程序,使用普通的 NSCoding 将内容持久化到磁盘是可以的,因为正在写入的信息以及应用程序本身本质上(不应该)是敏感的。但是,假设您是一家发布应用程序的银行。您可以选择将一些帐户信息或 API 密钥保存到磁盘,以便您可以与您的服务通信、验证用户的身份等。您可能不需要整个对象,但这无关紧要。NSCoder 不关心正在读取什么,只关心它可以读取并正确完成它的工作这是个问题。

安全方面,使用 -decodeObjectOfClass:forKey: 与 -decodeObjectForKey: 相比有什么好处吗?

是的,非常如此。您依赖 NSCoder 序列化/反序列化对象(更不用说正确的对象)这一事实是一个巨大的攻击向量。一旦黑客以 NSCoder 使用的格式修改了信息(一种类似 plist 的结构,既易于阅读,又非常具有可塑性),那么就无法保证你得到的就是你输入的. NSCoder 不关心有人决定切换存档中包含的类,因此您正在重新构建恶意类的对象,运行时也不关心。事实上,足够聪明的黑客会在应用程序中注入一个补丁,以确保反序列化的对象会引发某种未定义的状态(堆栈溢出),这可能会被用来潜在地利用整个应用程序。

decodeObjectOfClass:forKey:允许您强制 NSCoder 在反序列化方面更加智能,并且它修补了一个非常大的漏洞。这并不是说你不应该在没有NSCoder 的情况NSSecureCoding下使用它,而是说你必须聪明地知道你在什么情况下使用它。

于 2013-06-26T00:58:44.830 回答
0

当你调用decodeObjectForKey:解码一个实例变量时,在你可以验证它的类类型之前,仍然构造了对象(原因NSSecureCoding介绍)。

所以我假设这里仍然应用相同的规则,因此最好在解码实例变量时使用它decodeObjectOfClass:forKey而不是。decodeObjectForKey:

于 2013-06-25T16:40:23.213 回答
0

这是我阅读文档和NSHipsters帖子的感受。

NSCoding用于将您的课程转换为二进制文件。这要么用于将数据归档到磁盘,要么用于进程间通信。归档到磁盘相对安全,但是,进程间通信存在风险,因为您可能不信任为您提供数据的源进程。

所以首先,如果您只是NSCoding用于将对象持久写入磁盘,那么您无需担心NSSecureCoding(但是它很容易实现,见下文)

具体来说,如果一个类通过编码/解码其实例变量而不是其自身的整个实例来符合 NSCoding,那么实现 NSSecureCoding 是否仍然是可取的?

我不确定如何解码一个类的整个实例。通过从归档器中解码一些数据并对其进行处理来解码一个类。

- (id) initWithCoder:(NSCoder *)aDecoder 
{
   if (self = [super initWithCoder:aDecoder]) 
   {
       // Old way
       //obj myUnsecureObj = [aDecoder decodeObjectForKey:@"myKey"];

       // New way
       obj mySecureObj = [aDecoder decodeObjectOfClass:[MyClass class]
                                                forKey:@"myKey2"];

       // Use mySecureObj (e.g. save to an property / ivar)
   }
   return self;
}

+ (BOOL)supportsSecureCoding {
   return YES;
}
于 2013-06-25T16:51:02.370 回答