【代碼審計】SQL 注入

0x01 JDBC 拼接不當造成 SQL 注入

JDBC 有兩種方法執(zhí)行 SQL 語句,分別為 PrepareStatement 和 Statement,兩個方法的區(qū)別在于 PrepareStatement 會對 SQL 語句進行預編譯,而 Statement 在每次執(zhí)行時都需要編譯,會增大系統(tǒng)開銷。

理論上 PrepareStatement 的效率和安全性會比 Statement 好,但不意味著就不會存在問題。

以下是一個使用 Statement 執(zhí)行 SQL 語句的示例

String sql = "select * from user where id ="+req.getParameter("id");
PrintWriter out = resp.getWriter();
out.println("Statement Demo");
out.println("SQL: "+sql);
try {
    Statement st = conn.createStatement();
    ResultSet rs = st.executeQuery(sql);

這里如果輸入的 id 為 1 or 1 = 2,那么 SQL 語句就會被拼接為 select * from user where id = 1 or 1 = 2,改變了想要查詢 id = 1 的語義。

PreqareStatement 方法支持使用 ? 對變量位進行占位,在預編譯階段填入相應的值會構(gòu)造出完整的 SQL 語句,從而避免 SQL 注入的產(chǎn)生。

但開發(fā)有時為了便利,會直接采取拼接的方式構(gòu)造 SQL 語句,這樣一來依然會存在 SQL 注入,如下代碼所示。

String sql = "select * from user where id ="+req.getParameter("id");

PrintWriter out = resp.getWriter();
out.println("prepareStatement Demo");
out.println("SQL: "+sql);
try {
    PreparedStatement pst = conn.prepareStatement(sql);
    ResultSet rs = pst.executeQuery();

此時如果使用 or 1 = 1 仍然可以判斷存在 SQL 注入,但是如果使用 ? 作為占位符,填入的字段的值就會進行嚴格的類型檢查,就可以有效的避免 SQL 注入的產(chǎn)生,如下代碼所示。

PrintWriter out = resp.getWriter();
out.println("prepareStatement Demo");
String sql = "select * from user where id = ?";
out.println(sql);
try {
    PreparedStatement pstt = conn.prepareStatement(sql);
    // 參數(shù)已經(jīng)強制要求是整型
    pstt.setInt(1, Integer.parseInt(req.getParameter("id")));
    ResultSet rs = pstt.executeQuery();
    while (rs.next()){

0x02 框架使用不當造成 SQL 注入

通??蚣艿讓右呀?jīng)實現(xiàn)了對 SQL 注入的防御,但是如果在開發(fā)未能恰當?shù)氖褂每蚣艿那闆r下,依然會存在 SQL 注入的風險。

1、MyBatis 框架

MyBatis 的思想是將 SQL 語句編入配置文件中,避免 SQL 語句在代碼中大量出現(xiàn),方便對 SQL 語句的修改和配置。

MyBatis 使用 parameterType 向 SQL 語句傳參,在 SQL 引用傳參的時候可以使用 #{} 和 ${} 兩種方式,兩種方式區(qū)別如下:

${}:SQL 拼接符號,直接將輸入的語句拼接到 SQL 語句里,想避免 SQL 注入問題需要手動添加過濾

#{}:占位符號,在對數(shù)據(jù)解析時會自動將輸入的語句前后加上單引號從而避免 SQL 注入

也就是說在 MyBatis 框架中,如果使用了 ${} 方法,同時又沒有進行過濾就會產(chǎn)生 SQL 注入,而使用 #{} 方法時可以避免 SQL 注入。

2、Hibernate 框架

Hibernate 是現(xiàn)今主流的 Java 數(shù)據(jù)庫持久化框架,采用 Hibernate 查詢語句(HQL)注入。

HQL 查詢語句來自 Hibernate 引擎進行解析,因此產(chǎn)生的錯誤可能來自數(shù)據(jù)庫,也有可能來自 Hibernate 引擎。

HQL 和 SQL 的區(qū)別:

image

HQL 注入和 SQL 注入的成因都一樣,使用拼接 HQL 語句的寫法可能會導致 SQL 注入

Query query = session.createQuery("from User where name='"+queryString+"'");

但是受語法影響,HQL注入在漏洞利用上有一定的限制,比如不能利用聯(lián)合查詢、不能跨庫查表、執(zhí)行命令等。

對于 Hibernate 的注入,這里只作為簡單了解一下,平時代審的時候注意一下即可。

參考文章:

https://www.redhatzone.com/ask/article/1448.html

https://blog.csdn.net/qq_36594628/article/details/119461996

原文鏈接:

https://www.teamssix.com/211117-091653.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容