Akamai Diversity

The Akamai Blog

HQL Statement Tampering

Executive Summary

"Hibernate is an object-relational mapping (ORM) library for the Java language, providing a framework for mapping an object-oriented domain model to a traditional relational database. Hibernate solves object-relational impedance mismatch problems by replacing direct persistence-related database accesses with high-level object handling functions." (Wikipedia)

According to a recent Java developer survey, Hibernate was ranked as the 2nd most popular Java framework.

When non-sanitized user input is embedded directly into an HQL (Hibernate Query Language) statement, a malicious hacker may trick the HQL parser into splitting a predefined statement into two separate strings, and to ignore the second string, thus manipulating the original HQL statement and subverting application logic.

The effect caused by this vulnerability is similar in nature to using SQL comment indicators for commenting out the rest of a query when performing SQL injection attacks, albeit the difference is that HQL does not provide a legitimate comment indicator similar to SQL. 

Description

The Hibernate project uses ANTLR as a parser generator for HQL syntax. ANTLR works by reading the grammar description file (.g file), and generating syntax-parsing code written in Java.

We have discovered that a software defect exists in the Hibernate project source file "HqlBaseParser.java", which is automatically generated from the ANTLR grammar file "hql.g".

This defect was verified to exist in Hibernate versions 3.6 and 4.2. Since it hasn't been fixed yet, we assume that it is still relevant for the latest Hibernate version (4.3.1).

The problem occurs when the HQL statement is transformed into an HQL AST (Abstract Syntax Tree). The transformation of HQL into the AST is separated into 4 main parsing steps:

  • SELECT clause
  • WHERE clause
  • GROUP clause
  • ORDER clause

In each of the steps above, the parser's code attempts to parse the relevant syntax tokens recursively. When the code fails to parse a specific token, it can take one of two actions:

  1. Throw an exception or
  2. Invoke a sub-layer in the recursion to process the current token

If none of the sub-layers in the recursion of the current step knows how to parse the syntax token at hand, the token parsing process continues to the next step.

During our research, we have discovered an incorrect behavior in the parser's logic. It appears that When the HQL syntax parser attempts to deal with the tokens ')' (closing parenthesis), and the 'UNION' reserved word, each of the logic layers in the parser's code doesn't know how to deal with these tokens, and it keeps getting forwarded to the next layer, but at the end - no layer raises an exception. This behavior causes the token processing to halt at that point in the statement, and the parser completely ignores these tokens and any strings after them.

As an example, lets take a look at the following HQL statements:

Photo 1 for Ory Blog.png
 In both statements, the HQL parser will completely ignore the keyword 'UNION' and ')' (closing parenthesis), and everything past them, basically commenting out the rest of the query.

This software defect has interesting security implications - the effect caused by this vulnerability is similar in nature to using SQL comment indicators for commenting out the rest of a query when performing SQL injection attacks, albeit the difference is that HQL does not provide a legitimate comment indicator similar to SQL.

Lets have a look at a snippet of Java code, which uses Hibernate, and is vulnerable to HQL tampering through the parser defect mentioned above:

Photo 2 for Ory Blog.png
In the example above, a malicious user may trick the application to log him/her in, as userId '1', by sending the userId value 1) - this will yield the following HQL statement:

Photo 3 for Ory Blog.png
Notice that the rest of the statement, which attempts to validate the user's password, was completely removed, thus bypassing the login mechanism. In addition, this injection attack may circumvent standard input sanitization routines that only look for common SQL Injection attack patterns, but completely disregard the ')' or UNION strings.

Mitigating factors 

Until a formal patch for Hibernate will be available, you can remediate this vulnerability by:

  • Using parameterized HQL queries (parameter binding) - this should be the standard practice for writing secure HQL queries, as presented in this article
  • Modify your hibernate.cfg.xml to use the classic query translator, by setting the following configuration value

Photo 4 for Ory Blog.png

Note: by default, this property is not set explicitly, which means it defaults to the value "org.hibernate.hql.ast.ASTQueryTranslatorFactory" 
 

Additional Information

Upon submitting this advisory to the RedHat Security Response Team (submitted on January 2013), and getting acknowledgement from them about the severity of the vulnerability, we managed to discover that one of the two parsing issues ("UNION") was already logged in the project's JIRA system, since September 20th, 2011. https://hibernate.onjira.com/browse/HHH-6672

As of today, more than a year later, the Hibernate development team hasn't started working on a patch for both attack vectors, and it's unclear whether or not this issue will be fixed in the near future, however, we did receive their approval to release this information to the public, in the hopes that it will raise awareness about this problem.

* This research was done together with Nadav Grossman.

Leave a comment