### NSCoding y NSSecureCoding iOS cuenta con dos protocolos para la **serialización** de objetos para Objective-C o `NSObject`s: **`NSCoding`** y **`NSSecureCoding`**. Cuando una **clase se ajusta** a cualquiera de los protocolos, los datos se serializan a **`NSData`**: un envoltorio para **buffers de bytes**. Tenga en cuenta que `Data` en Swift es lo mismo que `NSData` o su contraparte mutable: `NSMutableData`. El protocolo `NSCoding` declara los dos métodos que deben implementarse para codificar/decodificar sus variables de instancia. **Una clase que utiliza `NSCoding` necesita implementar `NSObject` o estar anotada como una clase @objc**. El protocolo `NSCoding` requiere implementar encode e init como se muestra a continuación. ```swift class CustomPoint: NSObject, NSCoding { //required by NSCoding: func encode(with aCoder: NSCoder) { aCoder.encode(x, forKey: "x") aCoder.encode(name, forKey: "name") } var x: Double = 0.0 var name: String = "" init(x: Double, name: String) { self.x = x self.name = name } // required by NSCoding: initialize members using a decoder. required convenience init?(coder aDecoder: NSCoder) { guard let name = aDecoder.decodeObject(forKey: "name") as? String else {return nil} self.init(x:aDecoder.decodeDouble(forKey:"x"), name:name) } //getters/setters/etc. } ``` El problema con `NSCoding` es que el objeto a menudo ya está **construido e insertado antes de que puedas evaluar** el tipo de clase. Esto **permite a un atacante inyectar fácilmente todo tipo de datos**. Por lo tanto, se ha introducido el protocolo **`NSSecureCoding`**. Al conformarse con [`NSSecureCoding`](https://developer.apple.com/documentation/foundation/NSSecureCoding), es necesario incluir: ```swift static var supportsSecureCoding: Bool { return true } ``` Cuando `init(coder:)` es parte de la clase. A continuación, al decodificar el objeto, se debe realizar una comprobación, por ejemplo: ```swift let obj = decoder.decodeObject(of:MyClass.self, forKey: "myKey") ``` La conformidad con `NSSecureCoding` asegura que los objetos que se están instanciando son realmente los que se esperaban. Sin embargo, **no se realizan controles adicionales de integridad** sobre los datos y los datos no están cifrados. Por lo tanto, cualquier dato secreto necesita **cifrado adicional** y los datos cuya integridad deba ser protegida, deben tener un HMAC adicional. ### Archivado de objetos con NSKeyedArchiver `NSKeyedArchiver` es una subclase concreta de `NSCoder` y proporciona una forma de codificar objetos y almacenarlos en un archivo. El `NSKeyedUnarchiver` decodifica los datos y recrea los datos originales. Tomemos el ejemplo de la sección `NSCoding` y ahora los archivamos y desarchivamos: ```swift // archiving: NSKeyedArchiver.archiveRootObject(customPoint, toFile: "/path/to/archive") // unarchiving: guard let customPoint = NSKeyedUnarchiver.unarchiveObjectWithFile("/path/to/archive") as? CustomPoint else { return nil } ``` También puedes guardar la información en el plist primario `NSUserDefaults`: ```swift // archiving: let data = NSKeyedArchiver.archivedDataWithRootObject(customPoint) NSUserDefaults.standardUserDefaults().setObject(data, forKey: "customPoint") // unarchiving: if let data = NSUserDefaults.standardUserDefaults().objectForKey("customPoint") as? NSData { let customPoint = NSKeyedUnarchiver.unarchiveObjectWithData(data) } ``` ### Codable Es una combinación de los protocolos `Decodable` y `Encodable`. Un `String`, `Int`, `Double`, `Date`, `Data` y `URL` son `Codable` por naturaleza: lo que significa que pueden ser codificados y decodificados fácilmente sin ningún trabajo adicional. Tomemos el siguiente ejemplo: ```swift struct CustomPointStruct:Codable { var x: Double var name: String } ``` Al agregar `Codable` a la lista de herencia de `CustomPointStruct` en el ejemplo, los métodos `init(from:)` y `encode(to:)` son compatibles automáticamente. Para obtener más detalles sobre el funcionamiento de `Codable`, consulte [la documentación de desarrolladores de Apple](https://developer.apple.com/documentation/foundation/archives\_and\_serialization/encoding\_and\_decoding\_custom\_types). También puede usar codable para guardar los datos en la lista de propiedades primarias `NSUserDefaults`: ```swift struct CustomPointStruct: Codable { var point: Double var name: String } var points: [CustomPointStruct] = [ CustomPointStruct(point: 1, name: "test"), CustomPointStruct(point: 2, name: "test"), CustomPointStruct(point: 3, name: "test"), ] UserDefaults.standard.set(try? PropertyListEncoder().encode(points), forKey: "points") if let data = UserDefaults.standard.value(forKey: "points") as? Data { let points2 = try? PropertyListDecoder().decode([CustomPointStruct].self, from: data) } ``` ### Codificación JSON Existen muchas bibliotecas de terceros para codificar datos en JSON (como se explica [aquí](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#json-and-codable)). Sin embargo, Apple proporciona soporte para la codificación/decodificación de JSON directamente combinando `Codable` junto con un `JSONEncoder` y un `JSONDecoder`: ```swift struct CustomPointStruct: Codable { var point: Double var name: String } let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted let test = CustomPointStruct(point: 10, name: "test") let data = try encoder.encode(test) let stringData = String(data: data, encoding: .utf8) // stringData = Optional ({ // "point" : 10, // "name" : "test" // }) ``` ### XML Existen múltiples formas de codificar XML. Al igual que con el análisis de JSON, existen varias bibliotecas de terceros, como: [Fuzi](https://github.com/cezheng/Fuzi), [Ono](https://github.com/mattt/Ono), [AEXML](https://github.com/tadija/AEXML), [RaptureXML](https://github.com/ZaBlanc/RaptureXML), [SwiftyXMLParser](https://github.com/yahoojapan/SwiftyXMLParser), [SWXMLHash](https://github.com/drmohundro/SWXMLHash) Varían en términos de velocidad, uso de memoria, persistencia de objetos y lo más importante: difieren en cómo manejan las entidades XML externas. Vea [XXE en el visor de Office de Apple iOS](https://nvd.nist.gov/vuln/detail/CVE-2015-3784) como ejemplo. Por lo tanto, es clave deshabilitar el análisis de entidades externas XML si es posible. Consulte la [hoja de trucos de prevención de XXE de OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XML\_External\_Entity\_Prevention\_Cheat\_Sheet.html) para obtener más detalles. Además de las bibliotecas, se puede hacer uso de la clase [`XMLParser` de Apple](https://developer.apple.com/documentation/foundation/xmlparser) Cuando no se utilizan bibliotecas de terceros, sino la clase `XMLParser` de Apple, asegúrese de que `shouldResolveExternalEntities` devuelva `false`. {% hint style="danger" %} Todas estas formas de serializar/codificar datos se pueden **utilizar para almacenar datos en el sistema de archivos**. En esos escenarios, verifique si los datos almacenados contienen algún tipo de **información sensible**.\ Además, en algunos casos puede ser posible **abusar de algunos datos serializados** (capturándolos a través de MitM o modificándolos dentro del sistema de archivos) deserializando datos arbitrarios y **haciendo que la aplicación realice acciones inesperadas** (ver la página de deserialización). En estos casos, se recomienda enviar/guardar los datos serializados cifrados y firmados. {% endhint %} ## Referencias {% embed url="https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-object-persistence-mstg-platform-8" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 - ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? o ¿quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)! - Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección de exclusivos [**NFTs**](https://opensea.io/collection/the-peass-family) - Consigue el [**oficial PEASS & HackTricks swag**](https://peass.creator-spring.com) - **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** - **Comparte tus trucos de hacking enviando PRs al [repositorio de hacktricks](https://github.com/carlospolop/hacktricks) y al [repositorio de hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.