Safeguard
Application Security•

CWE-564 SQL Injection in Hibernate: Cause and Fix

Hibernate does not protect you if you build HQL with string concatenation. See how CWE-564 happens and how to fix it with bound parameters.

Safeguard Security Team
4 min read

CWE-564 is SQL injection through Hibernate. A developer builds a dynamic query from user input, and an attacker changes what the query means.

A lot of Java teams assume an ORM makes injection impossible. It does not. Hibernate runs whatever query string you hand it. If that string was assembled with concatenation, the ORM is just a longer path to the same bug.

MITRE lists the platforms as SQL and database servers, with Hibernate as the context in the name.

How it happens

Hibernate offers HQL, a query language that resembles SQL. If you build HQL by joining strings, user input becomes part of the query grammar.

MITRE's example uses this pattern:

// Vulnerable: user input concatenated into HQL
String street = getStreetFromUser();
Query query = session.createQuery(
    "from Address a where a.street='" + street + "'");

A normal value like Main St works. A value such as x' or '1'='1 changes the where clause so it matches every row. More elaborate input can reach other tables or run additional statements, depending on the database and driver.

The same mistake appears with the criteria API when raw restrictions are used, and with native SQL queries created through the session. The language of the query is different. The cause is not.

Client side checks do not help. MITRE notes that attackers can bypass them by editing values after the checks run, or by changing the client entirely.

What an attacker gains

MITRE lists confidentiality and integrity impact: reading application data and modifying application data.

In practice that means:

  • Reading rows the user should never see, such as other customers' records.
  • Changing or deleting data.
  • Bypassing login logic that relies on a query returning a row.
  • Learning the schema, which makes later attacks easier.

The attacker works through your application's database account, so the damage is bounded by that account's privileges. That is why least privilege matters here.

How to find it

The record has no detection list for this entry, so lean on general practice for injection.

  • Search the code. Look for createQuery, createSQLQuery and createNativeQuery calls where the argument contains a + or a formatted string.
  • Static analysis. SAST tools trace user input to query sinks and flag concatenation.
  • Dynamic testing. Send quote characters and boolean payloads to every input that feeds a search or filter and watch for errors or changed results.
  • Review logs. Query errors with unexpected quote characters are a signal.

How to fix it

MITRE's mitigations for this entry, in plain steps:

  1. Use prepared statements that bind variables. MITRE warns that prepared statements which do not bind variables can still be vulnerable. Binding is the point.
  2. Use allowlist checking on input. Rather than escaping metacharacters, define the narrow set of safe characters for the expected value and reject the rest.
  3. Apply least privilege to database accounts. If users may only read and modify their own data, the account should not be able to touch other data where the design allows it.
  4. Duplicate client side checks on the server. Anything checked in the browser must be checked again on the server.
  5. Where requirements allow, consider a non-SQL database that is not subject to this flaw.

The fix in code is a named parameter:

// Fixed: bound parameter
Query query = session.createQuery(
    "from Address a where a.street = :street");
query.setParameter("street", street);

Hibernate sends the value separately from the query text, so quote characters are data, not syntax.

Do not build the fix out of manual escaping. It is easy to miss a case, and the database layer behaves differently across vendors.

ORMs are also dependencies. Hibernate itself has had its own advisories over the years, so the version in your build matters as well as the way you call it. The free scan at gold.safeguard.sh/scan lists the libraries in a manifest with no login, keeps your file on your machine, and handles up to 100 dependencies.

Try it yourself

Click through it at your own pace, or open it full screen.

Quick check

Does using Hibernate prevent SQL injection?

No. If you build HQL or native SQL by concatenating user input, you are vulnerable. Bound parameters are what protect you.

Is a prepared statement always safe?

Only if variables are bound. MITRE notes that prepared statements that do not bind variables can still be attacked.

Why limit database account privileges?

If an injection still slips through, the attacker is limited to what the account can do.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.