The problem, described in the talk the exploit was first raised in —Marshalling Pickles — is that arbitrary object deserialization (or marshalling, or un-pickling, whatever your language calls it) is inherently unsafe, and should never be performed on untrusted data.
[…]
This means that if there isany object reachable from your runtime that declares itself serializable and could be fooled into doing something bad by malicious data, then it can be exploited through deserialization. This is a mind-bogglingly enormous amount of potentially vulnerable and mostly un-audited code.
In Cocoa land, this is whywe haveNSSecureCoding. Some things to be aware of:
If you’re decoding a collection containing custom classes, it’snot enough for them to conform toNSSecureCoding. You also have to use-[NSCoder decodeObjectOfClasses:forKey:] and add your classes to the set.
NSSecureCoding to check that you are decoding objects with the proper classes, you should still verify that the structure of the objects is correct.There’s a special (rather inconvenient) way that you need tocreate your archiver and unarchiver:
tl;dr: don’t use
-[NSKeyedArchiver encodeRootObject:]or-[NSKeyedUnarchiver decodeObject]in new code unless you need compatibility with Format 1 archives.Since
+[NSKeyedArchiver archivedDataWithRootObject:]and+[NSKeyedUnarchiver unarchiveObjectWithData:]don’t give you an opportunity to call-setRequiresSecureCoding:YES, they’re out of the party as well.That leaves us with
-[NSKeyedArchiver encodeObject:forKey:NSKeyedArchiveRootObjectKey]and-[NSKeyedUnarchiver decodeObjectForKey:NSKeyedArchiveRootObjectKey].
NSCoder still doesn’t supportNSError. [Update (2015-11-08): See the comments below.] I have not tested what happens if a Swift class implementsinit(coder:) and an exception is raised.Update (2015-11-10):Paul Kim:
Even if you don’t call
-decodeObject:… in your-initWithCoder:you still have to implement+supportsSecureCodingand return YES in your class, even if a superclass already did it.[…]
Objects like NSPredicate and NSSortDescriptor can take in key paths or selectors making them potentially unsafe. As a result, they are disabled after being securely decoded. To re-enable them, you have to call
-allowEvaluation(presumably after doing some sort of check).
CocoaiOSJavaMacNSErrorObjective-CProgrammingPythonSecuritySwift Programming Language
NSCoder got NSError-ish methods in 10.11:
https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/#10_11Coder (Unfortunately, I don't think this anchor actually works)
and for Swift, there's this in NSCoder.h:
- (nullable id)decodeTopLevelObjectAndReturnError:(NSError **)error NS_AVAILABLE(10_11, 9_0) NS_SWIFT_UNAVAILABLE("Use 'decodeTopLevelObject() throws' instead");
@aaron Thanks forreminding me! For some reason, that’s not in the regulardocumentation. Here’s the full set of newNSCoder error methods:
- (nullable id)decodeTopLevelObjectAndReturnError:(NSError **)error;- (nullable id)decodeTopLevelObjectForKey:(NSString *)key error:(NSError **)error;- (nullable id)decodeTopLevelObjectOfClass:(Class)aClass forKey:(NSString *)key error:(NSError **)error;- (nullable id)decodeTopLevelObjectOfClasses:(nullable NSSet<Class> *)classes forKey:(NSString *)key error:(NSError **)error;- (void)failWithError:(NSError *)error;
AndNSKeyedUnarchiver now has:
+ (nullable id)unarchiveTopLevelObjectWithData:(NSData *)data error:(NSError **)error;
There’s still no convenience method for secure unarchiving.
Black Friday
Blog
Archives
Tag Cloud
Top Posts
Recently Updated
RSS Feed ·Comments
Mastodon ·Twitter
Apple News
Trackback
Support this site viaPatreon.
Try my Mac apps: