MySQL的查询操作逻辑

就select语句而言:
(来自官方手册)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...]
[FROM table_references
[PARTITION partition_list]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]

Mysql对于一句select query的处理是从最上面的子句执行,每执行一句子句就生成虚拟表V,将虚拟表V作为下一个子句的输入,如果没有遇到子句则跳过寻找下一个可能的子句,直到执行到最后一个子句。将生成的最后一个表返回到用户界面,而执行顺序中的虚拟表对用户是透明的。其他语法的查询均遵从这一方法。
而报错注入的特性是当执行到执行到报错函数处,停止后面语句的执行并抛出错误到用户界面。基于这一特点,可以构造出并不符合语法规则的报错语句。在 http://blog.csdn.net/niexinming/article/details/55001126 中mysql执行的语句是:sql update `table` t left join (select char(97) as user from dual where (extractvalue(1,concat(0x7e,(select user()),0x7e)))) tt on tt.user=`t.username` set username ='admin' where id=1;修改为:sql update `users` t left join (select (extractvalue(1,concat(0x7e,(select user()),0x7e)))) tt on tt.a=`t.a` set username ='admin' where id=1;依然可以执行。但由于子查询优先级低于主句,因此不可以改变join on语法的完整性。
另外小密圈里有人问select * from test_*** 中的*可控,但是没有test_存在的表,能否注入。回答是不可以的,因为执行到from前没有可控内容,from就会被优先执行,由于表不存在,就会立刻退出并不执行后面的句子,因此是不可以注入的。如果有师傅有什么注入的姿势还请指教

支持一下
扫一扫,支持forsigner