sql注入解决方案
前言: 前几天公司进行渗透测试 发现了sql注入的问题,然后发现是有人使用了 $ ,然后看了他的代码发现了问题,最主要的原因就是懒,本来应该让前端传list集合,他却让前端拼字符串直接in(入参) ,然后我和项目经理考虑了,项目已经上线了,如果改入参还要重新联调接口,现在还有个新项目准备开发,抽不出来人进行修改联调了,便在内部扭转,进行操作,最后梳理成文档帮助公司同事解决这个问题。
mybatis Sql:
<if test="safetyPageParam.caseStatus !=null and safetyPageParam.caseStatus != ''">
AND t2.channel_status in (${safetyPageParam.caseStatus})
</if>
问题: 使用 $, 会引发SQL注入问题,其实是有点
入参:
“safetyPageParam.caseStatus”:"(select 7445 from (select(sleep(5)))xGHL)"
执行sql:
SELECT count(0) FROM sheet_report_info t1
LEFT JOIN (SELECT * FROM t_case_info WHERE is_del = 0) t2
ON t1.report_no = t2.report_no
LEFT JOIN (SELECT * FROM t_policy_info WHERE is_del = 0) t3
ON t1.report_no = t3.report_no
WHERE t1.channel_code = 'safety' AND t1.is_del = 0
AND t1.reg_user_code = '19UC1485196736019300352'
AND t2.channel_status IN (
(SELECT 7445 FROM (SELECT (sleep(5))) xGHL) // 注入sql
)
AND t2.channel_code = 'safety'
解决办法:
对于 in 操作的sql语句不能简单的将 $ 替代为 #。这样虽然规避了sql注入,但引发程序功能的不正确。
入参:
{
"caseNo": "",
"caseStatus": "'01','02'", // 前端传值,为了多选
"channelCode": "safety",
"closeAuditorCode": "",
"desc": false,
"endReportTime": "",
"endRiskTime": "",
"insuredCompanyReportNo": "",
"orderBy": "report_time",
"pn": 1,
"policyNo": "",
"ps": 10,
"regUserCode": "19UC1485196736019300352",
"reportNo": "",
"servicerCode": "",
"startReportTime": "",
"startRiskTime": "",
"u400Code": ""
}
为了达到多选 caseStatus,目前前端传值为String,内容为 " ‘01’,‘02’ ".
如果使用
t2.channel_status in (#{safetyPageParam.caseStatus})
则语义为
channel_status in ( " ‘01’,‘02’ ") 一个参数,参数值为 { ‘01’,‘02’ }
这样程序功能是错误的。
方案
java端将 ‘01’,‘02’ 进行 split(",")处理,转为list。
mybatis写法改为
<if test="safetyPageParam.listCaseStatus !=null and safetyPageParam.listCaseStatus.size > 0">
AND t2.channel_status in
<foreach collection="safetyPageParam.listCaseStatus" item="status" index="index" open="(" close=")" separator=",">
#{status}
</foreach>
</if>
每天记录发现的问题,不进步就是在退步