I understand SQLCipher has good encryption. However, if your Android App passes the SQLCipher key on SQLiteDatabase.openOrCreateDatabase call, then the attacker can see the Java code and get the key. Then he would use SQLCipher by himself using the same key (even the key is internally hashed and is not the real key, it is the only input needed here).
Is there a way to better hide the key? Say, if I could set the key from native code, then it would be harder to find the key by static analysis.
So I would call openOrCreateDatabase, get the db handler and pass it to C code through JNI. From C, I would generate a new key and then call sqlite3_key(db_handl, new_key, len);
Is this possible? How to get the db_handler from Java?
We don’t recommend hardcoding the key into an application, as it’s just not suitable for any secure implementation. No matter what you do, if the key is hardcoded and the attacker has the installation package, they will be able to find it and use it to access the data, no matter how well you obfuscate it.
SQLCipher is really intended to be used where key material is not included in the application package (i.e. not for use as DRM). In this model the key material comes from somewhere else (e.g. from the user in the form of a pin or password, or from some other means like a key service, secure keystore, etc.)
we take reference of this link for security purpose.
we getting the key from the .so file, by the support of ndk.
in this link it provide file detail for generating the .so file.
first, we need to create jni folder, then create 3 files with named respectively “Android.mk”,“Application.mk”,“sqlndk.c”.
you have to create new “.so” file using nkd-build command from terminal.
Please note that the article you reference shows one of several possible ways to disassemble a native library that contains the source of the password. Anytime you store the password anywhere the potential of a security breach increases. The amount of security necessary for any given application should of course be considered when discussing key management options.
Want to raise this topic. Was very disappointed with this article: Recovering SQLCipher encrypted data with Frida - Ackcent Although I’m not storing key on the device, looks like interception of the key on openOrCreateDatabase is not only possible but easy. Please suggest whether this is true, and maybe what are the options to protect in this case?
Hello @Eli_Petukhov - the article you pointed to demonstrates a very limited attack, primarily focused on intercepting a key from an application that hides key material from the user (e.g., an application with a DRM-style use case). Because Frida requires a rooted device, a repackaged app, or execution under a debugger, it is not easily usable for attacking user-provided keys. This is also noted in the article’s conclusion, which acknowledges that our recommendation to generate a substantial part of the key material with user-provided data mitigates this risk.
Hi @sjlombardo! Thanks for the prompt and detailed response! You are right, the article says about the limitations. Unless we have a rooted device, all is good. But in case when we have rooted device, nothing will help to what I understand - even user-provided key will be intercepted in openOrCreateDatabase call.
My current options to mitigate this risk are:
use PRAGMA KEY instead of the api call above (assumption is that it is easier to find this library call)
rely on vendor-specific integrity checks (Google Play Integrity / Apple DeviceCheck) to validate against rooted devices
I understand that on rooted device it all depends on qualification of attacker, and nothing will help against the best ones, but maybe there are some other options to consider besides the above?
Hello @Eli_Petukhov - Even on a rooted device, attacking data encrypted with a user-provided key using Frida would be hard. Frida still needs to be deployed by connecting the device to a workstation, pushing the Frida server via ADB, and starting it with root privileges. An attacker would either need to trick a technically savvy user into completing these steps or run them through another privileged process. This significantly reduces the practicality of this attack.
The post in question discusses a useful technique, but it overstates the general applicability of the attack and doesn’t adequately address the limitations until the last paragraph. It really applies best to a scenario where the application is hiding the data from a user. For instance, a developer has a “secret” data set that will be stored on device but they don’t want to allow the user direct access. The developer might encapsulate the data in an encrypted SQLCipher database, using a key unknown to the user (e.g. static or derived from on-device values).
Here the application is inherently treating the encrypted databases as a form of DRM, which we explicitly recommend against doing. Certainly, using Frida to hook and extract key material or data would be a lot quicker and easier than reverse-engineering the application though, especially for a penetration tester like the author.
In terms of mitigations, user-provided key material is the best protection and validating against rooted devices is another good layer of defense. However, using PRAGMA key instead of openOrCreateDatabase would only add minor difficulty. Frida could simply be used to hook statement execution functions instead to grab the PRAGMA statement.
In general, for applications that use SQLCipher as recommended, and implement good secure practices for key material, the threat of an attack using Frida is greatly reduced and probably shouldn’t be a significant concern.