It’s still not perfect because an attacker can potentially send requests to the key management server, but they shouldn’t be able to walk away with they keys to perform decryption outside of the system.
You then set up monitoring to watch how many decryption operations are being performed per minute or hour and alert admins when it steps outside of normal useage patterns.
It’s not perfect but can help you to 1) catch an attacker early and 2) have some type of estimate of the size of the breach when discovered. A very patient attacker may not trigger an alarm of decryption operations but in that case he’s got to work much slower, which limits the scope of the attack while they hopefully trigger something else that exposes them.
The gist is you create an encryption key for your row, encrypt it using your encryption service, and store it next to your actual payload. To decrypt, ask the service to decrypt the key which you use to decrypt the payload. If your database gets popped, your decryption server hopefully didnt because you hardened it specifically.
Envelope encryption is a good scheme. Under envelope encryption you have a master key and per-row or per-unit keys. You store the per-unit keys encrypted with the master key, and the master key is stored offsite.
For example on an AWS environment, you would use AWS KMS with IAM authentication to handle the master key crypt for the individual keys, and the encrypted versions of the individual keys are stored in a database that you own.
You encrypt your data with the individual keys (eg, one key per user, or one key per DB row, or one key per namespace, whatever), but the individual keys are decryptable only by KMS.
Under this scheme an attacker must both be able to get ahold of the encrypted individual keys, and be able to decrypt them with the master key.
Of course this leaves you very vulnerable if the master key is acquired, but KMS does not allow you to read the master key at all, you have to use the AWS API to make encryption/decryption requests. So the vulnerability is less about how secure the key is and more about how secure your IAM setup and instances are.
Or are we assuming that the decryption service enforces some policy about what and how much to decrypt?
But you're also forgetting that most data breaches in real life involve database backups, staging servers, development environments, and people with access. So envelope encryption really helps prevent those. Even if someone gets a hand on your DB dump they're unable to use it without authorization to the KMS, which they won't have unless they can also get into your application server.
Don't forget that data is most often leaked by people. DB backups, dev environments, inappropriate transfers. We hear about the big targeted attacks, but probably 90% of actual breaches are due to human misuse.
If you don't need to decrypt the data on the same system, you could always use asymmetric encrpytion, so encrypt with the "public" key and then keep the private key elsewhere.
If you require to be able to decrypt on the system in question then you need a key somewhere, so secure storage of the key is very important.
One option, often deployed in banks, is to store the key in a hardware security module (HSM) and then ensure that it's not available outside of that.
There's a load of tradeoffs to using HSMs but they can be useful where symmetric encrpytion is needed.
Amazon and Azure offer these in the cloud.
An attacker that compromised the customer facing application only has access to tokens and would be forced to access sensitive data via the data bunker. That application is heavily monitored and would hopefully be quickly noticed.
The HSM adds an additional layer of protection against loss of sensitive data via backup tapes or some insider attacks.
Physically separate the key storage from the data storage. Different servers, different user auth mechanism. Make them compromise both systems.
Unique keys per client.
Use key-encrypting keys, periodically replace them.
PCI environment must be totally self contained and not mixed with standard working environment. If an employee is phished, their credentials for email/etc should not gain access to the env.
Don't allow developers to deploy or even read from prod db. Have a separate deployment team, all access to prod database audited via production tickets.
Assuming a layered system, something like Vault transit encryption (perhaps with the master key in an HSM) should keep decryption keys away from front-end machines, though as ever, once you have root and can access the memory of a machine where the encryption keys are stored, most bets are off.
The general idea is to insert some kind of bogus information into a system, with no links to other systems, and then trigger a notification if someone accesses it.
You are already fucked at this point. I would focus my attention on prevent hackers from 1) gaining any unauthorized access. 2) from doing any sort of privilege escalation from a restricted account/service.