0x00 Mybatis框架
# 的$ 的区别
# 号会点语句进行预编译${ } 只是进行string 替换,动态解析SQL的时候会进行变量替换
0x01 预编译一些场景下的局限
select * from `user`
select * from 'user' #报错,表名不能使用单引号
select * from user order by name
select * from user order by 'name' # 语义发生改变,没有排序的效果了
0x02 之前有听人说order by后面的语句是不会参与预编译?
这句话是错误的。Order by也是会参与预编译的。从我们上面的jdbc的setString算法可以看到,是因为setString会在参数的前后加上’’,变成字符串。导致order by失去了原本的意义。只能说是预编译方式的order by不适用而已。所以对于这种order by的防御的话建议是直接写死在代码里面。对于order by方式的注入我们可以通过返回数据的顺序的不同来获取数据。
0x03 为什么预编译能让传入的数据只能是数据,它的底层原理是怎样的?
通常来说,一条SQL语句从传入到运行经历了生成语法树、执行计划优化、执行这几个阶段。在预编译过程中,数据库首先接收到带有预编译占位符?的SQL语句,解析生成语法树(Lex),并缓存在cache中,然后接收对应的参数信息,从cache中取出语法树设置参数,然后再进行优化和执行。由于参数信息传入前语法树就已生成,执行的语法结构也就无法因参数而改变,自然也就杜绝了SQL注入的出现。这样一个深刻而简单的原因,相信已经解答了我们最开始的疑问。
|