Does MariaDB provides asymmetric key encryption - encryption

I learned about the table encryption for MariaDB here.
However, it seems the keys are located in a single file in a way an attacker could easily decrypt the data by having read access on the filesystem.
Assuming that it can be safer, I would like to encrypt database depending on one public key, and connect to the database through a private key file stored on my side.
Is that in any way possible?

It is typical that encryption just moves the problem. It is possible to protect the key in storage but not easy or cheap and it is virtually impossible to protect it in RAM when being used by the DB.
Solutions to protecting the key in storage include moving it to an HSM or another more secure and limited access system that provides the key to the DB over a secure link.
One advantage is that is the DB is obtained without the key it is secure, the problem is that the same access can also provide the key to the attacker. The work factor has increased and that may meet the security needs.

Related

Is it okay to encrypt sqlite3 database with GnuPg?

I've been playing around with coding up a small password management command line utility in Python. Mostly just for fun, and probably nothing I would ever actually use since I already use established tools for this task.
The program stores site, user name, and password in a sqlite database, and provides various options for looking up passwords, accounts, etc. I was looking for a way to encrypt the sqlite database, because passwords, and I came across sqlcipher. I had trouble building it on mac os, and gave up on that pretty quickly. I decided to try just encrypting the database with GnuPg. From a usage stand point it seems to work well. I wrote a small wrapper in bash that quickly decrypts the database before any operation is done on it, and the re-encrypts it when its done. Is this an acceptable method for encrypting a sqlite database? I can't really find any other examples online of sqlite databases being encrypted this way.
Is this an acceptable method for encrypting a sqlite database?
If you consider it acceptable yes, others may or may not.
However, from a security point of view, probably not if you are decrypting the database file to use it and then encrypting it after use, as the decrypted version could be available and be accessed. The SEE (SQLite Encryption Extension) only decrypts to memory and then only partial data rather than the entire file, so would be more secure from the aspect of security.
How SEE Works
Each page is encrypted separately. The key to encryption
is a combination of the page number, the random nonce (if any) and the
database key. The data is encrypted in both the main database and in
the rollback journal or WAL file but is unencrypted when held in
memory. This means that if an adversary is able to view the memory
used by your program, she will be able to see unencrypted data.
An alternative would be to store encrypted values, decrypting each as they are extracted, this would then equate to the decrypted value(s) only being in-memory. This could have the potential benefit of multiple key phrases (say for multiple users). Thus there would be no single key that unlocks all data.

DPAPI Key Storage and Restoration

In light of the upcoming GDPR regulations, the company I work for is looking at upgrading their encryption algorithms and encrypting significantly more data than before. As the one appointed to take care of this, I have replaced our old CAST-128 encryption (I say encryption but it was more like hashing, no salt and resulting in the same ciphertext every time) with AES-256 and written the tools to migrate the data. However, the encryption key is still hardcoded in the application, and extractable within a couple of minutes with a disassembler.
Our product is a desktop application, which most of our clients have installed in-house. Most of them are also hosting their own DBs. Since they have the entirety of the product locally, securing the key seems like a pretty difficult task.
After some research, I've decided to go with the following approach. During the installation, a random 256-bit key will be generated for every customer and used to encrypt their data with AES encryption. The key itself will then be encrypted with DPAPI in user mode, where the only user who can access the data will be a newly created locked down domain service account with limited permissions, who is unable to actually log in to the machine. The encrypted key will the be stored in an ACL-ed part of the registry. The encryption module will then impersonate that user to perform its functions.
The problem is that since the key will be randomly generated at install time, and encrypted immediately, not even we will have it. If customers happen to delete this account, reinstall the server OS, or manage to lose the key in some other manner, the data will be unrecoverable. So after all that exposition, here comes the actual question:
I am thinking of having customers back up the registry where the key is stored and assuming that even after a reinstall or user deletion, as long as the same user account is created with the same password, on the same machine, it will create the same DPAPI secrets and be able to decrypt the key. However, I do not know whether or not that is the case since I'm not sure how these secrets are generated in the first place. Can anyone confirm whether or not this is actually the case? I'm also open to suggestions for a completely different key storage approach if you can think of a better one.
I don't see the link with GDPR but let's say this is just context.
It takes more than the user account, its password and the machine. there is more Entropy added to the ciphering of data with DPAPI.
See : https://msdn.microsoft.com/en-us/library/ms995355.aspx#windataprotection-dpapi_topic02
A small drawback to using the logon password is that all applications
running under the same user can access any protected data that they
know about. Of course, because applications must store their own
protected data, gaining access to the data could be somewhat difficult
for other applications, but certainly not impossible. To counteract
this, DPAPI allows an application to use an additional secret when
protecting data. This additional secret is then required to unprotect
the data. Technically, this "secret" should be called secondary
entropy. It is secondary because, while it doesn't strengthen the key
used to encrypt the data, it does increase the difficulty of one
application, running under the same user, to compromise another
application's encryption key. Applications should be careful about how
they use and store this entropy. If it is simply saved to a file
unprotected, then adversaries could access the entropy and use it to
unprotect an application's data. Additionally, the application can
pass in a data structure that will be used by DPAPI to prompt the
user. This "prompt structure" allows the user to specify an additional
password for this particular data. We discuss this structure further
in the Using DPAPI section.

Encrypting the database at rest without paying?

Right now the only way to encrypt a Cassandra database at rest seems to be with their enterprise edition which costs thousands of dollars: How to use Cassandra with TDE (Transparent Data Encryption)
Another solution is to encrypt every value before it enters the database, but then the key will be stored somewhere on every server in plaintext and would be easy to find.
I understand they offer "free" use for certain companies, but this is not an option and I am not authorized to pay $2000/server. How do traditional companies encrypt their distributed databases?
Thanks for the advice
I took the approach of encrypting the data disk on AWS. I added a new volume to the instance and checked the option to encrypt the volume. Then I edited cassandra.yaml to point to the encrypted volume.
We have done similar requirement in one of our project. Basically, I made use of trigger feature in Cassandra with custom implementation to perform encryption. It seems to be working fine for us.
You can refer below docs on how to create trigger and sample implemention of ITrigger interface
https://docs.datastax.com/en/cql/3.3/cql/cql_reference/cqlCreateTrigger.html
https://github.com/apache/cassandra/blob/2e5847d29bbdd45fd4fc73f071779d91326ceeba/examples/triggers/src/org/apache/cassandra/triggers/AuditTrigger.java
Encrypting before inserting is a good way. The keys will either be on each application or on each cassandra node. There isnt much difference really, either way you should use filesystem permissions to restrict access to key just the apps user. Theres steps to get more secure from there like requiring entering of passphrase on startup vs storing on disk, but it makes operational tasks horrific.

EncryptByKey versus EncryptByPassPhrase?

What are your thoughts about SQL Server's symmetric key functions? Specifically, I have two questions:
Which set of functions is better... EncryptByKey or EncryptByPassPhrase?
Both functions require a passphrase of some kind. In a typical web-application architecture, where should this passphrase be stored? (i.e., hard coded within a stored procedure in the database, or stored as a configuration setting in the web application)
I'm eager to see what the best practice is for these functions.
Encrypting using a passphrase is easier but the advantage of using a key is that the key can be secured using built in SQL sever roles. You can lock down use of the key to only those users that require access to that data.
If you use a certificate then you only need plain text during the initial setup and can store it outside your system. Again, the certificate is a securable object and can be locked down.
Hope this helps.

Best Practice: Protecting Personally Identifiable Data in a ASP.NET / SQL Server 2008 Environment

Thanks to a SQL injection vulnerability found last week, some of my recommendations are being investigated at work. We recently re-did an application which stores personally identifiable information whose disclosure could lead to identity theft. While we read some of the data on a regular basis, the restricted data we only need a couple of times a year and then only two employees need it.
I've read up on SQL Server 2008's encryption function, but I'm not convinced that's the route I want to go. My problem ultimately boils down to the fact that we're either using symmetric keys or assymetric keys encrypted by a symmetric key. Thus it seems like a SQL injection attack could lead to a data leak. I realize permissions should prevent that, permissions should also prevent the leaking in the first place.
It seems to me the better method would be to asymmetrically encrypt the data in the web application. Then store the private key offline and have a fat client that they can run the few times a year they need to access the restricted data so the data could be decrypted on the client. This way, if the server get compromised, we don't leak old data although depending on what they do we may leak future data. I think the big disadvantage is this would require re-writing the web application and creating a new fat application (to pull the restricted data). Due to the recent problem, I can probably get the time allocated, so now would be the proper time to make the recommendation.
Do you have a better suggestion? Which method would you recommend? More importantly why?
Encryption in SQL is really only good for securing the data as it rests on the server, although that doesn't mean that it is unimportant. When you mention that a prime concern is injection attacks or the likes, my concern would be whether or not the database uses a single account (SQL or otherwise) to connect to the database, which would be common for a public internet site. If you use integrated authentication, or connect to SQL using the same credentials supplied to the application, then SQL's encryption might work fine.
However, if you're using a single login, SQL's encryption is going to manage encrypting and decrypting the data for you, based on your login. So, if your application is compromised, SQL may not be able to protect that data for you, as it implicitly decrypts it and doesn't know anything is wrong.
You may want to, as you suggested, encrypt/decrypt the data in the application, and store as bytes in the database. That way you control who can decrypt the data and when (for example, you could assign the key to decrypting this data to those few employees you mentioned that are in a specific role). You could look into Microsoft's Security Application Block, or Bouncy Castle, etc. for good encryption utilities. Just be careful about how you manage the key.
Update:
Although you could potentially use two connection strings: one normal, with no rights to the encrypted data, and one that has the key and the rights to the data. Then have your application use the appropriate connection when the user has the rights. Of course, that's pretty kludgy.
Some practices that we follow:
Never use dynamic sql. It's completely unnecessary.
Regardless of #1, always parameterize your queries. This alone will get rid of sql injection, but there are lots of other entry points.
Use the least priviledged account you can for accessing the database server. This typically means the account should NOT have the ability to run ad hoc queries (see #1). It also means that it shouldn't have access to run any DDL statements (create, drop, ..).
Don't trust the web application, much less any input received from a browser. Sanitize everything. Web App servers are cracked on a regular basis.
We also deal with a lot of PII and are extremely strict (to the point of paranoia) on how the data is accessed and by whom. Everything that comes through the server is logged. To make sure this happens we only allow access to the database through stored procedures. The procs always test to see if the user account is even authorized to execute the query. Further they log when, who, and what. We do not have any mass delete queries at all.
Our IDs are completely non-guessable. This is for every table in the system.
We do not use ORM tools. They typically require way too much access to the database server to work right and we just aren't comfortable with that.
We do background checks on the DBA's and our other production support people every 6 months. Access to production is tightly controlled and actively monitored. We don't allow contractors access to production for any reason and everything is code reviewed prior to being allowed into the code base.
For the encrypted data, allow specific users access to the decryption keys. Change those keys often, as in once a month if possible.
ALL data transfer between machines is encrypted. Kerberos between servers and desktops; SSL between IIS and browsers.
Recognize and architect for the fact that a LOT of data theft is from internal employees. Either by actively hacking the system, actively granting unauthorized users access, or passively by installing crap (like IE 6) on their machines. Guess how Google got hacked.
The main question in your situation is identifying all of the parts that need access to the PII.
Things like how does the information get into your system? The main thing here is where does the initial encryption key get stored?
Your issue is key management. No matter how many way's you turn the problem around, you'll end up with one simple elementary fact: the service process needs access to the keys to encrypt the data (is important that is a background service because that implies it cannot obtain the root of the encryption hierarchy key from a human entered password whenever is needed). Therefore compromise of the process leads to compromise of the key(s). There are ways to obfuscate this issue, but no ways to truly hide it. To put this into perspective though, only a compromise of the SQL Server process itself could expose this problem, something which is significantly higher bar than a SQL Injection vulnerability.
You are trying to circumvent this problem by relying on the public key/private key asymmetry and use the public key to encrypt the data so that it can only be decrypted by the owner of the private key. So that the service does not need access to the private key, therefore if compromised it cannot be used to decrypt the data. Unfortunately this works only in theory. In the real world RSA encryption is so slow that is cannot be used for bulk data. This is why common RSA based encryption scheme uses a symmetric key to encrypt the data and encrypts the symmetric key with the RSA key.
My recommendation would be to stick with tried and tested approaches. Use a symmetric key to encrypt the data. Use an RSA key to encrypt the symmetric key(s). Have SQL Server own and control the RSA private key. Use the permission hierarchy to protect the RSA private key (really, there isn't anything better you could do). Use module signing to grant access to the encryption procedures. This way the ASP service itself does not even have the privileges to encrypt the data, it can only do so by the means of the signed encryption procedure. It would take significant 'creative' administration/coding mistakes from your colleagues to compromise such a scheme, significantly more than a mere 'operator error'. A system administrator would have an easier path, but any solution that is designed to circumvent a sysadmin is doomed.

Resources