OWASP Tip: A02:2021 – Cryptographic Failures
Greetings friends! I hope you learnt a lot from last week’s In Depth covering the first OWASP Top 10 risk, A01:2021 - Broken Access Control, which kicked off our OWASP Top 10 Series. This week we’re covering the second risk in the Top 10: A02:2021 – Cryptographic Failures. Unlike last week, we won’t be diving into it in detail, but rather I want to give you a checklist of sorts that you can work through in your apps, to ensure you’re using cryptography properly to secure your apps.
Subscribe to Laravel Security in Depth now, so you don’t miss out on each email in the OWASP Top 10 series!
👉 Thinking about a Security Audit or need a Penetration test?
🕵️ I’d love to work with you and secure your project!
Looking to learn more?
⏩ Security Tip #4: Parameterised Queries
▶️ In Depth #1: Encryption
A02:2021 – Cryptographic Failures
The second risk in the OWASP Top 10 is Cryptographic Failures. This risk used to be called “Sensitive Data Exposure”, but that never really made sense to me as that can happen across multiple risks, not just cryptographic failures, so it’s great to see that they’ve clarified the name in the latest version.
Before we can talk about preventing cryptographic failures, we need to understand what they are. Cryptography is used to protect information from being observed in some way, and comes in two main forms in our apps: encryption and hashing.
We use encryption to protect information that needs to be accessed again, such as encrypting encrypting values in the database, or the connecting between our servers and the browser through TLS certificates and the HTTPS protocol. We dived into Encryption in In Depth #1.
We use hashing in two ways, to protect information from being accessed while still allowing it to be compared (i.e. passwords), and also to prevent information from being modified that the user has access to (i.e. signed routes).
Both encryption and hashing are complex cryptographic functions, and both are fully supported in Laravel through easy-to-use helpers and features, so you’ve got no excuse not to take advantage of them! Laravel itself uses cryptography in a lot of different areas to keep your site secure, so you don’t even need to think about it a lot of the time. Consider cookies, which are encrypted to prevent tampering, and the auth scaffolding uses password hashing by default.
The official OWASP guide provides a list of areas to check for cryptographic requirements, so go check that out if you want to dive deeper. For this email, I’ve distilled OWASP’s advice and added my own recommendations into the following checklist, which you can use to check you’re avoiding cryptographic failures in your apps.
Avoiding Cryptographic Failures Checklist
Always require HTTPS.
This should be done at the webserver level so port 80 should automatically forward to 443 without ever hitting your application. If your application is generating
"http://"links, you can force HTTPS through
Enable HTTP Strict Transport Security (HSTS)., there is no reason not to implement some level of HSTS.
HSTS tells the browser to require HTTPS for all connections, preventing downgrade attacks and insecure connections from leaking information. Unless your site requires HTTP to function
Enable the 'Secure' flag on site cookies.
secureflag ensures the cookie is only sent over HTTPS connections.
Replace all instances of MD5, SHA-1, etc, with a secure hashing algorithm suitable for the task.
BCrypt or Argon2 are best for hashing passwords, and algorithms like SHA-256 are good for hashing content and signatures.
Ensure encryption keys are unique per application, and use different keys for different content.
Don’t share the keys between environments and don’t commit them! If you use Eloquent encryption casting, you can use a custom key.
Use cryptographically secure randomness generators.
Always use methods like
Str::random()to generate random values.
Only store data you need to store.
Avoid collecting unnecessary data, especially when it comes to PIIand financial data. The less data you have stored, the less that can be leaked.
Use encryption-at-rest on databases, sensitive fields, etc.
Also consider encrypting uploaded files if they contain sensitive data.
Don’t roll your own crypto.
An old saying, but still very relevant. Try to avoid building your own implementation, but instead reach for existing tools, such as Laravel’s Signed URLs.
Follow best practices.
If you need to build your own implementation for something, look for best practices and follow them. Cryptography is not easy, and it’s easy to overlook subtle nuances that can leave your implementations wide open to compromise.
That’s it for our checklist, I hope you find it helpful!
Please leave a comment if you’d like me to clarify any of the points or dig a bit deeper. Also check out the OWASP page, and dig into their resources.
And if it does, I would be really interested to learn why!
Personally Identifiable Information
Australian readers will know exactly what I’m referring to here!
As I wrote this line I realised I needed to add this to my list for a future Tip/In Depth!