淺談MyBatis Example模式SQL注入風(fēng)險(xiǎn)
在使用MyBatis逆向工程生成的Example查詢模式時(shí),很多開發(fā)者看到XML中存在${}占位符就會(huì)擔(dān)心SQL注入問題。但實(shí)際上,存在${}并不等同于存在SQL注入風(fēng)險(xiǎn)。本文將詳細(xì)分析何時(shí)會(huì)存在真正的注入風(fēng)險(xiǎn)。
存在SQL注入的兩個(gè)關(guān)鍵前提
前提一:Criteria存在自定義擴(kuò)展且接受外部輸入
MyBatis Generator生成的標(biāo)準(zhǔn)Criteria類是相對安全的,但如果開發(fā)者添加了自定義擴(kuò)展方法,就可能引入風(fēng)險(xiǎn):
// 危險(xiǎn)的自定義擴(kuò)展示例
public class MTaxSbPayExample {
public static class Criteria extends GeneratedCriteria {
// ? 危險(xiǎn):允許用戶直接傳入SQL條件
public Criteria andCustomCondition(String sqlCondition, Object value) {
addCriterion(sqlCondition, value, "custom");
return (Criteria) this;
}
// ? 危險(xiǎn):動(dòng)態(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)賦值
另一個(gè)風(fēng)險(xiǎn)點(diǎn)是orderByClause字段,因?yàn)镺RDER BY子句通常需要使用${}來處理列名:
<if test="orderByClause != null">
order by ${orderByClause}
</if>
危險(xiǎn)場景:
// ? 危險(xiǎn):直接將用戶輸入作為排序條件
@RestController
public class DataController {
public List<MTaxSbPay> getData(@RequestParam String sortBy) {
MTaxSbPayExample example = new MTaxSbPayExample();
// 直接使用用戶輸入,存在注入風(fēng)險(xiǎn)
example.setOrderByClause(sortBy);
return mapper.selectByExample(example);
}
}
惡意請求:
GET /getData?sortBy=id; DROP TABLE users;--
為什么存在${}不一定有SQL注入風(fēng)險(xiǎn)
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è)計(jì)模式
MyBatis Generator采用了條件與參數(shù)分離的設(shè)計(jì):
- 條件部分(
${criterion.condition}):硬編碼的操作符,如=、>、LIKE - 參數(shù)部分(
#{criterion.value}):用戶輸入,通過參數(shù)化查詢處理
這種設(shè)計(jì)確保了即使使用${},也不會(huì)直接拼接用戶輸入的內(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è)計(jì)模式:是否采用了參數(shù)分離的安全設(shè)計(jì)?
標(biāo)準(zhǔn)的MyBatis Generator生成的Example代碼通常是安全的,真正的風(fēng)險(xiǎn)往往來自于開發(fā)者的不當(dāng)擴(kuò)展和使用。
到此這篇關(guān)于淺談MyBatis Example模式SQL注入風(fēng)險(xiǎn)的文章就介紹到這了,更多相關(guān)MyBatis Example模式SQL注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring?boot應(yīng)用無法啟動(dòng)也沒報(bào)錯(cuò)信息的解決辦法
在使用Spring Boot開發(fā)應(yīng)用程序時(shí),偶爾會(huì)遇到啟動(dòng)不起來的問題,這是一種讓人沮喪的情況,尤其是當(dāng)日志中沒有任何錯(cuò)誤信息時(shí),這篇文章主要介紹了spring?boot應(yīng)用無法啟動(dòng)也沒報(bào)錯(cuò)信息的解決辦法,需要的朋友可以參考下2025-11-11
使用WebUploader實(shí)現(xiàn)分片斷點(diǎn)上傳文件功能(二)
這篇文章主要為大家詳細(xì)介紹了使用WebUploader實(shí)現(xiàn)分片斷點(diǎn)上傳文件功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
Spring-cloud-eureka使用feign調(diào)用服務(wù)接口
這篇文章主要為大家詳細(xì)介紹了Spring-cloud-eureka使用feign調(diào)用服務(wù)接口,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04
Java HtmlEmail 郵件發(fā)送的簡單實(shí)現(xiàn)代碼
下面小編就為大家?guī)硪黄狫ava HtmlEmail 郵件發(fā)送的簡單實(shí)現(xiàn)代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06
Java如何實(shí)現(xiàn)支付寶電腦支付基于servlet版本
這篇文章主要介紹了Java如何實(shí)現(xiàn)支付寶電腦支付基于servlet版本,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11

