最近做完项目时,甲方对系统有要过安全等保三级的要求,这里针对我所编写的模块遇到的代码扫描出现的sql注入问题,给出部分解决方案。

错误示例

最开始,使用fmt.Sprintf做字符串拼接的方式,来形成原生的sql语句。这样做虽然代码简单,但是却存在sql注入风险。

 str := fmt.Sprintf("select DataId,ParaId,ObjId,RtuCode,DevNo,RtuState,ReportDT,RecordDT,EventId,EventDT,CommType,SignalCSQ,PosState,PosAccu,Lng,Lat,ShiftRtu,ShiftCalc,SatNum,GnssDip,GnssSpeed,GnssAccu,RtuSticVolt,RtuBattVolt,RtuBattCurr,RtuSolarVolt,RtuSolarCurr,IsDaySum,RtuChagSum,RtuDischagSum,RtuRsdSum,SmsSend,SmsRece,AntenAbnr,ComAbnr,ChagAbnr,LampCtrlAbnr,PosAbnr,BattVoltAbnr,BattCurrAbnr,SolarVoltAbnr,SolarCurrAbnr,WorkMode,Sunlight,LampState,LampRhyt,LampRhytDip,LampVolt,LampCurr,LampStateAbnr,LampRhytAbnr,LampVoltAbnr,LampCurrAbnr,LampSticVolt,LampBattVolt,LampBattCurr,LampSolarVolt,LampSolarCurr from rtu_data_yz18 where Rtucode = '%s' ", c_code)
 err := global.DB.Raw(str).Find(&result).Error

正确操作

使用map,需要填入的变量,使用@变量的形式传递进去,可有效避免sql注入风险

args := make(map[string]any)
	args["id"] = c_id
	str := "with a1 as (SELECT ObjId from phar_define where ObjId = @id),a2 as(select ObjId,RtuCode,GnssType,PosType,WorkMode,LngRef,LatRef,VoltMax,VoltMin,ShiftLimit,DriftLimit,SunlightLimit,SIM,ServerSIM,IP,CenterSIM,APN,Port,LampBright from rtu_para_yz18),a3 as(select Lng,Lat,RtuCode,DataId from rtu_data_yz18) select a1.ObjId,PosType,GnssType,a2.RtuCode,a2.WorkMode,VoltMax,VoltMin,a3.Lng,a3.Lat,LngRef,LatRef,LampBright,ShiftLimit,DriftLimit,SunlightLimit,SIM,ServerSIM,IP,CenterSIM,APN,Port from a1 left join a2 on a1.ObjId=a2.ObjId left join a3 on a2.RtuCode=a3.RtuCode"
	err := global.DB.Raw(str,args).Find(&result).Error