SQL预编译的理解分享

SQL注入的产生与预编译

SQL注入是将SQL语句进行拼接和修改导致数据库进行错误的查询,而预编译进行了语句先行编译再进行传参数与传统式拼接语句不一样。
接下来我以个人的理解从代码视角进行解析预编译

预编译讲解

SQL执行流程

想了解SQL预编译就要知道SQL语句输入完成后,SQL会进行以下流程将我们的SQL语句进行处理

  1. 词法分析(Lexical Analysis):将SQL语句分解为一个个的词法单元,如关键字、标识符、运算符、常量等。

  2. 语法分析(Syntax Analysis):根据语法规则,将词法单元组合成语法结构,形成语法树(Parse Tree)或抽象语法树(Abstract Syntax Tree)。

  3. 语义分析(Semantic Analysis):对语法树进行语义检查,包括检查表名、列名的正确性,检查数据类型的匹配性,以及执行权限的验证等。

  4. 查询优化(Query Optimization):对SQL语句进行优化,选择最优的执行计划。优化的目标包括提高查询性能、减少资源消耗等。

  5. 执行计划生成(Execution Plan Generation):根据优化后的查询计划生成执行计划,执行计划定义了执行SQL语句的具体步骤和顺序。

  6. 数据访问(Data Access):根据执行计划,访问数据库中的数据。这可能涉及到磁盘I/O操作、索引的使用、锁的管理等。

  7. 数据处理(Data Processing):对访问到的数据进行处理,如排序、聚合、连接等操作,以得到最终的结果。

  8. 结果返回(Result Return):将处理后的结果返回给应用程序或客户端,供后续的处理或展示。

总体看上会比较抽象,简单概括就是:解析语句-》分析语句有无错误-》进行优化-》创建执行-》返回结果

SQL预编译

select * from users where id=1;
这个是个正常的SQL语句,当这个语句进入到SQL里面就会进行以上刚刚的SQL流程处理,返回一定的结果

在进行SQL注入的情况的时候,会添加and 1=2,造成以下语句

select * from users where id=1 and 1=2;

这时候,会进行二项查询分别是id=1的结果与1=2的结果进行运算,造成SQL注入;

我们将总体流程拿下来进行使用,可以看成语句:

select * from users where id=1;

在SQL界面输入完成并回车后,SQL引擎会将这个语句进行检查分析将其编译成为一个用于查询user表id的一个函数(def)并且去执行它,那么SQL注入的原理也是如此

select * from users where id=1 union select database(),user(),3,4;

SQL检查传输的语句的本意是查询users表里面id=1的情况,但是SQL注入的原因使语句不仅变成了查user表同时还查询database(),user();于是SQL将这个语句的需求,进行编写功能写成函数(def)并进行执行,将结果返回给用户,造成SQL注入。


SQL的预编译是采用占位符,进行提前编译,请看语句

select * from user where id=?;

预编译采用提前编译形式,将问号位进行占位,让SQL引擎进行功能编译

SQL引擎查询到语句的意思是:需要查询user表里面的数据,具体是谁?不知道,先编译功能

于是将功能编译成一个需要传参的函数,如果说之前的语句功能是

def userid1():

那么现在的功能就是

def userid(id):

整体的大致框架已经编写完成,这个框架就是用来查询user表的,你查不了别的,你随便传参但是它的功能就已经规定死了
你基本上不可能拿一个上传文件的功能去完成一个SQL查询的动作;

而且在经过预编译的一些处理机制,大致上会将一些标点符号去除,或者进行转义

因此当我们传参的时候就成为了以下这样
def userid(1'and#): 

但是更多的是实际上传入是
def userid(1) 

正确的数据
呃,只能说是你随便传,反正我的功能就这样,有就是有,没有就是没有咯



posted @ 2025-05-04 21:21  枫叶天凝  阅读(26)  评论(0)    收藏  举报