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ū)別:
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
原文鏈接: