Oracle 存储过程 字符串拼接 SQL注入的问题

SQL注入 同时被 2 个专栏收录
1 篇文章 0 订阅
1 篇文章 0 订阅

之前项目中写的一个大的存储过程 中间用到的SQL字符串拼接的方法 来完成业务的流程 类似SQL的动态拼接把

 

为什么要有用到这种形式 因为我这个存储过程里面要处理 至少三个系统的六种情况 所以使用拼接的方式是最容易想到的

 

存储过程大概意思 先将查询到的数据存放到临时表中 然后再对临时表的数据做遍历,这里不说这个了

 

直接正题: (以对数据做处理) 之前都是这样直接写的

但是这有个严重的问题 就是用字符串拼接的方法实现的sql , 如果传入的参数 是非法的 如(or ' 1=1 --)很容易造成SQL注入的问题

   V_SQL := ' INSERT INTO TEMP_Table(t1,t2,t3,t4,t5,t6)
                select
                       .....
                from USER_BASIC ub
                        left join ......
                where ud.xxxx = ''xxx''';

                --传入LK_QUERY_USER_ID
                IF LK_QUERY_USER_ID IS NOT NULL THEN
                    V_SQL := V_SQL || ' and ub.USER_ID like ''%' || LK_QUERY_USER_ID || '%''' ;
                end if;
                   
                -- 过滤不需要返回的人员  属于正则表达式分割
                    IF LK_FORWARD_USER IS NOT NULL THEN
                        V_SQL := V_SQL || ' and ub.USER_ID not in (
                SELECT REGEXP_SUBSTR( ''' || LK_FORWARD_USER || ''', ''[^,]+'', 1, ROWNUM) userId
                FROM DUAL
                CONNECT BY ROWNUM <=
                           LENGTH(''' || LK_FORWARD_USER || ''') -
                           LENGTH(REGEXP_REPLACE(''' || LK_FORWARD_USER || ''', '','', '''')) + 1)';
                    end if;
                    
                    
                 --过滤掉当前操作人
                   IF LK_USER_ID IS NOT NULL THEN
                       V_SQL := V_SQL || 'and ub.USER_ID !=''' || LK_USER_ID || '''';
                   end if;   

                   --执行操作
                   execute immediate V_SQL;

处理方法

第一 最简单的 方法 我认为是 用Java程序对传入的参数 进行校验 符合规则的才能让其调用存储过程 否则不能调用 这就解决了 sql注入的大部分问题 当然 这不是 今天的主题...

 

防止SQL注入的方法

因为我是使用的是  execute immediate V_SQL; 执行的

这里就不得不说一下 execute immediate 的特性了

用法3
    v_sql:= ' select t.user_id FROM sys_users t where t.user_name = :1';
    execute immediate v_sql into v_dname using v_item ;
    
用法4
    v_sql := 'BEGIN :1 := ' || 'sys_users_pkg.get_user_id' || '(:2,:3,:4,:5);END;';
  execute immediate v_sql using out v_user_id, in p_user_name, in p_password, 
    in p_parameter_other_1, p_parameter_other_2;
  • :1,:2 这样的字符代表占位符,在v_sql整个字符串中它代表的意义是需要等待指定的,我们可以使用using关键字指定 占位符 上是什么。
  • in 和 out 是 输入/输出的意思,in是默认的参数类型可以省略
  • 使用了using 但是没使用 in 或者out 关键字 那就是 in类型。
  • using aa 等价于 using in aa
  • using out aa 使用aa这个变量或字面量(没打错)去替换对应位置的占位符

 

懂了吧 知道怎么去 处理注入的问题了把 我们可以利用 using xxx 这个特性 将 入参 当成占位符处理 类似 mybatis 中的 #{}

 

代码

一定要主意using 后面的顺序 按照你的sql 的前后顺序来的

 

我这里 使用了LK_NUMBER 变量 来判断 需要 使用多少的变量 为了区分各种情况把

 

 --过滤掉当前操作人
                   
            -- 过滤不需要返回的人员  属于正则表达式分割
            IF LK_FORWARD_USER IS NOT NULL THEN
                LK_NUMBER := LK_NUMBER + 4;
                V_SQL := V_SQL || 'and ub.USER_ID NOT in (
                SELECT REGEXP_SUBSTR(:LK_FORWARD_USER, ''[^,]+'', 1, ROWNUM) userId
                FROM DUAL
                CONNECT BY ROWNUM <=
                           LENGTH(:LK_FORWARD_USER) -
                           LENGTH(REGEXP_REPLACE(:LK_FORWARD_USER, '','', '''')) + 1)';
            end if;
                   
                    --用户ID过滤
                   IF LK_USER_ID IS NOT NULL THEN
                        V_SQL := V_SQL || 'and ub.USER_ID != :LK_USER_ID ';
                    end if;

                    --查询ID 过滤
                    IF LK_QUERY_USER_ID IS NOT NULL THEN
                        LK_NUMBER := LK_NUMBER + 1;
                        V_SQL := V_SQL || 'and ub.USER_ID like concat(''%'',concat(:LK_QUERY_USER_ID,''%''))';
                    end if;
                    
                    
                if LK_NUMBER = 0 then
                    execute immediate V_SQL using LK_USER_ID;
                elsif LK_NUMBER = 1 then
                    execute immediate V_SQL using LK_USER_ID,LK_QUERY_USER_ID;
                elsif LK_NUMBER = 4 then
                    EXECUTE immediate V_SQL using LK_FORWARD_USER,LK_FORWARD_USER,LK_FORWARD_USER,LK_USER_ID;
                elsif LK_NUMBER = 5 then
                    EXECUTE immediate V_SQL using LK_FORWARD_USER,LK_FORWARD_USER,LK_FORWARD_USER,LK_USER_ID,LK_QUERY_USER_ID;
                end if;

这样就完成了 拼接sql 注入的问题

  • 0
    点赞
  • 2
    评论
  • 1
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

打赏作者

paohui001lqp

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值