系统里大量存在查询界面,例如A框为模糊查询条件,里面输入文字a,系统后台会拼接SQL条件 A like '%a%'。B框为等于条件,输入b,后台翻译为B='b'。看起来没有什么问题,但是偏偏黑客哥会使用这个漏洞,例如B=‘b'这个,黑哥会在录入框里输入1' or '1'='1,带入后得到
B='1' or '1'='1' 成了永真条件,造成数据泄露,这就是SQL注入。防止起来也没什么秘密,检查下输入条件,避免出现% or 等。问题在于系统中这样的地方太多,写起来代码量太大。平台提供的基本方案如下:
public static boolean sql_inj(String str){ //这里是注入关键词可以根据需要进行增加或者修改。 String inj_str = "'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|+|="; String[] inj_stra=inj_str.split("\\|"); for (int i=0 ; i < inj_stra.length ; i++ ){ if (str.indexOf(inj_stra[i])>=0){ return true; } } return false; }
这个是检查某个字符串是否含注入的SQL,为基本函数。前面讲过所有接口的参数都是一个输入的对象,挨个检查这个对象里对应属性值即可,最终方案如下:
// 通用检查查询参数
public static boolean sql_inj(Object o,String fields){
CommonsUtil.debugLog("==sql_inj o="+o+" fields="+fields);
String []fs=fields.split(",");
for(int i=0;i<fs.length;i++){
String value=reflectUtils.getFieldValueByName(o,fs[i]);
if (value!=null && !"".equals(value) && sql_inj(value)) {
CommonsUtil.debugLog("feild="+fs[i]+" value="+value);
return true;
}
}
return false;
}
fields是要求检查的属性名字,例如:“name,idcard”
reflectUtils.getFieldValueByName里有反射机制获取属性信息,下篇将介绍反射
整体效果:
public PageResult<EvaKeyItemDTO> getKeyItemListBySetId(@RequestBody EvaKeyItemRequestDTO dto) { PageResult<EvaKeyItemDTO> rsPage = new PageResult(BaseController.getURI(), dto); // 防sql注入 if (CommonsUtil.sql_inj(dto,"itemName,itemType,validFlag,lowValue,highValue")){ rsPage.setRetCode(IOResultEnum.INVAILD_PARAMTER.getKey()); rsPage.setMsg("查询条件中非法注入了SQL"); return rsPage; }