What Laravel's encrypted casts can protect you from
The other week I asked a very pointy question on the PHP Australia Slack channel:
Real talk, is encrypted casting security theater?
My question was half genuine confusion, and half Cunningham’s Law.
Encrypted casting is a feature in Laravel’s Eloquent ORM which allows us to very transparently encrypt a value in one database column of a model. This encryption happens in the PHP code, using the global app key.
The encryption happens inside the ORM layer, so our app code doesn’t even need to know about it. It felt so transparent, to me, that it may as well not exist.
-
Our entire database is already encrypted at rest, which protects against somebody walking out of the AWS datacenter with a hard drive.
-
Our app servers’ connections to the database are encrypted in-flight, so observers of the network can’t snoop on that traffic.
Beyond that, and of course the usual high standard of security that app servers are held to to prevent SQL injection or other vulnerabilities, I wasn’t seeing the benefit of encrypting specific colums more. But the good folks of PHP Australia provided me with some great insight into what other threats this feature can mitigate.
-
The biggest one I overlooked was SQL injection. If an app had an SQL injection vulnerability, an attacker might be able to perform arbitrary queries against the database, but not arbitrary code execution. Therefore they’d be able to access unencrypted data, but not the encrypted columns.
-
Another good point was systems which aren’t our app which could access the same database. For example, our business intelligence dashboard or other analytics systems. Their trust model is different to that of our application; encryption which is transparent to our app and therefore seems “too easy”, is very opaque to these other systems!
-
Finally, our own staff could, even inadvertently, be a risk to the data. Adding this extra layer of encryption of the most sensitive data protects against accidental disclosure, since access to the
APP_KEY
is extremely tightly controlled. This might not protect us against bugs in the code, but could catch ops errors or other mistakes.
Thanks to Andrew, Pat, valorin, James and Samuel for helping me think through this. I appreciate your patient explanations!