天天看點

Java審計之SQL注入

目前已知的操作資料庫的方式應該也就JDBC、Mybatis、Hibernate。現在應該比較少見SSH是以可能較少遇到Hibernate中的SQL注入審計,後續遇到會進行補充。大部分情況下應該都是SSM居多,應該Mybatis會經常遇到些。本文主要來記錄些JDBC與Mybatis中可能存在SQL注入的情況。

先簡單回顧一下JDBC:

Java通過java.sql.DriverManager來管理所有資料庫的驅動注冊,是以如果想要建立資料庫連接配接需要先在java.sql.DriverManager中注冊對應的驅動類,然後調用getConnection方法才能連接配接上資料庫。 JDBC定義了一個叫java.sql.Driver的接口類負責實作對資料庫的連接配接,所有的資料庫驅動包都必須實作這個接口才能夠完成資料庫的連接配接操作。java.sql.DriverManager.getConnection(xx)其實就是間接的調用了java.sql.Driver類的connect方法實作資料庫連接配接的。資料庫連接配接成功後會傳回一個叫做java.sql.Connection的資料庫連接配接對象,一切對資料庫的查詢操作都将依賴于這個Connection對象。

後面主要涉及的3個對象

connection

connection對象代表資料庫

可以設定資料庫自動送出。事務送出(connection.commit()),事務復原(connection.rollback())。

statement

調用connnection.createStatement()方法會傳回一個statement對象。

是具體執行sql語句

PreparedStatement

與statement對象的差別是,不直接放入sql語句,先用?作為占位符進行預編譯,等預編譯完成後,對?進行指派,之後調用execute等方法不需要添加參數即可完成執行SQL語句。

那麼在使用JDBC的時候在使用statement直接拼接SQL語句而不是PreparedStatement預編譯方式執行SQL語句的話可能就會造成SQL注入。

示例代碼,POST和GET同理,隻是會把代碼寫在doPost方法裡。

這裡就是一個比較經典的使用Statement對象,沒有進行預編譯,将前端傳入的參數id直接拼接到SQL語句裡可能導緻SQL注入。如果沒有自己加一些對惡意傳入字元的過濾就會導緻SQL注入。在審計的時候如果發現了是使用JDBC的方式可以跟一下或者全局搜尋,看執行SQL時使用的是statement還是PreparedStatement,如果是statement多半就存在注入了。

大機率會出現在搜尋框等會用到模糊查詢的地方

同理如果是用statement直接拼接的可能就會存在SQL注入了。

以上是 JDBC在使用Statement執行SQL時可能會存在注入的點,在審計時可以嘗試直接搜尋如Statement字段去定位危險方法,如果參數可控基本就是一個SQL注入。

Mybatis中有兩種擷取前端傳入值的方式

當參數通過 <code>#{}</code> 聲明的,會通過 PreparedStatement ,即預編譯的方式來執行。 預編譯不僅可以對 SQL 語句進行轉義,避免 SQL 注入,還可以增加執行效率。 而Mybatis底層也是JDBC實作的,但值得注意的一點是,這裡的 PreparedStatement 嚴格意義上來說并不是完全等同于預編譯。其實預編譯分為用戶端的預編譯以及服務端的預編譯,4.1 之後的 MySql 伺服器端已經支援了預編譯功能。很多主流持久層架構(MyBatis,Hibernate)其實都沒有真正的用上預編譯,預編譯是要我們自己在參數清單上面配置的,如果我們不手動開啟,JDBC 驅動程式 5.0.5 以後版本 預設預編譯都是關閉的。需要通過配置連接配接資料庫時的url參數來進行開啟<code>useServerPrepStmts=true&amp;cachePrepStmts=true</code> 即MySQL是否開啟服務端的預編譯是由用戶端連接配接時的參數useServerPrepStmts決定的,而在MySQL提供的Connector/J版本5.0.5(release 2007-03-02)之後,預設情況下,useServerPrepStmts=false。即如果沒有顯式設定成true,預設情況下,MySQL不啟用服務端預編譯

通常寫模糊查詢時就會用到like語句,不過一般用#{}在SQL中拼接%會直接報錯,比如下面這個

但是用${}在SQL中拼接%就并不會報錯,這也是導緻在模糊查詢處出現SQL注入的原因之一。

安全寫法:

另外也可參考此文章https://www.anquanke.com/post/id/190170利用Mybatis generator編寫安全的demo

類似于模糊查詢,其他的還有SQL語句中的一些部分,例如order by字段、表名、in後注入等,是無法使用預編譯語句的,可能會出現存在${}拼接的情況就會導緻SQL注入。

審計時可以重點關注是否存在Statement和${}直接拼接SQL語句的情況(Mybatis),大機率都會是可能存在注入的點。

所有内容僅限于維護網絡安全學習參考