ORM Injection

Deepak Raj
4 min readDec 10, 2021

My previous blog is all about ORM. If u haven't check that out please read about it

So this blog is all about Object Relational Mapping Injection

Introduction

Object Relational Mapping (ORM) Injection is an attack using SQL Injection against an ORM generated data access object model. From the point of view of a tester, this attack is virtually identical to a SQL Injection attack. However, the injection vulnerability exists in code generated by the ORM layer. The benefits of using an ORM tool include quick generation of an object layer to communicate to a relational database, standardize code templates for these objects, and that they usually provide a set of safe functions to protect against SQL Injection attacks. ORM generated objects can use SQL or in some cases, a variant of SQL, to perform CRUD (Create, Read, Update, Delete) operations on a database

How to Test

Instead of directly targeting the application with SQL queries, you’d be focusing on abusing the ORM layer to send malicious SQL queries

Identify the ORM Layer

To efficiently test and understand what’s happening between your requests and the backend queries, and as with everything related to conducting proper testing, it is essential to identify the technology being used. By following the information gathering chapter, you should be aware of the technology being used by the application at hand. Check this list mapping languages to their respective ORMs

Identifying the ORM library the application is using:
– Hibernate: .. and 1bi = 1bd and ...
– EclipseLink: ... and FUNCTION('1=1 and','2')='2' and ...
– TopLink: ... and SQL('1=1') and ...
– OpenJPA: ... and "1"='1' and ...

Abusing the ORM Layer

After identifying the possible ORM being used, it becomes essential to understand how its parser is functioning, and study methods to abuse it, or even maybe if the application is using an old version, identify CVEs pertaining to the library being used

Weak ORM Implementation

A vulnerable scenario where the ORM layer was not implemented properly

ist results = session.createQuery("from Orders as orders where orders.id = " + currentOrder.getId()).list();
List results = session.createSQLQuery("Select * from Books where author = " + book.getAuthor()).list();

The above didn’t implement the positional parameter, which allows the developer to replace the input with a ?. An example would be as such:

Query hqlQuery = session.createQuery("from Orders as orders where orders.id = ?");
List results = hqlQuery.setString(0, "123-ADB-567-QTWYTFDL").list(); // 0 is the first position, where it is dynamically replaced by the string set

his implementation leaves the validation and sanitization to be done by the ORM layer, and the only way to bypass it would be by identifying an issue with the ORM layer

Vulnerable ORM Layer

ORM layers are code, third-party libraries most of the time. They can be vulnerable just like any other piece of code. One example could be the sequelize ORM npm library which was found to be vulnerable in 2019. In another research done by RIPS Tech, bypasses were identified in the hibernate ORM used by Java.

Cheat Sheet

SQL vs. ORM injections

Mikhail and Sergey focused their researches about ORM injections on these Java libraries. ORM injections are also called JPQL or HQL injections and they are very similar to SQL injections. Instead of defining SQL queries directly, this ORM libraries are using its own language JPQL/HQL (Java Persistence Query Language/Hibernate Query Language). These queries are translated to SQL by ORM library:

Quering data with ORM
Quering data with traditional SQL

Exploitation techniques

n Apache OpenJPA ORM they have found two methods to execute abritary SQL functions: The first is the WRONG SINGLE QUOTE PROC: It substitutes a sequence of ” (two single quotes) by one ‘ (single quote) after it checks the syntax. With this behavior it’s possible to hide SELECT-statements within a string:
ORM sees: and '1'='1'' and (select 1 where 1=1) = ''1' and
DBMS gets: and '1'='1' and (select 1 where 1=1) = '1' and

The second method is the QUOTES INDIFFERENCE:
ORM sees: and "a' = 'a' and (select 8 where 1=1)=8 and 'b" = 'b'
DBMS gets: and 'a' = 'a' and (select 8 where 1=1)=8 and 'b' = 'b'

Hibernate

In the Hibernate library they have found several methods: The first one is the SINGLE QUOTE ESCAPING method, which works in MySQL because it’s escapes single quotes in strings with a backslash (\’):
In HQL it is a string:
'abc\''or 1=(select 1)--'
In MySQL it is a string and a additional SQL expression:
'abc\''or 1=(select 1)--'

In PostgresSQL and H2 it’s possible to escape strings with two dollar quotes ($$). They’ve used this behavior to exploit it in the $-QUOTED STRINGS method:
In HQL it’s interpreted as the variable $$ is compared to a string:
$$='$$=concat(chr(61),chr(39)) and 1=1--'
but in SQL it’s a dollar quoted string compared to the concat() function:
$$='$$=concat(chr(61),chr(39)) and 1=1--'

For PostgresSQL and Oracle they’ve showed also the MAGIC FUNCTIONS method. PostgresSQL has a build in function query_to_xml('Arbitrary SQL') and Oracle DBMS_XMLGEN.getxml('SQL'). It’s possible to use this function to execute arbitrary SQL statements.

Reference

https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.7-Testing_for_ORM_Injection

--

--

Deepak Raj

Computer oriented, Ethical Hacker, CyberSec,Bug Hunter