MASTG-KNOW-0096: Bancos de Dados Realm
Realm Objective-C e Realm Swift não são fornecidos pela Apple, mas ainda assim merecem destaque. Eles armazenam todos os dados não criptografados, a menos que a configuração tenha a criptografia habilitada.
O exemplo a seguir demonstra como usar criptografia com um banco de dados Realm:
// Abre o arquivo Realm criptografado, onde getKey() é um método para obter uma chave do Keychain ou de um servidor
let config = Realm.Configuration(encryptionKey: getKey())
do {
let realm = try Realm(configuration: config)
// Use o Realm normalmente
} catch let error as NSError {
// Se a chave de criptografia estiver incorreta, `error` indicará que é um banco de dados inválido
fatalError("Erro ao abrir o realm: \(error)")
}
O acesso aos dados depende da criptografia: bancos de dados não criptografados são facilmente acessíveis, enquanto os criptografados exigem uma investigação sobre como a chave é gerenciada — seja ela embutida no código (hardcoded), armazenada sem criptografia em um local inseguro, como preferências compartilhadas (shared preferences), ou de forma segura no KeyStore da plataforma (que é a melhor prática). No entanto, se um invasor tiver acesso suficiente ao dispositivo (por exemplo, acesso com jailbreak) ou puder reempacotar o aplicativo, ele ainda poderá recuperar chaves de criptografia em tempo de execução usando ferramentas como o Frida. O seguinte script do Frida demonstra como interceptar a chave de criptografia do Realm e acessar o conteúdo do banco de dados criptografado.
function nsdataToHex(data) {
var hexStr = '';
for (var i = 0; i < data.length(); i++) {
var byte = Memory.readU8(data.bytes().add(i));
hexStr += ('0' + (byte & 0xFF).toString(16)).slice(-2);
}
return hexStr;
}
function HookRealm() {
if (ObjC.available) {
console.log("ObjC está disponível. Tentando interceptar classes do Realm...");
const RLMRealmConfiguration = ObjC.classes.RLMRealmConfiguration;
Interceptor.attach(ObjC.classes.RLMRealmConfiguration['- setEncryptionKey:'].implementation, {
onEnter: function(args) {
var encryptionKeyData = new ObjC.Object(args[2]);
console.log(`Comprimento da Chave de Criptografia: ${encryptionKeyData.length()}`);
// Exibe o conteúdo hexadecimal da chave de criptografia
var encryptionKeyBytes = encryptionKeyData.bytes();
console.log(hexdump(encryptionKeyBytes, {
offset: 0,
length: encryptionKeyData.length(),
header: true,
ansi: true
}));
// Converte os bytes da chave de criptografia para uma string hexadecimal
var encryptionKeyHex = nsdataToHex(encryptionKeyData);
console.log(`Chave de Criptografia em Hexadecimal: ${encryptionKeyHex}`);
},
onLeave: function(retval) {
console.log('Saindo de RLMRealmConfiguration.- setEncryptionKey:');
}
});
}
}