[vulnerability]SQL Injection·Entry-level
[漏洞]SQL注入·入门篇
目录
前置知识
漏洞定义
漏洞影响
漏洞发现
漏洞类型
漏洞修复
总结
0x00 前置知识
WEB基础知识
SQL基础知识
sqli-labs环境(可选)
0x01 漏洞定义
SQL注入(英语:SQL injection),也称SQL注入或SQL注码,是发生于应用程序与数据库层的安全漏洞。简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了字符检查,那么这些注入进去的恶意指令就会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏或是入侵。
0x02 漏洞影响
攻击视角
- 通过SQL注入漏洞,可以获取当前业务数据库的所有数据,如果权限控制不当,可以获取数据库中所有数据,以及可以进行数据的修改、删除。
- 如果没有进行安全加固,可以通过SQL注入漏洞,拿到服务器的shell。
防守视角
- 存在SQL注入漏洞,可能导致数据泄露,被拖库、修改数据、删库等危害。
- 可能导致服务器沦陷,攻击者可能会通过此服务器进行入侵内网、挖矿、勒索等攻击行为。
0x03 漏洞发现
SQL注入在不同的数据库中细节有不同,本文以MySQL为例。(常见数据库:MySQL、Oracle、SQL Server、PostgreSQL)
漏洞存在前提
- 网站是动态的
- 使用了数据库
- 存在GET或POST传参(或者cookie参数等其他位置)
漏洞存在位置
下面是一个HTTP请求包的格式
1 |
|
根据上面请求包,注入点可能存在的位置如下:
GET参数中
/?id=homePage
POST参数中
username=harold&email=harold@netspi.com
{
“username”:”harold“,
“email”:”harold@netspi.com“
}harold harold@netspi.com COOKIE参数中
Cookie: user=harold;
HOST中
Host: www.netspi.com
其他HTTP头参数中
XXXXXX: XXX
探测的Payload
测试是否存在漏洞,需要在待测点输入测试语句。
测试语句如下所示:
1 |
|
漏洞发现过程
以sqli-labs 为例,介绍如何发现一个简单的SQL注入漏洞
发现漏洞思路简单整理:
观察URL http://192.168.224.130/sqli-labs/Less-1/?id=1,发现存在一个GET参数**id=1**
测试是否是可控的(即改变参数值会返回不同内容或者发生其他改变)
发现id值不同,返回的Login name 和 Password 是不同的,所以判断是可控的
在参数可控的前提下,使用测试语句进行测试,依次尝试
发现单引号(‘)与双引号(“)的返回不同,而且单引号还触发了一个关键的事件,在网页上显示了SQL语法错误的报错,这是存在SQL注入的标志之一
由于根据步骤3基本可以确定存在SQL注入,那么接下来就是使用语句进行准确论证。使用语句进行闭合
只要语句1返回内容为正常,语句2返回内容为异常(即不存在数据),即可证明存在SQL注入漏洞
0x04 漏洞类型
按参数类型分
根据参数类型,分为数字型和字符型
数字型:参数为数字,注入形式为不需要单双引号
一般使用以下payload来进行探测
and 1=1
and 1=2
字符型:参数为字符串,即各种数字、字母、符号等都可以作为参数,注入形式为需要单双引号闭合
一般使用以下payload来进行探测
‘ and ‘1’=’1
‘ and ‘1’=’2
“ and “1”=”1
“ and “1”=”2
按利用方式分
根据注入点不同响应类型,可以分为联合注入、报错注入、布尔盲注与时间盲注
联合注入:页面返回SQL语句查询的数据,且可以通过union来覆盖返回的数据,可以通过union后面构造语句,来覆盖页面正常显示的信息,用来获取想要获得的数据库的信息或数据。联合注入又叫联合查询注入,是最基础的SQL注入漏洞。(原理是当union前面的语句获取不到数据的时候,会与后面语句结果合并,这样后面语句的结果就为第一行,可以读取出来)
例如:
http://192.168.224.130/sqli-labs/Less-1/?id=%27%20union%20select%201,2,3%20--+
报错注入:页面会返回SQL的报错信息,可以通过构建特殊SQL语句产生的报错信息来获取数据库的信息以及数据。(原理是部分报错语句会带上上一步的数据,可以通过报错信息来获取数据)
例如:
布尔盲注:页面返回的数据与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--+
时间盲注:页面返回的数据与SQL无关,无报错无法使用布尔盲注,可以通过构建判断语句,通过的睡眠(sleep),不通过的不睡眠,然后通过响应时间来获取数据。(原理为判断语句执行不同分支,其中一个分支可以进行睡眠来进行消耗时间,这样不同结果响应时间不同,可以进行差异化区分来获取判断结果)
例如:
一些特殊场景
堆叠注入:正常的注入点只能通过拼接执行一条SQL语句,但是有的注入点可以通过分号(;)来结束第一个SQL语句,然后在后面执行第二条SQL语句,如
二次注入:前面所说的都是注入点的参数可以直接控制,但是有一类注入是先将payload(攻击语句)写入到数据库(或其他长期存储的位置),然后在漏洞位置触发,进行攻击
详情见文章:
0x05 漏洞修复
预编译
使用数据库链接管理的API中提供的预编译技术的方法来执行SQL语句,或者框架中提供的安全API
例如:
PHP中:
MySQLi - bind_param
pdo - bindParam
Java中:
jdbc - PreparedStatement
最推荐的方法,安全性最高,在正确使用的情况下,几乎完全杜绝SQL注入漏洞。
黑名单过滤
过滤以下字符
‘
“
union
and
or
select
--
…等
修复简单方便。缺点是容易被绕过以及影响正常业务(有些正常输入的内容可能会被过滤)。
安全设备
使用WAF、RASP等其他安全产品来防护
适用于不好修复或者没办法修复的SQL注入漏洞,缺点是可被绕过。
0x06 总结
SQL注入产生的原因是服务端执行SQL语句的时候,采用了拼接,而拼接的语句中存在可以被攻击者控制的参数,于是产生了漏洞。
所以寻找漏洞的关键就是找到可控的拼接到SQL语句中的参数。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!