# Hibernate对注入的简单测试

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2013-11-25T07:41:00Z
Canonical: https://wepostx.com/topics/186

> 乌云历史资料归档
>
> **原始作者：** clzzy
> **原始编号：** superkieran-wooyundrops:114
> **原始发布时间：** 2013-11-25 15:41
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

## 0x00 背景

前段时间遇到一个使用了Hibernate框架的站，以前没怎么接触过（由于是Java盲，所以大家勿喷），再注入的事情发生了许多奇奇怪怪的事情，于是向本地搭一个看看是个神马情况。Hibernate配备了一种非常强大的查询语言，这种语言看上去很像SQL。但是不要被语法结构上的相似所迷惑，HQL是非常有意识的被设计为完全面向对象的查询。

## 0x01 测试

本次测试的环境是JDK5.0+Tomcat8+Hibernate3.0+Servlet。数据库情况如下：

![原文图片](/media/2016/06/a28cb25175ae0c4213b47a40d79b62de)

通过百度知道Hibernate的查询大概有5、6种，通过分析对注入能产生不同影响的应该有如下三种：

```text
1、HQL方式 2、原生SQL方式 3、Criteria方式
```
重点是HQL方式，HQL相当于Hibernate自己有一套SQL语法，在用Hibernate作为查询中间层的时候，它会将你写的HQL翻译成对应数据库的SQL语句，Hibernate支持N种数据库。
会一丢丢Java的童鞋都知道Hibernate的使用流程：
首先要告诉Hibernate数据库的连接信息，hibernate.cfg.xml文件：

```text
#!xml <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <!-- Generated by MyEclipse Hibernate Tools. --> <hibernate-configuration> <session-factory> <property name="dialect">org.hibernate.dialect.Oracle9Dialect</property> <property name="connection.url">jdbc:oracle:thin:@192.168.79.151:1521:orcl</property> <property name="connection.username">system</property> <property name="connection.password">xxoo</property> <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="myeclipse.connection.profile">oracle_connet</property> <mapping resource="com/mytest/map/Userlist.hbm.xml"/>//这里是包含表的映射文件 </session-factory> </hibernate-configuration>
```
其实是映射你想使用的数据表（系统会按照表明自动生成文件，比如我的Userlist表会生成Userlist.hbm.xml），Userlist.hbm.xml文件：
分别将ID、USERNAME、USERPWD列映射为id、username、userpwd，而在实际环境中，开发者可能映射成他们喜欢的名字。
注：

```text
1、未映射的表是不能查询的； 2、使用映射后表名、列名时大小写敏感； 3、不能使用数据库中的列名，比如USERNAME映射为username之后，不能再使用USERNAME，否则报错。
```

```text
#!xml <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.mytest.map.Userlist" table="USERLIST" schema="SYSTEM"> <id name="id" type="java.math.BigDecimal"> <column name="ID" precision="22" scale="0"/> <generator class="assigned"/> </id> <property name="username" type="java.lang.String"> <column name="USERNAME" length="20" not-null="true"/> </property> <property name="userpwd" type="java.lang.String"> <column name="USERPWD" length="30" not-null="true"/> </property> </class> </hibernate-mapping>
```

### 1、原生的HQL方式：大概代码：

```text
try{ s=HibernateSessionFactory.getSession(); tx=s.beginTransaction(); Query query=s.createQuery("from Userlist as u where username='" +userName + "'"); Qstring=query.getQueryString(); // Iterator it = query.iterate(); //这是Iterate数据返回方式 List it=query.list();//这是List数据返回方式 // ul = (Userlist) it.next(); ul=(Userlist)it.get(0); mUserPwd=ul.getUserpwd(); }catch (Exception e) { System.out.println(e.getMessage()); return e.getMessage(); }//这里加了返回抛出的异常的代码 tx.commit(); //关闭连接 HibernateSessionFactory.closeSession();
```
上面提到的Iterate和List数据返回方式没发现对注入产生多大的影响，他们呢的具体差别请google。
使用单引号测试（有返回异常的代码，数据库报错）：

![原文图片](/media/2016/06/e4f5bf4514228ba4724c25d1e2c35e6a)

使用单引号测试（没有返回异常的代码，默认情况，Tomcat报错）：

![原文图片](/media/2016/06/050f6d79bc581b4e9ac87398537cbc27)

```text
And 'a'='a
```

![原文图片](/media/2016/06/df31e41f4c8cd976aaffccbdd2e8881c)

```text
And 'a'='b
```

![原文图片](/media/2016/06/08f198f7994f0009f61c970b990897b3)

跨库查系统表？想都不要想：

![原文图片](/media/2016/06/98b13b47e5c7d64719b049b7e47505a7)

*号也是不能用滴：

![原文图片](/media/2016/06/a9d14f928d7e819541b9ca4cee8e3846)

不支持union：

![原文图片](/media/2016/06/b5815c50f9cd3b0c58d6a8a1b47b4dfb)

单独内嵌select作为条件（正常执行）：

![原文图片](/media/2016/06/ffb3d1da2c5bbc2c5e013a599f79946f)

单独执行substr()，ASCII()函数没问题：

![原文图片](/media/2016/06/7a2ff70e0554147eec378a25d89f33ba)

但是执行

```text
ASCII(SUBSTR((select userpwd from Userlist where ROWNUM=1)，1,1))>0
```
就不行了：

![原文图片](/media/2016/06/244c1609cf62b10fd69f69ff37e0b7d3)

结论：这里能爆的列还得看前面那个select的心情。
小刺猬和它的小伙伴们都惊呆了：

![原文图片](/media/2016/06/242bd1128aee405aa91d7c893d18d76e)

对于第二种使用原生SQL的方式，写法大概是这样：

```text
s=HibernateSessionFactory.getSession(); tx=s.beginTransaction(); Query query=s.createSQLQuery("select USERPWD from Userlist where USERNAME='" +userName + "'"); Qstring=query.getQueryString(); List it = query.list(); mUserPwd=(String)it.get(0);
```
就不多说了，就可普通注入一样。毫无压力：

![原文图片](/media/2016/06/c02626c91e09c00b81b7717f081b7779)

说说第三种，写法大概是这样：

```text
s=HibernateSessionFactory.getSession(); List UserLists=s.createCriteria(Userlist.class).add(Restrictions.eq("username",userNameString)).list(); Userlist u=(Userlist)UserLists.get(0); mUserPwd=u.getUserpwd();
```
如果说我们在HQL下还能用

```text
ascii(substr(userpwd,1,1))>1
```
来猜解前面SELECT中选择的列中有的列的内容的话，那么在第三种Criteria方式下，基本就绝望了：

![原文图片](/media/2016/06/ba650d8cc326ec6695ff9652bd1e0fd9)

![原文图片](/media/2016/06/e2428d0767f8ad449d3b473e582adbe5)

![原文图片](/media/2016/06/5ae520c7cd2e9db10342e892f5526c0a)

![原文图片](/media/2016/06/17f555d78cab8c0e0b118438f38e3f82)

本来要结束的时候，我发现了第四种，是HQL的另一种写法，大概代码这么写：

```text
s=HibernateSessionFactory.getSession(); tx=s.beginTransaction(); Query query=s.createSQLQuery("select {p.*} from Userlist {p} where {p}.USERNAME="+userNameString).addEntity("p", Userlist.class); Qstring=query.getQueryString(); List it = query.list(); mUserPwd=(String)it.get(0);
```
貌似这样的也没得玩，歇菜了：

![原文图片](/media/2016/06/79ae1ef4017b25161e7f6e39cc0fee1c)

![原文图片](/media/2016/06/2871b7c814eb96b93f0540cc9bdeb43d)

## 0x02 总结

最后：时间有限，只做了字符型的简单粗浅表面测试，抛个砖，希望有更多经验的留言啊，毕竟这方面的资料网上真心极少，为了方便大众，请大牛们现身说法。

## Replies
