作者:
clzzy
·
2013/11/25 15:41
0x00 背景
前段時間遇到一個使用了Hibernate框架的站,以前沒怎麼接觸過(由於是Java盲,所以大家勿噴),再注入的事情發生了許多奇奇怪怪的事情,於是向本地搭一個看看是個神馬情況。Hibernate配備了一種非常強大的查詢語言,這種語言看上去很像SQL。但是不要被語法結構上的相似所迷惑,HQL是非常有意識的被設計為完全物件導向的查詢。
0x01 測試
本次測試的環境是JDK5.0+Tomcat8+Hibernate3.0+Servlet。資料庫情況如下:
![2013112511500521075.png](https://i.iter01.com/images/b55807621075b0957ca6bec0b5bef25926d5746ed21eba28f235cf57cf48d2d0.jpg)
透過百度知道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](https://i.iter01.com/images/da3d1087fd49aee43fb642825ba71fec030f4a311ae4c1fb24b26e2e8ea95e91.jpg)
使用單引號測試(沒有返回異常的程式碼,預設情況,Tomcat報錯):
![2013112511514496111.png](https://i.iter01.com/images/baf6799dbda0203b1f1db1633380b2da71c587ca40f9d64f9ed1247b7a5bb3e7.jpg)
And 'a'='a
![2013112511522315773.png](https://i.iter01.com/images/64edf65a08b25bf960fad65d3834398f8c4aa0c1b25f18b1f1807a08fa9b1e6f.jpg)
And 'a'='b
![2013112511525569278.png](https://i.iter01.com/images/79e222d039db4372e64bf6463e53781d9cd43ae7a860e0d4c070a6f48a6a18f9.jpg)
跨庫查系統表?想都不要想:
![2013112511532221767.png](https://i.iter01.com/images/38aab12b647629806a4ac3722c201d0e26feca177d47b94b50480ba5e45cc53f.jpg)
*號也是不能用滴:
![2013112511534553955.png](https://i.iter01.com/images/e86a659eff3d59be3eddffaf953e3b33021a030c4ab9996908ff67aa9e19df33.jpg)
不支援union:
![2013112511541396421.png](https://i.iter01.com/images/9583a260d736fcd62da2ded45642a7efc707f0f095cb31f44ad54cd32ce10751.jpg)
單獨內嵌select作為條件(正常執行):
![2013112511544292137.png](https://i.iter01.com/images/2d3db8562c1168908b99ba46eb0bed86d32295d080fd7de279771677e253c142.jpg)
單獨執行substr(),ASCII()函式沒問題:
![2013112511550372977.png](https://i.iter01.com/images/2f750807abf708ac83881ee09e59c585dd78d4d18f4abfd53d1056128fe5ead6.jpg)
但是執行
ASCII(SUBSTR((select userpwd from Userlist where ROWNUM=1),1,1))>0
就不行了:
![2013112511552223471.png](https://i.iter01.com/images/1b1822a566ac18147e0ad9ffbb95e48c140d46644ae6c4a91341d0b0991ee5e8.jpg)
結論:這裡能爆的列還得看前面那個select的心情。
小刺蝟和它的小夥伴們都驚呆了:
![2013112511554437592.png](https://i.iter01.com/images/588907fb8be9e097f8385b9d8b597a35dec1c3ab3fcd05f5a5e6bcd4f8474657.jpg)
對於第二種使用原生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](https://i.iter01.com/images/3807dfb459f9517b2c192ddd41cfdf5cad7aed8e1fb93d383248728841bd1e05.jpg)
說說第三種,寫法大概是這樣:
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](https://i.iter01.com/images/351ce2378e61c507c8f00120bd9dd08b6e36b756d507c64972906c130342431a.jpg)
![2013112511565763376.png](https://i.iter01.com/images/07afb547c37cc976f0e3dc9f4fdd4f798c8491ae0568ed4b4c956d1923d5142f.jpg)
![2013112511571458944.png](https://i.iter01.com/images/033712c98a64b8a762b6985e502d4bf488e5f1c8ae5491070b52fb0d83405171.jpg)
![2013112511573196321.png](https://i.iter01.com/images/10c4654eabbb3abcae108dbc17cc0051aac7f4dfe55bc8571dd106928b52b4f2.jpg)
本來要結束的時候,我發現了第四種,是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](https://i.iter01.com/images/7018b0407def620567438be2ed74bcdeb3c2762206f24e6cf29dd7dc48d57288.jpg)
![2013112511581991918.png](https://i.iter01.com/images/e06b8cfb76fab93b5a467c02b658f6a94ce78cc9e7b6002d85195292da42edc1.jpg)
0x02 總結
最後:時間有限,只做了字元型的簡單粗淺表面測試,拋個磚,希望有更多經驗的留言啊,畢竟這方面的資料網上真心極少,為了方便大眾,請大牛們現身說法。
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!