9.4 KiB
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.
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
, você precisa incluir:
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:
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:
// 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
:
// 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:
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.
Você também pode usar o codable para salvar os dados na lista de propriedades primárias NSUserDefaults
:
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). No entanto, a Apple fornece suporte para codificação/decodificação JSON diretamente combinando Codable
com um JSONEncoder
e um JSONDecoder
:
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, Ono, AEXML, RaptureXML, SwiftyXMLParser, 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 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 para obter mais detalhes. Além das bibliotecas, você pode usar a classe XMLParser
da Apple
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). 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" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
-
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!
-
Descubra A Família PEASS, nossa coleção exclusiva de NFTs
-
Adquira o swag oficial do PEASS & HackTricks
-
Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-me no Twitter 🐦@carlospolopm.
-
Compartilhe suas técnicas de hacking enviando PRs para o repositório hacktricks e hacktricks-cloud repo.