Database Security
Prerequisites: Using SQL from application code, Views
Databases hold an organization's most valuable data. A handful of practices prevent most breaches.
1. Prevent SQL injection — always use parameters
Covered in the Application Code lesson, and worth repeating: never build SQL by concatenating user input. Use parameterized queries or an ORM. This one habit prevents the most common database attack.
2. Least privilege
Each application and person should get only the permissions they need:
-- PostgreSQL
CREATE ROLE reporting_app LOGIN PASSWORD '...';
GRANT CONNECT ON DATABASE shop TO reporting_app;
GRANT USAGE ON SCHEMA public TO reporting_app;
GRANT SELECT ON orders, order_items, products TO reporting_app;
-- no INSERT, UPDATE, DELETE, and no access to customers
- A reporting tool needs
SELECT, notDELETE. - The web application's account shouldn't be able to
DROP TABLE. - Never let applications connect as the superuser (
postgres,root,sa).
If an attacker does find a way in, least privilege limits the damage.
3. Restrict what users can see
- Views can expose only some columns — for example, customers without
email addresses — with
SELECTgranted on the view instead of the table. - Row-level security (PostgreSQL, SQL Server) restricts which rows a user sees — for example, each tenant only sees their own data:
-- PostgreSQL
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON orders
USING (tenant_id = current_setting('app.tenant_id')::int);
4. Protect sensitive data
- Passwords — never store them in plain text or with fast hashes like MD5 or SHA-256. Store a slow, salted hash (bcrypt, Argon2) computed by the application.
- Encryption in transit — require TLS for database connections.
- Encryption at rest — for disks and backups, usually provided by the platform.
- Minimize — don't store data you don't need; mask or remove personal data in development and test copies.
5. Secure operations
- Keep the database off the public internet; allow connections only from the application's network.
- Keep credentials in a secrets manager or environment variables, never in source code.
- Keep the database software patched.
- Log and review access to sensitive tables.
- Test that backups can actually be restored (next lessons).