Подтвердить что ты не робот

Когда использовать NSSecureCoding

Я изучаю протокол NSSecureCoding, представленный Apple в 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:?

4b9b3361

Ответ 1

В частности, если класс соответствует NSCoding путем кодирования/декодирования его переменных экземпляра, в отличие от всего экземпляра самого себя, было бы целесообразным реализовать NSSecureCoding?

Это зависит от потребностей вашего приложения. Для любого старого приложения сохраняющиеся вещи на диске с простым NSCoding прекрасны, потому что написанная информация и само приложение (не должны) быть чувствительными по своей природе. Но, скажем, вы были банком, выпустившим заявку. Вы можете сохранить данные учетной записи или ключ API на диске, чтобы вы могли общаться с вашей службой, проверить личность пользователя и т.д. Возможно, вам не нужен весь объект, но это не имеет значения. NSCoder не заботится о том, что читается, просто чтобы он мог прочитать и правильно выполнить свою работу. Это проблема.

Безопасно, есть ли какая-либо польза в использовании -decodeObjectOfClass: forKey: в отличие от -decodeObjectForKey:?

Да, очень. Сам факт, что вы полагаетесь на NSCoder для сериализации/десериализации объекта (не говоря уже о правильном объекте), - это огромный вектор атаки. После того, как хакер изменил информацию в формате, используемом NSCoder (подобная plist структуре, которая является удобочитаемой и очень малируемой), тогда нет способа гарантировать, что то, что вы получаете, - это то, что вы вводите NSCoder не заботится о том, чтобы кто-то решил переключить классы, содержащиеся в архиве, чтобы вы переконструировали объект вредоносного класса, а также время выполнения. На самом деле достаточно умный хакер вводит исправление в приложение, чтобы убедиться, что десериализованный объект вызовет какое-то состояние undefined (переполнение стека), которое может быть использовано для потенциального использования всего приложения.

decodeObjectOfClass:forKey: позволяет заставить NSCoder быть намного умнее десериализации, и он исправляет то, что было бы очень большой дырой. Это не означает, что вы никогда не должны использовать NSCoder без NSSecureCoding, а скорее должны быть умны в ситуациях, в которых вы его используете.

Ответ 2

Когда вы вызываете decodeObjectForKey: для декодирования переменной экземпляра, объект все еще строится, прежде чем вы сможете проверить его тип класса (причина, по которой вводится NSSecureCoding).

Итак, я предполагаю, что одни и те же правила все еще применяются здесь, и поэтому лучше использовать decodeObjectOfClass:forKey вместо decodeObjectForKey:, когда вы также декодируете переменные экземпляра.

Ответ 3

Вот мое чувство от чтения документов и сообщений NSHipsters.

Вы используете NSCoding за то, что ваши calsses в двоичном формате. Это либо для архивирования данных на диск, либо для межпроцессного взаимодействия. Архивирование на диск относительно безопасно, однако межпроцессная связь опасна, потому что вы можете не доверять исходному процессу, который предоставляет вам данные.

Итак, если вы просто используете 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;
}