When to use NSSecureCoding

13,712

Specifically if a class conforms to NSCoding by encoding/decoding its instance variables, as opposed to the whole instance of itself, would it still be advisable to implement NSSecureCoding?

It depends on the needs of your application. For any old app, persisting things to disk with plain NSCoding is fine, because the information being written, and the application itself, are (should not) be sensitive in nature. But, say you were a bank releasing an application. You may choose to persist some account information, or an API key to disk so you could communicate with your service, verify the identity of the user, etc. You may not want the whole object, but that shouldn't matter. NSCoder doesn't care what is being read, just that it can read it and do its job correctly. This is a problem.

Security-wise, is there any benefit in using -decodeObjectOfClass:forKey: as opposed to -decodeObjectForKey:?

Yes, very much so. The very fact that you're relying on NSCoder to serialize/deserialize an object (let alone the right object) is a huge attack vector. Once a hacker has modified the information in the format used by NSCoder (a plist-like structure, which is both human-readable and very maleable), then there is no way to guarantee that what you're getting back is what you put in. NSCoder doesn't care that someone decided to switch the classes contained in the archive so you're re-constructing an object of a malicious class, and neither does the runtime. In fact, a smart enough hacker would inject a patch into the application to make sure that the deserialized object would induce some sort of undefined state (a stack overflow), which could be used to potentially exploit the entire application.

decodeObjectOfClass:forKey: allows you to force NSCoder to be a lot smarter about deserialization, and it patches what would be a very large hole. That's not to say that you should never use NSCoder without NSSecureCoding, but rather that you have to be smart about what situations you use it in.

Share:
13,712
Gabriele Petronella
Author by

Gabriele Petronella

I wanted to write something smart here, so I ended up writing something about me wanting to write something smart, which I hope it will make me look smart. Why are you reading this anyway?

Updated on June 13, 2022

Comments

  • Gabriele Petronella
    Gabriele Petronella about 2 years

    I'm learning about the NSSecureCoding protocol introduced by Apple in iOS 6.

    From my understanding so far, it should be used whenever a class encodes/decodes instances of itself, in order to prevent substitution attacks.

    I'm wondering whether it would be appropriate to use it in other cases.

    Specifically if a class conforms to NSCoding by encoding/decoding its instance variables, as opposed to the whole instance of itself, would it still be advisable to implement NSSecureCoding?


    EDIT

    Suppose I have a class that is implementing NSCoding like follows

    - (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;
    }
    

    and suppose also that no XPC is involved. Instances of this class will be archived in a plist stored on disk.

    Security-wise, is there any benefit in using -decodeObjectOfClass:forKey: as opposed to -decodeObjectForKey:?

  • Gabriele Petronella
    Gabriele Petronella about 11 years
    so I guess my question now is: provided that everything is archived on disk and no XPC is involved, is it worth to convert an existing code base to adopt NSSecureCoding? Does it have any advantage?
  • Robert
    Robert about 11 years
    My feeling is No - I suspect apple use it internally for XPC. I.e. if ([class conformsToProtocol:@protocol(NSSecureCoding)] && [class supportsSecureCoding]) useWithXPC else throwError
  • Gabriele Petronella
    Gabriele Petronella about 11 years
    Ok, for the sake of completeness, I posted an example in my edited answer. Thank you for the answer
  • Gabriele Petronella
    Gabriele Petronella about 11 years
    thank you for the answer. I added an example to my question, that you may want to take a look at.
  • Hejazi
    Hejazi about 11 years
    In most of the apps, where you're the one who encodes and decodes the data, there is no real benefit from calling decodeObjectOfClass:forKey: instead of decodeObjectForKey:.
  • Gabriele Petronella
    Gabriele Petronella about 11 years
    very nice answer, thank you very much. Just to complicate things a little bit more, what if I need to support iOS 5 too. I guess checking the class of the returned object is the only way to go, isn't it?
  • CodaFi
    CodaFi about 11 years
    It's easier to just write your own. I know there are a lot of frameworks now that support key-value-coding to JSON mechanisms, or just redo it in C. Whatever you come up with with undoubtedly be faster and more stable than the mess that is NSCoder
  • Gabriele Petronella
    Gabriele Petronella about 11 years
    I'm afraid I don't quite get what you mean by "write your own". Your own coder?
  • CodaFi
    CodaFi about 11 years
    Yes. There are a million other formats, and a million other ways of serializing objects, I'm sure you can find one that suits your needs and that supports older iOSes (especially if it's in another language).
  • CodaFi
    CodaFi about 11 years
    The problem with checking the class is that even among Foundation objects, the isa pointer can lie to you. The very fact that object_setClass() and isa assignment exists means you're powerless to stop any old object from slipping by undetected.
  • Gabriele Petronella
    Gabriele Petronella about 11 years
    Thank you for the suggestion. Unfortunately, in this specific scenario, I'm just an auditor, not a developer of the product. I frankly don't think that the developer team will go through such a massive change in the architecture. Would checking the class still be a reasonable "patch" for iOS 5?
  • CodaFi
    CodaFi about 11 years
    "Reasonable," but by no means perfect.
  • Gabriele Petronella
    Gabriele Petronella about 11 years
    Agreed. Thank you for the answer and the advice.