淺談MyBatis Example模式SQL注入風(fēng)險
在使用MyBatis逆向工程生成的Example查詢模式時,很多開發(fā)者看到XML中存在${}占位符就會擔(dān)心SQL注入問題。但實(shí)際上,存在${}并不等同于存在SQL注入風(fēng)險。本文將詳細(xì)分析何時會存在真正的注入風(fēng)險。
存在SQL注入的兩個關(guān)鍵前提
前提一:Criteria存在自定義擴(kuò)展且接受外部輸入
MyBatis Generator生成的標(biāo)準(zhǔn)Criteria類是相對安全的,但如果開發(fā)者添加了自定義擴(kuò)展方法,就可能引入風(fēng)險:
// 危險的自定義擴(kuò)展示例
public class MTaxSbPayExample {
public static class Criteria extends GeneratedCriteria {
// ? 危險:允許用戶直接傳入SQL條件
public Criteria andCustomCondition(String sqlCondition, Object value) {
addCriterion(sqlCondition, value, "custom");
return (Criteria) this;
}
// ? 危險:動態(tài)表名或列名
public Criteria andDynamicColumn(String columnName, String operator, Object value) {
addCriterion(columnName + " " + operator, value, columnName);
return (Criteria) this;
}
}
}
如果用戶輸入直接傳遞給這些方法:
// 惡意輸入示例 String userInput = "1=1; DROP TABLE users;--"; example.createCriteria().andCustomCondition(userInput, "someValue");
前提二:Example對象作為接口參數(shù)且orderByClause被不當(dāng)賦值
另一個風(fēng)險點(diǎn)是orderByClause字段,因?yàn)镺RDER BY子句通常需要使用${}來處理列名:
<if test="orderByClause != null">
order by ${orderByClause}
</if>
危險場景:
// ? 危險:直接將用戶輸入作為排序條件
@RestController
public class DataController {
public List<MTaxSbPay> getData(@RequestParam String sortBy) {
MTaxSbPayExample example = new MTaxSbPayExample();
// 直接使用用戶輸入,存在注入風(fēng)險
example.setOrderByClause(sortBy);
return mapper.selectByExample(example);
}
}
惡意請求:
GET /getData?sortBy=id; DROP TABLE users;--
為什么存在${}不一定有SQL注入風(fēng)險
1. 硬編碼的安全使用
在標(biāo)準(zhǔn)的MyBatis Generator實(shí)現(xiàn)中,${criterion.condition}中的condition是硬編碼的:
// 生成的安全方法
public Criteria andIdEqualTo(String value) {
addCriterion("ID =", value, "id"); // "ID =" 是硬編碼字符串
return (Criteria) this;
}
對應(yīng)的XML處理:
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
最終生成安全的SQL:
WHERE ID = ? -- 參數(shù): 用戶輸入值
2. 參數(shù)分離的設(shè)計模式
MyBatis Generator采用了條件與參數(shù)分離的設(shè)計:
- 條件部分(
${criterion.condition}):硬編碼的操作符,如=、>、LIKE - 參數(shù)部分(
#{criterion.value}):用戶輸入,通過參數(shù)化查詢處理
這種設(shè)計確保了即使使用${},也不會直接拼接用戶輸入的內(nèi)容。
3. 用戶輸入路徑受限
標(biāo)準(zhǔn)的Criteria類只提供預(yù)定義的方法:
// 用戶只能通過這些安全的方法構(gòu)建查詢
criteria.andIdEqualTo(userInput); // 安全
criteria.andNameLike("%" + userInput + "%"); // 安全
criteria.andStatusIn(Arrays.asList("ACTIVE", "INACTIVE")); // 安全
用戶無法直接控制criterion.condition的值,只能影響criterion.value,而后者是參數(shù)化處理的。
總結(jié)
MyBatis的${}占位符本身并不等同于SQL注入漏洞。關(guān)鍵在于:
- 數(shù)據(jù)來源:是硬編碼還是用戶輸入?
- 使用方式:是否進(jìn)行了適當(dāng)?shù)尿?yàn)證和過濾?
- 設(shè)計模式:是否采用了參數(shù)分離的安全設(shè)計?
標(biāo)準(zhǔn)的MyBatis Generator生成的Example代碼通常是安全的,真正的風(fēng)險往往來自于開發(fā)者的不當(dāng)擴(kuò)展和使用。
到此這篇關(guān)于淺談MyBatis Example模式SQL注入風(fēng)險的文章就介紹到這了,更多相關(guān)MyBatis Example模式SQL注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Idea連接數(shù)據(jù)庫并執(zhí)行SQL語句的方法示例
這篇文章主要介紹了Idea連接數(shù)據(jù)庫并執(zhí)行SQL語句的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
關(guān)于QueryWrapper,實(shí)現(xiàn)MybatisPlus多表關(guān)聯(lián)查詢方式
這篇文章主要介紹了關(guān)于QueryWrapper,實(shí)現(xiàn)MybatisPlus多表關(guān)聯(lián)查詢方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。2022-01-01
SWT(JFace)體驗(yàn)之ApplicationWindow
SWT(JFace)體驗(yàn)之ApplicationWindow2009-06-06
SpringBoot中使用MyBatis-Plus詳細(xì)步驟
MyBatis-Plus是MyBatis的增強(qiáng)工具,簡化了MyBatis的使用,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2025-01-01
SWT(JFace)體驗(yàn)之StackLayout布局
SWT(JFace)體驗(yàn)之StackLayout布局實(shí)現(xiàn)代碼。2009-06-06
java開發(fā)CPU流水線與指令亂序執(zhí)行詳解
這篇文章主要為大家介紹了java開發(fā)CPU流水線與指令亂序執(zhí)行詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
SpringBoot RestTemplate GET POST請求的實(shí)例講解
這篇文章主要介紹了SpringBoot RestTemplate GET POST請求的實(shí)例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
SpringBoot整合mybatisplus和druid的示例詳解
這篇文章主要介紹了SpringBoot整合mybatisplus和druid的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08

