开发指南038-防SQL注入

发布于:2024-07-03 ⋅ 阅读:(11) ⋅ 点赞:(0)

系统里大量存在查询界面,例如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;
        }