米桃安全漏洞讲堂系列第1期:SQL注入漏洞

一、概述

漏洞原理

所谓SQL 注入,即攻击者猜测Web系统的数据验证过程,在输入数据的最后加上一段SQL语句,让服务器端的SQL执行出现偏差,最终达到欺骗服务器执行恶意SQL命令

SQL注入的本质为对输入检查不充分,导致SQL语句将用户提交的非法数据当作语言的一部分来执行,即拼接SQL命令。如:

java 复制代码
uname = request.POST['username']
password = request.POST['password']
sql = "SELECT all FROM users WHERE username='" + uname + "' AND password='" + password + "'"
database.execute(sql)

上面这段程序直接将客户端传过来的数据写入到数据库。试想一下,如果用户传入的 password 值是: "password' OR 1=1",那么 sql 语句便会变成:

sql 复制代码
sql = "SELECT all FROM users WHERE username='username' AND password='password' OR 1=1"

那么,这句 sql 无论 username 和 password 是什么都会执行,从而将所有用户的信息取出来。

漏洞类型分类

  • 注入点分为两类:数字型注入、字符型注入
  • 请求方式分类四类:GET注入、POST注入、Cookie注入、HTTP Header注入
  • 是否回显分类:显注、盲注

漏洞危害

1、数据库敏感数据被黑客窃取(即"拖库"),造成关键业务数据、用户认证信息等泄漏。如企业经营信息或员工重要信息泄漏,会引发严重后果。

2、数据库敏感数据被黑客修改(网页篡改、挂马),造成系统运行异常,或者业务流程异常执行,以达到黑客的恶意目的。

3、黑客取得数据库管理员权限 ,通过写入文件操作将木马(webshell)等恶意执行文件写入服务器操作系统。运行恶意执行文件,获取服务器及内网其他服务器的系统管理员权限,完全控制服务器。 鉴于SQL注入的危害性,漏洞一经发现,漏洞级别通常为高危或严重级别

SQL注入位置

GET、POST、HTTP头部注入,Cookie注入,任何客户端可控,传递到服务器的变量。只要应用程序涉及到数据库查询的位置,都有SQL注入存在的隐患。而如果查询参数,需要用户参与,则这些位置,就是注入漏洞经常被利用的地方。常见位置:

  • 表单(常用语绕过认证)
  • 下拉列表(遍历数据库表)
  • 附带查询参数的URL中(盲注猜解数据库)

SQL注入漏洞防御措施:

  • 参数化查询(推荐)
  • 验证用户的输入的合法性
  • 正确使用框架调用数据库
  • 限制应用用户数据库操作权限

二、测试方法

一次完整的SQL注入漏洞利用,主要分为四个阶段。

(a)发现注入点(有无回显)

(b)数据库信息搜集

(c)数据获取

(d)提权、权限维持

寻找注入点是整个SQL注入漏洞利用过程的第一步,也是最重要的一步。通常测试方法可分为手工注入、自动化工具注入。

2.1、手工注入

我们可以通过观察一个请求不同参数的服务端返回结果,判断是否存在SQL注入漏洞。 以最简单的Get请求数字型注入为例。第一条请求为默认请求。第二条请求增加了参数" and 1=1 "。第三条请求增加了参数" and 1=2 "。

html 复制代码
www.abc.com/index.php?id=2
www.abc.com/index.php?id=2 and 1=1
www.abc.com/index.php?id=2 and 1=2

若第2条请求返回正常,第3条返回不正常说明id参数,后面的请求在数据库中被当作了sql语句执行,即id参数存在注入漏洞。

类似的判断payload可参考如下。各数据库通用。可在开发测试阶段进行测试。

sql 复制代码
通用payload:
'
 or 1=1
a' or 1=1
a' or 1=1#
1' or '1'='1
1') or ('1'='1

a" or 1=1#
a" or "1"="1
123" or "1"="1
a' OR 1=1 OR '1'='1
a" or 1=1 or "1"="1
a" or 1=1 or "1"="1#
' and 1=1 --#
' and 1=2 --#
'and 1=1 and '%'='
%' and 1=1--'
%' and 1=1 and '%'='

SQLSERVER:
1 or 'ab'='a'+'b'
1) or ('ab'='a'+'b'
1' or 'ab'='a'+'b
1') or ('ab'='a'+'b

MySQL:
1 or 'ab'='a' 'b'
1) or ('ab'='a' 'b'
1' or 'ab'='a' 'b
1') or ('ab'='a' 'b

Oracle:
1) or ('ab'='a' 'b'
1) or ('ab'='a'‖'b'
1' or 'ab'='a'‖'b
1') or ('ab'='a'‖'b

找到注入点后,进入第二阶段,就可以使用各种组合的sql语句去查询数据库信息。

获取当前数据库用户权限、数据库版本

(1)此处针对name参数,使用攻击语句, -1')and (extractvalue(1,concat(0x7e,(select user()),0x7e))) -- 进行注入。后端返回数据库用户名、ip信息(左侧为请求报文,右侧为应答报文,下同)。

(2)继续针对name参数查询数据库名: -1')and (extractvalue(1,concat(0x7e,(select database()),0x7e))) -- 获取数据库名。

使用二分法猜解数据库名、表名、列名

上述例子针对的是具有回显的SQL注入。如果非回显注入(盲注),系统只返回正常与不正常,则需使用二分法进行猜解。

  1. 数据库名长度猜解

假设已确认注入点,且为盲注点。猜解数据库名,首先需判断数据库名长度。 针对注入点"startDate"执行判断语句为: 'and(1=if((length(database())=7),1,(select 1 union select 2)))and' '=' 这里,database())=7,数字即为数据库长度,可从1-20进行尝试,若系统返回正常,则说明数据库名称猜解正确。

如下,当数据库名长度为6或8时,系统均提示无数据,当数据库名为7时,系统返回数据。

(2)数据库名猜解 当数据库名长度猜解出为7后,需要依次确定是哪七个字符。此处依然通过是否回显判断猜测结果。 对注入点"startDate"参数,使用攻击语句 :'and(1=if((mid(database(),§3§,1)='§e§'),1,(select 1 union select 2)))and''=' 进行探测。

配合抓包工具burpsuite自动化intruder探测模块,批量发包,快速查看返回结果。

攻击密码字典。数据库长度为7,故第一个参数字典为1-7。数据库名组成包括26位字母(不区分大小写)、0-9数字、下划线、中划线,故第二个穷举参数包括38个字符。配置如下:

发起批量请求,通过返回报文长度,我们就能确认7位数据库名长度,每一位上的字符内容。重新梳理后,可得到数据库名为vie_biz

至此,我们通过手工方式,完成了数据库名的猜解。同理,依次猜解表名、列名。获取上述数据后,整张数据库表信息均可查询。提权步骤属于后渗透内容,不在本文讨论范围,不赘述。

综上,在找到SQL注入点后,SQL注入流程可总结如下:

2.2、自动化工具注入(Sqlmap)

上述手工注入法,对于我们理解sql注入的流程非常有帮助。但劣势也很明显,需要尝试不同的攻击payload,猜解数据库信息费时费力。针对该问题,自动化注入工具Sqlmap应运而生。

Sqlmap是一款开源的命令行自动SQL注入工具。它由Bernardo Damele A.G.和 Daniele Bellucci 以 GNU GPLv2 许可证方式发布,可从 github.com/sqlmapproje... 上下载。

其主要功能是扫描,发现并利用给定的URL的SQL注入漏洞,目前支持的数据库是MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase和SAP MaxDB。采用五种独特的SQL注入技术,分别是:

1)基于布尔的盲注,即可以根据返回页面判断条件真假的注入。

2)基于时间的盲注,即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。

3)基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。

4)联合查询注入,可以使用union的情况下的注入。

5)堆查询注入,可以同时执行多条语句的执行时的注入。

以某个sql漏洞为例,针对serviceName参数进行注入攻击。 使用语句:

sql 复制代码
sqlmap.py -u https://xxxx.zhongan.com/123456.json?serviceName=0 --level=5 --dbs

攻击语句参数中,--dbs表示探测数据库名,--level=5表示探测复杂程度,分1-5级,5级表示最复杂。

通过返回内容我们可以看到,sqlmap探测出目标服务后端使用MySQL数据库,版本大于5.0.12。数据库包含4个库,以及相应的库名

若需要更详细的探测,可通过更改参数,探测具体的表名、字段名,以及表中的数据。此处不赘述。

三、防御措施

如何预防SQL注入问题,首先需要明确漏洞形成的原因,主要有两个:

  • 缺少用户输入验证
  • 数据和控制结构合同在同一个传输通道中(SQL语句拼接)

针对SQL注入问题,OWASP(全球开源组织)提供了如下防护建议:

(a)参数化查询(推荐)

(b)验证用户的输入的合法性

(c)正确使用框架调用数据库

(d)限制应用用户数据库操作权限

针对上述四个方面防护,我们结合实际,逐一说明如何落地实施。

(a)参数化查询

最佳编程实践是使用参数化查询方式也称为预编译方式执行SQL语句,目前成熟的框架都准备了安全的方法供开发人员调用。

值得注意的是,某些安全方法如果调用不当的话,仍然存 在SQL注入的问题。例如使用java内置安全方法prepareStatement:

sql 复制代码
String sql="select * from user where name="+Name;
conn.prepareStatement(sql).executeUpdate();

虽然使用了安全方法,但仍是以字符串拼接的形式进行调用,系统存在SQL注入漏洞。正确的 使用方式是通过占位符的形式进行调用:

sql 复制代码
pst = conn.prepareStatement("select * from user where name= ?");
rs = pst.setString(1, user.getUsername()).executeQuery();

(b)验证用户的输入的合法性

验证用户的输入。即通过前端或后端的方式过滤用户输入内容,如白名单、黑名单。 使用白名单方式,只符合特定场景,但效果显著。

使用黑名单方式,适用范围广。若由于客观原因不能使用参数化查询方式执行SQL语句,则可过滤以下特殊字符等危险 输入:

java 复制代码
String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|* |%|chr|mid|master|truncate|char|declare|sitename|net user|xp_cmdshell|;|or| -|+|,|like'|and|exec|execute|insert|create|drop|table|from|grant|use|group_co ncat|column_name|information_schema.columns|table_schema|union|wher e|select|delete|update|order|by|count|*|"+ "chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";

另外,也可以增加限制用户输入内容格式限制(类型、长度),增加防护效果。

以上防护措施,均建议通过后端实现。普通前端验证,通过抓包可绕过前端防护。

(c)正确使用框架调用数据库(mybatis、ibatis等)

若使用ibatis、MyBatis框架调用数据库。对于ibaits参数引用可以使用#和$两种写法, 其中#写法会采用预编译方式,将转义交给了数据库,不会出现注入问题。

如果采用$写法,则相 当于拼接字符串,会出现注入问题,正确使用如下:

sql 复制代码
select * from user where name =#Name#

like语句需要根据使用的数据库类型进行如下调整:

java 复制代码
MySQL数据库:CONCAT('%',#param#,'%')
Oracle数据库:' % '|| '#param#'||' % '
MSSQL数据库:' % ' +#param# + ' % '

总结为:#为预编译,$为拼接

(d)限制应用用户数据库操作权限

遵循软件开发中的最小权限原则。在保证使用功能正常的前提下,尽量使用低权限账号 ,并且尽可能回收操作权限

四、企业安全防护措施

企业针对SQL注入的防护可以微软提出的SDL(软件安全开发周期Security Development Lifecycle)来划分,包含如下领域:

4.1、应用上线前

4.1.1、安全开发培训

安全团队可对公司技术研发团队成员开展安全开发相关培训。宣导通用安全漏洞的研发侧防御方法。

以及在需求阶段,可加入安全方面考虑,如业务逻辑风险防范等。

4.1.2、研发阶段

研发人员按照预定的预定的业务逻辑完成开fb,并能正确调用相关研发组件安全防御函数。

4.1.3、测试阶段

  • SAST源码扫描

通过源代码安全扫描,可发现非用户输入功能点的SQL注入,例如orderby排序参数等,作为人工测试的有力补充。常见的源码扫描工具如fortify、checkmarks等。

  • IAST灰盒工具扫描

IAST称为交互式应用程序安全测试。是Gartner公司提出的一种新的应用程序安全测试方案,通过在服务端部署Agent程序,监控Web应用程序运行时函数执行、数据传输,高效识别安全缺陷及漏洞,同时可准确定位漏洞所在代码文件、行数、函数及参数。通常SQL注入返回数据特征明显,使用IAST工具可高效监测SQL注入行为,并发出预警。

IAST工具可在测试阶段通过测试员工点击,被动发现发现安全漏洞。国内常见的IAST厂商包括火线、悬镜等。

  • 渗透测试

应用系统上线前均应通过渗透测试检测,黑盒方式发现漏洞。实现方式可为人工检测、DAST工具自动化扫描等。SQL注入作为高危通用漏洞,是重要测试点。

4.2、应用上线后

4.2.1、应用安全防护WAF

WAF全称Web应用防火墙,主要防护web端攻击,常见的SQL注入、XSS漏洞,以及组件框架漏洞,均可通过特征识别进行防护。

WAF属于较早诞生的安全防护产品,如今虽经常被人诟病防护场景单一,规则易被绕过等。但作为企业安全防护的前道,可协助应用拦截常规扫描、攻击 等。并对一些0day漏洞,可上线临时防护规则,仍是推荐的安全防护产品 。开源waf推荐长亭雷池,23年底已荣登GitHub开源类waf产品Star第一。github.com/chaitin/Saf...

4.2.2、企业自建SRC平台

更进一步,企业对外公开接收外部漏洞的平台------SRC安全应急响应中心(Security Response Center),邀请社会白帽子,以奖励方式挖掘自身企业所有信息系统相关漏洞。

建设src的方式主要分两种。一种为企业自行搭建,分前后端,漏洞审批、流转等,要求有研发人员进行平台研发。并配备src运营人员,进行漏洞审核、分发、社区运营等工作。常见的如阿里ASRC、京东JDSRC。

另一个为托管模式,企业可将src托管于付费第三方平台,审核漏洞由三方平台把关。企业只需确认接收漏洞并修复。常见的三方漏洞托管平台,如漏洞盒子、补天等。

两种模式各有优势,企业可根据自身情况选择。

4.2.3、DAST应用黑盒扫描

企业可按需采购DAST动态应用安全扫描产品,借助DAST工具,定期对自身企业公网应用做扫描,持续提升信息系统的安全水位。常见的DAST产品如xray、goby等,均包含社区开源版。

五、总结展望

本文简要讲述了SQL注入漏洞的原理、测试方法及防御措施。然而SQL注入的内容远不止此,针对不同的数据库(包括NoSQL)、注入类型、回显方式、利用手法、权限提升等,涉及数据库、WEB开发、编程语言特性,均可衍生出大量知识点。

作为历年OWASP TOP10中常客,SQL注入其破坏性不言而谕。对于一个信息系统而言,预防SQL注入最低成本的方式,是在设计研发阶段从系统底层完成防护。应用上线后,安全工具、渗透测试、应急响应平台作为发现漏洞的辅助手段。

相关推荐
denglei.6 分钟前
在Nginx部署Web应用,如何保障后端API的安全
nginx·安全
Smile灬凉城6662 小时前
robots协议
安全·php·robots
Hacker_Nightrain3 小时前
网络安全与加密
安全·web安全
网安-轩逸5 小时前
汽车网络安全渗透测试
安全·web安全·汽车
几维安全6 小时前
如何通过运行时威胁洞察提升反欺诈策略
运维·网络·安全
学习溢出7 小时前
【网络安全】John the Ripper 散列密码,PDF密码
安全·网络安全·pdf·哈希算法
黑客Jack7 小时前
什么是网络安全审计?
网络·安全·web安全
为几何欢7 小时前
【hackmymv】emma靶机wp
安全·网络安全·渗透·hackmyvm·hmv
Anna_Tong9 小时前
全局流量管理:提升用户体验与保障服务稳定性
运维·服务器·网络·数据库·安全·负载均衡
冰镇屎壳郎9 小时前
前端安全 常见的攻击类型及防御措施
前端·安全·前端安全