Hibernate对注入的简单测试

0x00 背景


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

0x01 测试


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

2013112511500521075.png

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

1、HQL方式
2、原生SQL方式
3、Criteria方式

重点是HQL方式,HQL相当于Hibernate自己有一套SQL语法,在用Hibernate作为查询中间层的时候,它会将你写的HQL翻译成对应数据库的SQL语句,Hibernate支持N种数据库。

会一丢丢Java的童鞋都知道Hibernate的使用流程:

首先要告诉Hibernate数据库的连接信息,hibernate.cfg.xml文件:

#!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,而在实际环境中,开发者可能映射成他们喜欢的名字。

注:

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


#!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方式:大概代码:

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。

使用单引号测试(有返回异常的代码,数据库报错):

2013112511511598103.png

使用单引号测试(没有返回异常的代码,默认情况,Tomcat报错):

2013112511514496111.png

And 'a'='a 

2013112511522315773.png

And 'a'='b

2013112511525569278.png

跨库查系统表?想都不要想:

2013112511532221767.png

*号也是不能用滴:

2013112511534553955.png

不支持union:

2013112511541396421.png

单独内嵌select作为条件(正常执行):

2013112511544292137.png

单独执行substr(),ASCII()函数没问题:

2013112511550372977.png

但是执行

ASCII(SUBSTR((select userpwd from Userlist where ROWNUM=1),1,1))>0

就不行了:

2013112511552223471.png

结论:这里能爆的列还得看前面那个select的心情。

小刺猬和它的小伙伴们都惊呆了:

2013112511554437592.png

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

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);

就不多说了,就可普通注入一样。毫无压力:

2013112511561333503.png

说说第三种,写法大概是这样:

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下还能用

ascii(substr(userpwd,1,1))>1

来猜解前面SELECT中选择的列中有的列的内容的话,那么在第三种Criteria方式下,基本就绝望了:

2013112511564296588.png

2013112511565763376.png

2013112511571458944.png

2013112511573196321.png

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

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);

貌似这样的也没得玩,歇菜了:

2013112511581343139.png

2013112511581991918.png

0x02 总结


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

©乌云知识库版权所有 未经许可 禁止转载


30
隐形人真忙 2015-02-24 00:17:06

HQL注入很鸡肋,一般万能密码还行,盲注的话,列名和元数据如何爆,是个问题。除非try-catch中有这样的代码:e.getSQLException或者e.getSQL(),“友好”的显错,所有列名都能爆出。

30
Asuri 2014-09-06 21:52:10

这方面的资料真心很少......源码审计的时候遇到的一个,明知肯定有注入,但是现有的办法都不行.....

30
Oops 2014-01-13 11:47:57

说是java盲,我怎么感觉比我知道得还详细啊

30
Mody 2014-01-02 17:25:11

应该属于第三种,ANSCII \SUBSTR 分开可以,结合就不行了。。。楼主最近可有好的利用方法??

30
Mody 2014-01-02 17:00:22

遇到一个。。蛋碎中

30
核攻击 2013-12-17 10:55:27

阅~

30
neal 2013-12-03 18:43:33

java 这个面向对象的语言 在hibernate使用里面 sql还是 拼接字符串,我只能说 神一般的程序员。 一般使用都是第三或者第四种。

30
wefgod 2013-12-03 11:13:38

我去,悲剧啊。就是说第一个方法无法跨过去查任何其它表了?注册有的表也不行?
好难搞哦

30
0x_Jin 2013-11-25 18:43:22

二楼抢坐!

30
clzzy 2013-11-25 16:37:13

老夫先来

感谢知乎授权页面模版