mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-30 06:53:11 +00:00
149 lines
9.4 KiB
Markdown
149 lines
9.4 KiB
Markdown
### NSCoding e NSSecureCoding
|
|
|
|
O iOS vem com dois protocolos para **serialização** de objetos para Objective-C ou `NSObject`s: **`NSCoding`** e **`NSSecureCoding`**. Quando uma **classe se conforma** a qualquer um dos protocolos, os dados são serializados para **`NSData`**: um invólucro para **buffers de bytes**. Observe que `Data` em Swift é o mesmo que `NSData` ou seu contraparte mutável: `NSMutableData`. O protocolo `NSCoding` declara os dois métodos que devem ser implementados para codificar/decodificar suas variáveis de instância. **Uma classe que usa `NSCoding` precisa implementar `NSObject` ou ser anotada como uma classe @objc**. O protocolo `NSCoding` requer a implementação de codificação e inicialização, conforme mostrado abaixo.
|
|
```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.
|
|
}
|
|
```
|
|
O problema com `NSCoding` é que o objeto muitas vezes já está **construído e inserido antes que você possa avaliar** o tipo de classe. Isso **permite que um invasor injete facilmente todos os tipos de dados**. Portanto, o protocolo **`NSSecureCoding`** foi introduzido. Ao se conformar com [`NSSecureCoding`](https://developer.apple.com/documentation/foundation/NSSecureCoding), você precisa incluir:
|
|
```swift
|
|
static var supportsSecureCoding: Bool {
|
|
return true
|
|
}
|
|
```
|
|
quando `init(coder:)` faz parte da classe. Em seguida, ao decodificar o objeto, deve ser feita uma verificação, por exemplo:
|
|
```swift
|
|
let obj = decoder.decodeObject(of:MyClass.self, forKey: "myKey")
|
|
```
|
|
A conformidade com `NSSecureCoding` garante que os objetos que estão sendo instanciados são realmente aqueles que eram esperados. No entanto, **não há verificações adicionais de integridade** sobre os dados e os dados não são criptografados. Portanto, quaisquer dados secretos precisam de **criptografia** adicional e os dados cuja integridade deve ser protegida devem receber um HMAC adicional.
|
|
|
|
### Arquivamento de objetos com NSKeyedArchiver
|
|
|
|
`NSKeyedArchiver` é uma subclasse concreta de `NSCoder` e fornece uma maneira de codificar objetos e armazená-los em um arquivo. O `NSKeyedUnarchiver` decodifica os dados e recria os dados originais. Vamos pegar o exemplo da seção `NSCoding` e agora arquivá-los e desarquivá-los:
|
|
```swift
|
|
// archiving:
|
|
NSKeyedArchiver.archiveRootObject(customPoint, toFile: "/path/to/archive")
|
|
|
|
// unarchiving:
|
|
guard let customPoint = NSKeyedUnarchiver.unarchiveObjectWithFile("/path/to/archive") as?
|
|
CustomPoint else { return nil }
|
|
```
|
|
Você também pode salvar as informações no plist primário `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
|
|
|
|
É uma combinação dos protocolos `Decodable` e `Encodable`. Uma `String`, `Int`, `Double`, `Date`, `Data` e `URL` são `Codable` por natureza: o que significa que podem ser facilmente codificados e decodificados sem nenhum trabalho adicional. Vamos ver o seguinte exemplo:
|
|
```swift
|
|
struct CustomPointStruct:Codable {
|
|
var x: Double
|
|
var name: String
|
|
}
|
|
```
|
|
Ao adicionar `Codable` à lista de herança para `CustomPointStruct` no exemplo, os métodos `init(from:)` e `encode(to:)` são automaticamente suportados. Para mais detalhes sobre o funcionamento de `Codable`, confira [a documentação do desenvolvedor da Apple](https://developer.apple.com/documentation/foundation/archives\_and\_serialization/encoding\_and\_decoding\_custom\_types).
|
|
|
|
Você também pode usar o codable para salvar os dados na lista de propriedades primárias `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)
|
|
}
|
|
```
|
|
### Codificação JSON
|
|
|
|
Existem muitas bibliotecas de terceiros para codificar dados em JSON (como exposto [aqui](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#json-and-codable)). No entanto, a Apple fornece suporte para codificação/decodificação JSON diretamente combinando `Codable` com um `JSONEncoder` e um `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
|
|
|
|
Existem várias maneiras de fazer a codificação XML. Assim como a análise JSON, existem várias bibliotecas de terceiros, 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)
|
|
|
|
Elas variam em termos de velocidade, uso de memória, persistência de objetos e, mais importante, diferem em como lidam com as entidades XML externas. Veja [XXE no visualizador de escritório da Apple iOS](https://nvd.nist.gov/vuln/detail/CVE-2015-3784) como exemplo. Portanto, é fundamental desativar a análise de entidades externas XML, se possível. Consulte a [folha de dicas de prevenção de XXE da OWASP](https://cheatsheetseries.owasp.org/cheatsheets/XML\_External\_Entity\_Prevention\_Cheat\_Sheet.html) para obter mais detalhes. Além das bibliotecas, você pode usar a classe [`XMLParser` da Apple](https://developer.apple.com/documentation/foundation/xmlparser)
|
|
|
|
Ao não usar bibliotecas de terceiros, mas o `XMLParser` da Apple, certifique-se de deixar `shouldResolveExternalEntities` retornar `false`.
|
|
|
|
{% hint style="danger" %}
|
|
Todas essas maneiras de serializar/codificar dados podem ser **usadas para armazenar dados no sistema de arquivos**. Nesses cenários, verifique se os dados armazenados contêm algum tipo de **informação confidencial**.\
|
|
Além disso, em alguns casos, você pode ser capaz de **abusar de alguns dados serializados** (capturando-os via MitM ou modificando-os dentro do sistema de arquivos) desserializando dados arbitrários e **fazendo com que o aplicativo execute ações inesperadas** (consulte a página de [desserialização](../../pentesting-web/deserialization/)). Nesses casos, é recomendável enviar/salvar os dados serializados criptografados e assinados.
|
|
{% endhint %}
|
|
|
|
## Referências
|
|
|
|
{% embed url="https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-object-persistence-mstg-platform-8" %}
|
|
|
|
|
|
|
|
<details>
|
|
|
|
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
|
|
|
- Você trabalha em uma **empresa de segurança cibernética**? Você quer ver sua **empresa anunciada no HackTricks**? ou você quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
|
|
|
- Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
|
|
|
- Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
|
|
|
|
- **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
|
|
|
- **Compartilhe suas técnicas de hacking enviando PRs para o [repositório hacktricks](https://github.com/carlospolop/hacktricks) e [hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)**.
|
|
|
|
</details>
|