为什么数据库会被绕晕并交出所有人的数据? 因为我原本只让数据库查“名字叫张三的”,但我加了 or 1=1。在数据库眼里,1永远等于1,这个条件是绝对成立的。所以它判断:“即使名字不是张三,只要1等于1,也算符合条件。”这样一来,数据库里每一条数据都满足这个永真条件,它只能老老实实把所有人的数据全部交出来。
一句话总结:前端输入的字符,后端不加验证直接当代码执行了,这就是字符型注入。
二、结合源码的大白话理解
我们来看一眼后端实际的源码: select id,email from member where username=‘$name’ 这里的 $name 就是专门用来接收前端输入内容的变量。
正常输入 kobe 时,后端执行代码为: select id,email from member where username=‘kobe’ 所以只查出 kobe 一个人的数据。
但是,我输入了:kobe’ or 1=1 #。因为后端没有做严格检查,直接将我的输入拼接到代码里,导致后端执行的完整代码变成了: select id,email from member where username=‘kobe’ or 1=1 #’ 这串代码直接绕过了原本的验证逻辑,把数据库里所有人的数据全交了出来。
三、Payload构造与原理拆解(三部曲)
Payload构造语句:kobe’ or 1=1 # 它总共分三步,完美构成了漏洞利用的闭环。
闭合引导(第一步:kobe’) 为什么叫字符型?因为输入的是文字。后端用 ‘$name’ 将其包裹。我输入 kobe’ 后,后端拼接的完整代码变成了: select id,email from member where username=‘kobe’’ 多出来的单引号提前闭合了原本的引号边界,打破了后端代码原本的语法结构,为后续注入铺路。
构造永真条件(第二步:or 1=1) or 是逻辑“或”。A or B 只要其中一个成立,整体就成立。而 1=1 是一个永远为真的条件,在安全领域我们称它为永真条件。我接着输入 or 1=1,后端的完整拼接代码变成了: select id,email from member where username=‘kobe’ or 1=1’ 数据库判断:“即使名字不是kobe,只要1等于1也行。”于是直接返回了数据库中所有的数据。
注释截断(第三步:#) 后端源码末尾还有一个单引号 ’ 用来收尾。如果不处理它,系统执行时会报错。我输入井号 #,后端的完整拼接代码变成了: select id,email from member where username=‘kobe’ or 1=1 #’ 井号在数据库里是注释符,它告诉数据库从它开始往后的内容全部忽略。这个动作阻止了报错,让注入完美执行。