CTF场景下为什么MySQL反引号查询会返回预期外的表数据?
反引号查询行为的核心逻辑拆解
基础规则澄清
- MySQL中反引号是标识符引用符,作用是包裹列名、表名等数据库对象名称,和编程语言中代表字符串的引号语义完全不同,不会被解析为字符串值
- SQL中等值比较的运算规则为左结合,不存在链式等值判断的内置语义。也就是说
A = B = C的实际执行顺序是:先计算(A = B)得到一个布尔数值结果,再把这个结果和C做等值比较,完全不等价于A=B AND B=C - 跨类型比较的隐式转换规则:当数字和字符串做等值判断时,MySQL会尝试将字符串转为数字;如果字符串以非数字开头,转换结果为0
两次查询结果的逐行推演
返回全表的查询语句
select * from myTable where first = second = 'anyString';
按照左结合规则拆分为两步执行:
- 先计算括号内的第一级比较:
(first =second)
逐行对比当前行first列值和同名列second的存储值:- 第1行:
first_data对比second_data,不相等,得到比较结果0 - 第2行:
third_data对比fourth_data,不相等,得到比较结果0
- 第1行:
- 再计算第二级比较:拿第一步的结果和字符串值做判断,即
0 = 'anyString'
按照隐式转换规则,非数字开头的anyString转数字结果为0,因此0=0结果为真,所有行都满足过滤条件,最终返回全表数据。
返回空集的查询语句
select * from myTable where first = first = 'anyString';
同样按左结合规则拆分为两步执行:
- 先计算第一级比较:
(first =first)
拿当前行first列值和自身做对比,所有行的比较结果都为相等,得到统一结果1 - 再计算第二级比较:
1 = 'anyString'
字符串anyString转数字结果为0,因此1 = 0结果为假,没有行满足过滤条件,最终返回空集。
关联CTF场景的考点逻辑
这类异常本质是输入语法被数据库引擎错位解析:题目中前端传入的JavaScript对象字段常带有反引号(作为JS模板字符串、动态属性的标识),如果后端直接把这类带反引号的输入拼进SQL语句,没有做转义处理,就会把本该作为字符串值的输入当成数据库列名解析,进一步触发连续等值比较的逻辑漏洞,造成过滤条件完全失效。
注:查询返回的1条警告,就是MySQL检测到字符串与数字隐式转换时的常规提示,不影响上述逻辑的执行结果。
内容的提问来源于stack exchange,提问作者Ayberk Eser
相关产品推荐
相关产品推荐

