☁️ HackTricks云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 - 你在一家**网络安全公司**工作吗?你想在HackTricks中看到你的**公司广告**吗?或者你想获得**PEASS的最新版本或下载PDF格式的HackTricks**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)! - 发现我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品:[**The PEASS Family**](https://opensea.io/collection/the-peass-family) - 获得[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com) - **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f)或[**电报群组**](https://t.me/peass),或者**关注**我在**Twitter**上的[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**。** - **通过向[hacktricks repo](https://github.com/carlospolop/hacktricks)和[hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)提交PR来分享你的黑客技巧**。
### NSCoding和NSSecureCoding iOS提供了两个用于Objective-C或`NSObject`对象**序列化**的协议:**`NSCoding`**和**`NSSecureCoding`**。当一个**类符合**这两个协议之一时,数据将被序列化为**`NSData`**:一个**字节缓冲区**的包装器。请注意,Swift中的`Data`与`NSData`或其可变对应物:`NSMutableData`是相同的。`NSCoding`协议声明了必须实现的两个方法,以便对其实例变量进行编码/解码。**使用`NSCoding`的类需要实现`NSObject`或被注解为@objc类**。`NSCoding`协议要求实现如下的编码和初始化方法。 ```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. } ``` `NSCoding`存在的问题是对象通常在你能够评估类类型之前已经被构建和插入。这使得攻击者可以轻松地注入各种数据。因此,引入了`NSSecureCoding`协议。当遵循[`NSSecureCoding`](https://developer.apple.com/documentation/foundation/NSSecureCoding)时,你需要包括: ```swift static var supportsSecureCoding: Bool { return true } ``` 当`init(coder:)`是类的一部分时。接下来,在解码对象时,应进行检查,例如: ```swift let obj = decoder.decodeObject(of:MyClass.self, forKey: "myKey") ``` 遵循`NSSecureCoding`确保实例化的对象确实是预期的对象。然而,对数据没有进行额外的完整性检查,数据也没有加密。因此,任何秘密数据都需要额外的加密,需要保护完整性的数据应该获得额外的HMAC。 ### 使用NSKeyedArchiver进行对象归档 `NSKeyedArchiver`是`NSCoder`的具体子类,提供了一种编码对象并将其存储在文件中的方法。`NSKeyedUnarchiver`解码数据并重新创建原始数据。让我们以`NSCoding`部分的示例为例,现在对它们进行归档和解档: ```swift // archiving: NSKeyedArchiver.archiveRootObject(customPoint, toFile: "/path/to/archive") // unarchiving: guard let customPoint = NSKeyedUnarchiver.unarchiveObjectWithFile("/path/to/archive") as? CustomPoint else { return nil } ``` 您还可以将信息保存在主要的plist `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 它是`Decodable`和`Encodable`协议的组合。`String`、`Int`、`Double`、`Date`、`Data`和`URL`本质上是`Codable`的:这意味着它们可以很容易地进行编码和解码,无需额外的工作。让我们看下面的例子: ```swift struct CustomPointStruct:Codable { var x: Double var name: String } ``` 通过在示例中将`CustomPointStruct`的继承列表中添加`Codable`,自动支持`init(from:)`和`encode(to:)`方法。有关`Codable`的工作原理的更多详细信息,请参阅[Apple开发者文档](https://developer.apple.com/documentation/foundation/archives\_and\_serialization/encoding\_and\_decoding\_custom\_types)。 您还可以使用`Codable`将数据保存在主属性列表`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) } ``` ### JSON 编码 有很多第三方库可以用来将数据编码为 JSON(如此处所示:[链接](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#json-and-codable))。然而,苹果提供了直接使用 `Codable` 结合 `JSONEncoder` 和 `JSONDecoder` 来进行 JSON 编码/解码的支持: ```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 有多种方法可以进行XML编码。与JSON解析类似,有各种第三方库,例如:[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)。 它们在速度、内存使用、对象持久性等方面有所不同,更重要的是它们在处理XML外部实体时的方式也不同。例如,参考[苹果iOS办公查看器中的XXE](https://nvd.nist.gov/vuln/detail/CVE-2015-3784)。因此,如果可能的话,禁用外部实体解析是关键。请参阅[OWASP XXE预防备忘单](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html)了解更多详细信息。除了这些库,您还可以使用苹果的[`XMLParser`类](https://developer.apple.com/documentation/foundation/xmlparser)。 当不使用第三方库而是使用苹果的`XMLParser`时,请确保让`shouldResolveExternalEntities`返回`false`。 {% hint style="danger" %} 所有这些序列化/编码数据的方式都可以**用于将数据存储在文件系统中**。在这些情况下,检查存储的数据是否包含任何**敏感信息**。此外,在某些情况下,您可能能够**滥用某些序列化**数据(通过MitM捕获它或在文件系统中修改它),反序列化任意数据并**使应用程序执行意外操作**(参见[反序列化页面](../../pentesting-web/deserialization/))。在这些情况下,建议发送/保存加密和签名的序列化数据。 {% endhint %} ## 参考资料 {% 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 🎥 - 您在**网络安全公司**工作吗?您想在HackTricks中看到您的**公司广告**吗?或者您想获得**PEASS的最新版本或下载PDF格式的HackTricks**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)! - 发现我们的独家[NFT收藏品](https://opensea.io/collection/the-peass-family)——[**The PEASS Family**](https://opensea.io/collection/the-peass-family) - 获取[**官方PEASS和HackTricks衣物**](https://peass.creator-spring.com) - **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f)或[**电报群组**](https://t.me/peass),或在**Twitter**上**关注**我[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**。** - **通过向[hacktricks repo](https://github.com/carlospolop/hacktricks)和[hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)提交PR来分享您的黑客技巧**。