• 为什么SQL预编译可以防止SQL注入攻击


    前言

    防范SQL注入攻击是每一位做后端开发的程序员必须会的基本功。本文介绍其中一种防范攻击的方法:SQL预编译。

    本文大部分内容引用自这篇文章,部分内容有修改。

    注入例子

    先简单回顾下SQL注入攻击的过程,假设有一个SQL语句:

    SELECT * FROM users WHERE id = '{$p}';
    
    • 1

    {$p}是用户传递过来的查询参数,假设用户传递的参数是123,则SQL会是:

    SELECT * FROM users WHERE id = '123';
    
    • 1

    但如果用户传递的参数是';DROP TABLE users;-- ,SQL就会变成:

    SELECT * FROM users WHERE id = '';DROP TABLE users;-- ';
    
    • 1

    原本一个简单的SELECT语句,通过精心构造查询参数,就让它变成了一个删除users表的语句!

    从注入的过程可以发现,如果用户传递过来的参数,我们不做任何处理就拼接到SQL语句中,很容易就会让黑客改变我们SQL语句的语法结构,引发严重事故。

    解决方法

    一、对用户参数进行转义

    对一些有特殊意义的字符,例如单引号,进行转义,转义后再去数据库查询,相信很多人都知道这种做法,本文就不详细讲了。

    二、SQL预编译

    本文说的预编译,是指在数据库端进行的预编译。有部分代码库的预编译是在客户端本地进行的,这种是虚假的“预编译”。

    通过SQL预编译,可以防止语法结构被改变。先了解下SQL的执行过程:

    1. 词法分析:将SQL语句分解成一个个token(关键字、标识符、运算符),然后对token进行分类和解析,生成相应的数据结构。
    2. 语法分析:根据SQL语法检测规则检查语法是否正确,并成成语法树。
    3. 语义分析:遍历语法树,确定表和列等信息,同时检查语义的正确性。
    4. 优化处理:使用优化器对SQL语句进行处理和优化,比如执行计划、索引等。
    5. 执行计划:使用执行计划生成器生成SQL语句的执行计划,比如数据的访问方式,索引的使用方式等。
    6. 引擎执行:将执行计划发送给相应的数据库引擎进行处理,执行计划被翻译成底层的操作指令,执行数据扫描、索引查找、排序、分组等操作。
    7. 返回数据:将执行结果返回给客户端,比如查询结果集或操作结果。

    在这里,我们粗暴的把执行过程理解成两步,即:先编译SQL语法结构(1~3步),再执行SQL语句(4~7步)。

    正常情况下,用户输入的参数会直接参与SQL语法的编译,而预编译则是先构建语法树,确定SQL语法结构以后,再拼接用户的参数。

    2.1 预编译原理

    预编译最初的目的是提高SQL语句的执行效率,因为有很多语法结构相同,但只有参数值不同的SQL,比如:

    SELECT * FROM users WHERE id = '1';
    SELECT * FROM users WHERE id = '2';
    
    • 1
    • 2

    这些SQL的语法树相同,但每次都要进行重复的编译,很浪费时间。

    而预编译可以将SQL语句模板化,值的位置用占位符替代,这样数据库就会事先编译好SQL语法结构,等真正调用的时候,再传入参数值执行,省掉了重复建立语法树的时间。

    SELECT * FROM users WHERE id = {占位符}
    
    • 1

    因为语法树已经建立好了,要查询什么表、查询字段是哪些、有多少个查询条件等等这些全都已经确定好了,用户传入的参数不参与语法树的构建,就改不了SQL的语法结构,也就避免了注入。

    2.2 预编译的局限性

    预编译的机制是先编译,再传值,用户传递的参数无法改变SQL语法结构,从根本上解决了SQL注入的问题。

    但并不是所有参数都可以使用预编译,比如动态表名和列名的场景,因为语义分析时,会解析语法树,检查表名和列名是否存在,所以表名和列名不能被占位符替代,也就无法使用预编译。

    同理,排序场景的ASC/DESC也不能使用预编译。

    参阅

  • 相关阅读:
    qt定时器的使用
    SpringBootWeb登录认证
    使用 SAP UI5 sap.ui.export.Spreadsheet API 进行 Excel 导出的一些限制
    (附源码)计算机毕业设计SSM基于框架的旅游管理系统
    Objective-C中的KVO
    python输出多维数组最大值、最小值和指定值的全部索引值index
    市政管理学考试复习资料
    缓存和DB一致性
    Linux Ubunto Nginx安装
    [附源码]java毕业设计基于Web留学管理系统
  • 原文地址:https://blog.csdn.net/ljfrocky/article/details/133356906