[vulnerability]SQL Injection·Entry-level

[漏洞]SQL注入·入门篇

目录

  1. 前置知识

  2. 漏洞定义

  3. 漏洞影响

  4. 漏洞发现

  5. 漏洞类型

  6. 漏洞修复

  7. 总结

0x00 前置知识

WEB基础知识

SQL基础知识

sqli-labs环境(可选)

0x01 漏洞定义

SQL注入(英语:SQL injection),也称SQL注入SQL注码,是发生于应用程序与数据库层的安全漏洞。简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了字符检查,那么这些注入进去的恶意指令就会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏或是入侵。

0x02 漏洞影响

攻击视角

  1. 通过SQL注入漏洞,可以获取当前业务数据库的所有数据,如果权限控制不当,可以获取数据库中所有数据,以及可以进行数据的修改、删除。
  2. 如果没有进行安全加固,可以通过SQL注入漏洞,拿到服务器的shell。

防守视角

  1. 存在SQL注入漏洞,可能导致数据泄露,被拖库、修改数据、删库等危害。
  2. 可能导致服务器沦陷,攻击者可能会通过此服务器进行入侵内网、挖矿、勒索等攻击行为。

0x03 漏洞发现

SQL注入在不同的数据库中细节有不同,本文以MySQL为例。(常见数据库:MySQL、Oracle、SQL Server、PostgreSQL)

漏洞存在前提

  1. 网站是动态的
  2. 使用了数据库
  3. 存在GET或POST传参(或者cookie参数等其他位置)

漏洞存在位置

下面是一个HTTP请求包的格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
POST /?id=homePage HTTP/1.1
Host: www.netspi.com
Connection: close
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
X-Server-Name: PROD
Cookie: user=harold;

username=harold&email=harold@netspi.com

// 上面为一个完整包,下面是POST参数的其他形式
{
"username":"harold",
"email":"harold@netspi.com"
}


<root>
<username>harold</username>
<email>harold@netspi.com</email>
</root>

根据上面请求包,注入点可能存在的位置如下:

  1. GET参数中

    /?id=homePage

  2. POST参数中

    username=harold&email=harold@netspi.com

    {
    “username”:”harold“,
    “email”:”harold@netspi.com
    }

    harold harold@netspi.com
  3. COOKIE参数中

    Cookie: user=harold;

  4. HOST中

    Host: www.netspi.com

  5. 其他HTTP头参数中

    XXXXXX: XXX

探测的Payload

测试是否存在漏洞,需要在待测点输入测试语句。

测试语句如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 注:仅列举部分,不同注入点的闭合不相同。
-- 简单测试语句
'
"
2-1

-- 布尔测试语句
' and '1'='1
' and '1'='2
and 1=1
and 1=2

-- 时间盲注测试语句
" and if(left(version(),1)='5',sleep(10),sleep(10))--+
' and if(left(version(),1)='5',sleep(10),sleep(10))--+

漏洞发现过程

以sqli-labs 为例,介绍如何发现一个简单的SQL注入漏洞

发现漏洞思路简单整理:

  1. 观察URL http://192.168.224.130/sqli-labs/Less-1/?id=1,发现存在一个GET参数**id=1**

    漏洞发现1

  2. 测试是否是可控的(即改变参数值会返回不同内容或者发生其他改变)

    http://192.168.224.130/sqli-labs/Less-1/?id=2

    http://192.168.224.130/sqli-labs/Less-1/?id=3

    http://192.168.224.130/sqli-labs/Less-1/?id=4

    发现id值不同,返回的Login name 和 Password 是不同的,所以判断是可控的

    漏洞发现2

    漏洞发现3

    漏洞发现4

  3. 在参数可控的前提下,使用测试语句进行测试,依次尝试

    http://192.168.224.130/sqli-labs/Less-1/?id=1'

    http://192.168.224.130/sqli-labs/Less-1/?id=1"

    发现单引号(‘)与双引号(“)的返回不同,而且单引号还触发了一个关键的事件,在网页上显示了SQL语法错误的报错,这是存在SQL注入的标志之一

    漏洞发现5

    漏洞发现6

  4. 由于根据步骤3基本可以确定存在SQL注入,那么接下来就是使用语句进行准确论证。使用语句进行闭合

    http://192.168.224.130/sqli-labs/Less-1/?id=1' and ‘1’=’1

    http://192.168.224.130/sqli-labs/Less-1/?id=1' and ‘1’=’2

    只要语句1返回内容为正常,语句2返回内容为异常(即不存在数据),即可证明存在SQL注入漏洞

    漏洞发现7

    漏洞发现8

0x04 漏洞类型

按参数类型分

根据参数类型,分为数字型字符型

  1. 数字型:参数为数字,注入形式为不需要单双引号

    一般使用以下payload来进行探测

    and 1=1

    and 1=2

  2. 字符型:参数为字符串,即各种数字、字母、符号等都可以作为参数,注入形式为需要单双引号闭合

    一般使用以下payload来进行探测

    ‘ and ‘1’=’1

    ‘ and ‘1’=’2

    “ and “1”=”1

    “ and “1”=”2

按利用方式分

根据注入点不同响应类型,可以分为联合注入报错注入布尔盲注时间盲注

  1. 联合注入:页面返回SQL语句查询的数据,且可以通过union来覆盖返回的数据,可以通过union后面构造语句,来覆盖页面正常显示的信息,用来获取想要获得的数据库的信息或数据。联合注入又叫联合查询注入,是最基础的SQL注入漏洞。(原理是当union前面的语句获取不到数据的时候,会与后面语句结果合并,这样后面语句的结果就为第一行,可以读取出来)

    例如:

    http://192.168.224.130/sqli-labs/Less-1/?id=%27%20union%20select%201,2,3%20--+

    联合注入

  2. 报错注入:页面会返回SQL的报错信息,可以通过构建特殊SQL语句产生的报错信息来获取数据库的信息以及数据。(原理是部分报错语句会带上上一步的数据,可以通过报错信息来获取数据)

    例如:

    http://192.168.224.130/sqli-labs/Less-1/?id=1%27%20and%20(select%20count(*)%20from%20information_schema.tables%20group%20by%20concat((select%20version()),floor(rand(0)*2)))--+

    报错注入

  3. 布尔盲注:页面返回的数据与SQL无关或者不能用联合注入与报错注入的情况,且在SQL语句不同时页面会有不同的展示,通过构建逻辑不同的语句来对信息和数据进行猜测,来获取信息和数据。(原理是通过构建判断语句,根据页面的返回来看到判断语句是否为真)

    例如:

    http://192.168.224.130/sqli-labs/Less-8/?id=1%27%20and%20ascii(substr(database(),1,1))=115%20--+

    http://192.168.224.130/sqli-labs/Less-8/?id=1%27%20and%20ascii(substr(database(),1,1))=116%20--+

    布尔盲注1

    布尔盲注2

  4. 时间盲注:页面返回的数据与SQL无关,无报错无法使用布尔盲注,可以通过构建判断语句,通过的睡眠(sleep),不通过的不睡眠,然后通过响应时间来获取数据。(原理为判断语句执行不同分支,其中一个分支可以进行睡眠来进行消耗时间,这样不同结果响应时间不同,可以进行差异化区分来获取判断结果)

    例如:

    http://192.168.224.130/sqli-labs/Less-9/?id=2%27%20and%20if(left(version(),1)=%275%27,sleep(10),sleep(10))--+

    时间盲注

一些特殊场景

  1. 堆叠注入:正常的注入点只能通过拼接执行一条SQL语句,但是有的注入点可以通过分号(;)来结束第一个SQL语句,然后在后面执行第二条SQL语句,如

    http://192.168.224.130/sqli-labs/Less-38/?id=1%27%20;%20insert%20into%20users(id,username,password)values(%27101%27,%27lqs1%27,%27lqs1%27)%20--+

  2. 二次注入:前面所说的都是注入点的参数可以直接控制,但是有一类注入是先将payload(攻击语句)写入到数据库(或其他长期存储的位置),然后在漏洞位置触发,进行攻击

    详情见文章:

    https://www.jianshu.com/p/3fe7904683ac

0x05 漏洞修复

  1. 预编译

    使用数据库链接管理的API中提供的预编译技术的方法来执行SQL语句,或者框架中提供的安全API

    例如:

    PHP中:

    MySQLi - bind_param

    pdo - bindParam

    Java中:

    jdbc - PreparedStatement

    最推荐的方法,安全性最高,在正确使用的情况下,几乎完全杜绝SQL注入漏洞。

  2. 黑名单过滤

    过滤以下字符

    union

    and

    or

    select

    --

    …等

    修复简单方便。缺点是容易被绕过以及影响正常业务(有些正常输入的内容可能会被过滤)。

  3. 安全设备

    使用WAF、RASP等其他安全产品来防护

    适用于不好修复或者没办法修复的SQL注入漏洞,缺点是可被绕过。

0x06 总结

​ SQL注入产生的原因是服务端执行SQL语句的时候,采用了拼接,而拼接的语句中存在可以被攻击者控制的参数,于是产生了漏洞。

​ 所以寻找漏洞的关键就是找到可控的拼接到SQL语句中的参数。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!