1.参数化查询原理
参数化查询是指在设计与数据库链接并访问时,在需要数值或数据的地方,使用参数来给值。即在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中有恶意的指令,由于已经编译完成,就不会被数据库运行。目前,参数化查询是最有效可预防SQL注入攻击的的防御方法
2.防SQL注入
参数化查询的作用主要有两点:
(1)参数过滤
(2)执行计划重用
防止SQL注入主要就是利用了执行计划重用,即在链接数据库时给参数赋值时,重用了以前的执行计划,没有对SQL语句重新编译,也就没有重新执行语法解析,所以语句还是原来的结构,符合标准,只是用一个具体的值替换参数
以SQL Server为例,数据库接收到一句SQL指令做作的工作如下:
收到指令-->编译SQL生成执行计划-->选择执行计划-->执行执行计划
当SQL Server收到任何一个指令,包括:查询、批处理、存储过程、触发器、预编译指令和动态SQL Server语句,要完成语法解析、语义分析,然后再进行“编译”,生成能够运行的“执行计划”。在编译的过程中,SQL Server 会根据所涉及的对象的架构、统计信息,以及指令的具体内容,估算可能的执行计划,以及它们的成本,最后选择一个SQL Server认为成本最低的语句
执行计划生成之后,SQL Server通常会把它们缓存到内存里,术语统称它们叫“Plane Cache”。以后同样的语句执行,SQL Server就可以使用同样的执行计划,而无须再做一次编译。这种行为,叫做“重用”。但是有时候,哪怕是一模一样的语句,SQL Server下次执行还是要再做一次编译。这种行为叫“重编译”。执行计划的编译和重编译都是要耗费资源的
3.实例
原始SQL:
SELECT COUNT(*) FROM USERS WHERE PASSWORD = 'A' AND USERNAME = 'B'
结果:
原始SQL执行结果注入SQL:
这里有人将UserName设置为了"b' or 1=1 –"
SELECT COUNT(*) FROM USERS WHERE PASSWORD = 'A' AND USERNAME = 'B' OR 1=1—'
结果:
注入SQL执行结果任何动态的执行SQL都有注入的风险,因为动态意味着不重用执行计划,而如果不重用执行计划的话,那么就基本上无法保证你写的SQL所表示的意思就是你要表达的意思
这就好像小时候的填空题,查找密码是(____) 并且用户名是(____)的用户,不管你填的是什么值,我所表达的就是这个意思, 存储过程也是一样的道理,因为可以重用执行计划
参考:
https://blog.csdn.net/wrs120/article/details/54924763
https://blog.csdn.net/andong154564667/article/details/81117616
网友评论