Database Security: Threats, Controls and Best Practices
Database security protects data from theft, misuse and loss. See the main threats, core controls, SQL injection defences and how load testing fits in.
What is database security?
Database security is the set of controls that protect a database and the data in it from unauthorised access, modification, deletion and theft. It combines technical measures (authentication, encryption, network isolation), operational habits (patching, auditing, tested backups) and policy (who may see which data, and for how long it is kept).
Databases are a prime target because they hold what attackers want in one place: customer records, credentials and payment-related data. The same controls also protect you from honest mistakes, such as a developer running a delete against production.
Common database threats
| Threat | What it looks like |
|---|---|
| SQL injection | User input changes the meaning of a query, for example ' OR 1=1 -- in a login form |
| Stolen or leaked credentials | A database password committed to a public repository or reused from another breach |
| Excessive privileges | The web app connects as an admin, so any bug in the app becomes a full database compromise |
| Exposed database | A database port open to the internet, often with default or no authentication |
| Unprotected backups | An unencrypted dump in a storage bucket that is readable by too many people |
| Insider misuse | An authorised user exports or changes data they should not |
| Resource exhaustion | Slow queries or too many connections make the database unavailable |
The core controls
Authentication
Give every person and service its own account, with no shared logins. Where your platform supports it, prefer short-lived, identity-based credentials over long-lived passwords. This is the same discipline as identity and access management for the rest of your stack.
Authorisation and least privilege
Each account gets only the permissions it needs. The application account should not own the schema or run administrative commands, and administrators should use separate accounts. A role-based permission list is a form of access control list.
Encryption in transit and at rest
Require TLS for every connection and refuse plain-text ones. Encrypt storage and backups so a stolen disk or snapshot is useless on its own. Encrypt especially sensitive fields separately if the database operator should not see them.
Network isolation
Keep the database in a private network. Applications reach it through private routes, and administrators through a VPN or bastion host. Restrict which sources the firewall or security group accepts.
Auditing, patching and backups
Log privilege changes, schema changes and bulk exports, and alert on unusual ones. Apply database and operating system patches on a regular schedule. Take encrypted backups, store a copy in a separate account or region, and test a restore, because a backup you have never restored is an assumption.
SQL injection: the classic failure
SQL injection happens when user input is built into a query string. The OWASP SQL Injection Prevention Cheat Sheet lists prepared statements (parameterised queries) as the primary defence, with allow-list validation for the parts that cannot be bound, such as table names or sort order, and warns that escaping is fragile. It also says application accounts should never have DBA or admin access.
# Vulnerable: input is concatenated into the query
query = f"SELECT * FROM users WHERE email = '{user_input}'"
cursor.execute(query)
# Safe: the driver sends the value separately from the SQL
cursor.execute("SELECT * FROM users WHERE email = %s", (user_input,))
ORMs parameterise by default, but raw-query escape hatches in them are a common way injection returns. Read the OWASP cheat sheet for the full list. Injection reaches the database through your API, so API security is database security too.
Handling sensitive data
- Passwords: store a slow salted hash (bcrypt, scrypt or Argon2), never the password or a reversible encryption of it.
- Personal and payment data: encrypt at column or application level, or tokenise it so the real value lives in a dedicated vault.
- Test and dev data: mask or synthesise it instead of copying production.
- Multi-tenant data: use row-level security where the engine supports it. In PostgreSQL, a table with row security enabled and no policy shows no rows to ordinary users, but table owners and superusers bypass it unless you force it.
Compliance in one paragraph
Rules such as GDPR, HIPAA, PCI DSS and SOC 2 each ask for access control, encryption, logging and incident response around the data they cover. Under GDPR Article 33, a personal data breach must be reported to the supervisory authority without undue delay and, where feasible, within 72 hours of becoming aware of it. Confirm with your own compliance advisers which rules apply to you.
Common mistakes
- Connecting the app as an admin because it makes setup easier.
- Copying production data into staging and leaving it unmasked.
- Never testing a restore.
- Leaving credentials in code, CI logs or container images instead of a secrets manager.
- Treating encryption as the whole answer. It does not stop injection or a stolen application password.
Database security, load testing and monitoring
LoadFocus does not scan for vulnerabilities, but performance work touches the same systems. A load test shows how your database behaves as concurrent users rise, for example when slow queries pile up or the connection pool runs dry (see how to optimise database connection pools). If you run it against a staging environment, use masked or synthetic data, as covered in cloud testing security best practices. API monitoring checks your database-backed endpoints on a schedule, so a failing or slow endpoint raises an alert instead of waiting for a customer report.
FAQ: database security
How do I prevent SQL injection?
Use parameterised queries or prepared statements for every query that includes user input, validate against an allow-list for identifiers that cannot be bound, and connect with an account that has only the permissions the app needs.
Should I encrypt at the application or the database layer?
Database-level encryption is simpler to run but the database can read the plain data. Application-level encryption keeps keys away from the database but makes searching and sorting harder. Highly sensitive fields often justify both.
What is the difference between encryption at rest and in transit?
At rest protects stored data, such as disks and backups. In transit protects data on the network between the application and the database. You need both.
Can I expose my database to the internet?
Almost never. Keep it in a private network and allow only your application servers and a controlled admin path to reach it.
What is row-level security?
A database feature that filters which rows a user can read or change, based on policies you define. It is useful for multi-tenant applications as a second line of defence behind application checks.
How do I notice a database breach?
Audit logs plus alerts on odd behaviour: bulk exports, queries at unusual hours, new privileged accounts, and schema changes outside a planned change window.
Related terms
Related LoadFocus Tools
Put this concept into practice with LoadFocus, the same platform that powers everything you just read about.