飞道的博客

Web系统常见安全漏洞介绍及解决方案-sql注入

368人阅读  评论(0)

一、常见漏洞类型

关于web安全测试,目前主要有以下几种攻击方法:

  1. XSS
  2. SQL注入
  3. 跨目录访问
  4. 缓冲区溢出
  5. cookies修改
  6. Htth方法篡改(包括隐藏字段修改和参数修改)
  7. CSRF
  8. CRLF
  9. 命令行注入

今天主要讲下SQL注入。

二、SQL注入

1、SQL 注入危险性、可能原因

严重性:
类型: 应用程序级别测试
WASC威胁分类: WASC-19 SQL Injection(sql注入)
漏洞分类方法WASC介绍参考博文

CVE 引用: 不适用

CVE 的英文全称是“Common Vulnerabilities & Exposures”通用漏洞披露。CVE就好像是一个字典表,为广泛认同的信息安全漏洞或者已经暴露出来的弱点给出一个公共的名称。使用一个共同的名字,可以帮助用户在各自独立的各种漏洞数据库中和漏洞评估工具中共享数据,虽然这些工具很难整合在一起。这样就使得CVE成为了安全信息共享的“关键字”。如果在一个漏洞报告中指明的一个漏洞,如果有CVE名称,你就可以快速地在任何其它CVE兼容的数据库中找到相应修补的信息,解决安全问题。

安全风险:

  1. 可能会查看、修改或删除数据库条目和表 —SQL盲注
  2. 可能会窃取或操纵客户会话和 cookie,它们可能用于模仿合法用户,从而使黑客能够以该用户身份查看或变更用户记录以及执行事务 —跨站的脚本编制

可能原因:
未对用户输入正确执行危险字符清理

2、场景重现

攻击者利⽤SQL注⼊漏洞,可以获取数据库中的多种信息(例如:管理员后台密码),从⽽脱取数据库中内容(脱库)。在特别情况下还可以修改数据库内容或者插⼊内容到数据库,如果数据库权限分配存在问题,或者数据库本⾝存在缺陷,那么攻击者可以通过SQL注⼊漏洞直接获取web shell或者服务器系统权限。
例如,如果应用程序根据用户的输入(如用户名和密码)来查询用户帐户的数据库表,以认证用户,而攻击者能够将恶意数据注入查询的用户名部分(和/或密码部分),查询便可能更改成完全不同的数据复制查询,可能是修改数据库的查询,或在数据库服务器上运行 Shell 命令的查询。
一般而言,攻击者会分步实现这个目标。他会先学习 SQL 查询的结构,然后使用该知识来阻挠查询(通过注入更改查询语法的数据),使执行的查询不同于预期。假设相关查询是:

SELECT COUNT(*) FROM accounts WHERE username='$user' AND password='$pass' 

其中 $user 和 $pass 是用户在登录页面上输入的值(可能是来自 GET 请求查询参数,也可能是来自 POST 请求主体参数)。此查询的一般用法,其值为 u s e r = j o h n 、 user=john、 user=johnpassword=secret123。形成的查询如下:

SELECT COUNT(*) FROM accounts WHERE username='john' AND password='secret123' 

如果数据库中没有这个用户密码配对,预期的查询结果便是 0,如果此类配对存在(也就是数据库中有名称为“john”的用户,且其密码为“secret123”),结果便是 >0。这是应用程序的基本认证机制。但攻击者可以用下列方式来更改此查询:
攻击者可以提供单引号字符(')所组成的输入,使数据库发出错误消息,其中通常包含关于 SQL 查询的有价值的信息。攻击者只需在发送的请求中包含用户值 ',并在密码中包含任何值(如 foobar)。结果便是下列(格式错误)的 SQL 查询:SELECT COUNT(*) FROM accounts WHERE username=''' AND password='foobar'

后端执行这段代码查询数据可能会产生发生语法错误,这时攻击者便得知查询是根据表达式 username=‘ u s e r ′ a n d p a s s w o r d = ′ user' and password=' userandpassword=pass’ 来构建的。攻击者了解查询的格式这一关键信息后,下一步只需使用:
user =' or 1=1 or ''=' password = foobar
生成的查询如下:

SELECT COUNT(*) FROM accounts WHERE username='' or 1=1 or ''='' AND password='foobar' 

这个sql表示查询“accounts”表的所有记录,因为 1=1 表达式永远为真,于是用户(攻击者)也会被视为有效。这个探测方法有若干变体,例如,发送 '; or '(您应该记住,几乎所有供应商都有他们自己唯一的 SQL“版本”。具体地说,发送 ’ having 1=1,也会生成错误消息,此消息会泄露有关列名称的信息。

3、sql盲注

降低 SQL 注入攻击风险的一般方式,是禁止详细的 SQL 错误消息,攻击者通常便利用这些消息(如上述示例所示报错信息提供了sql具体内容),轻易找出容易遭受“SQL 注入”的脚本。
这种隐藏报错信息的解决方案还不能够真正解决问题,攻击者可以通过sql盲注技术进行攻击,这种注入方法不需要依赖返回 SQL 错误消息,便能找出容易遭受“SQL 注入”的脚本。

sql盲注需要修改发送请求的参数(被嵌入在 SQL 查询中的参数),这项修改包括搭配原始字符串来使用 AND Boolean 表达式,使sql条件能够直接得出 true或 false,最终结果应该与原始结果相同(例如:登录成功)或者不同(例如:登录失败)。在某些少见的情况中,得出 true 的 OR 表达式也很有用。

4、检测⽅法

  1. 识别⽤户输⼊。SQL注⼊漏洞可能在系统输⼊参数中,这些参数执⾏数据库操作。
  2. GET、POST参数中。
  3. COOKIE参数中。
  4. http请求头。主机头、引⽤站点(referer)、User-Agent和X-Forwarded-For等。
  5. 检测SQL注⼊。使⽤SQL注⼊测试语句对输⼊参数进⾏测试。
  6. 特殊符号:单引号,分号,web服务器响应报错。
  7. 条件响应:and 1=1、and 1=2、’ or ‘1’=‘1、’ or ‘1’='2,两次web服务器响应不同。
  8. 时间延时:sleep(5)、waitfor delay ‘0:0:5’,系统服务器延迟响应。
  9. 参数相加:对数字类型进⾏加减运算,字符类型使⽤数据库连接符号进⾏连接。系统服务器响应与原来的响应相同。
  10. 利⽤SQL注⼊。对以上测试进⼀步利⽤,⼿⼯构造SQL注⼊语句或者使⽤SQLMAP检测脚本构造注⼊语句。

5、防护⽅案

问题的补救方法在于对用户输入参数进行过滤、校验或者采⽤参数预处理的⽅式
通过验证用户输入未包含危险字符,便可能防止恶意的用户导致应用程序执行计划外的任务,例如:启动任意 SQL 查询、嵌入将在客户端执行的 Javascript. 代码、运行各种操作系统命令,等等。
建议过滤出所有以下字符:
[1] |(竖线符号)
[2] & (& 符号)
[3];(分号)
[4] $(美元符号)
[5] %(百分比符号)
[6] @(at 符号)
[7] '(单引号)
[8] "(引号)
[9] '(反斜杠转义单引号)
[10] "(反斜杠转义引号)

我公司采用的就是这种方法哦,将特殊符号加入一个黑名单,在全局的监听器中过滤掉含有这些黑名单中特殊符号的查询,基本上就能解决sql注入问题了。

三、使用ORM框架

使用ORM框架对sql注入是有积极意义的,在实际解决SQL注入时,还有一个难点就是应用复杂后,代码数量庞大,难以把可能存在sql注入的地方不遗漏的找出来,而ORM框架为我们发现问题提供了一个便捷的途径。以mybatis为例,它生成的sql语句都结构化的写在XML文件中,它支持动态sql,可以在sql语句中插入动态变量${keyid},如果用户能控制这个变量,则会存在一个sql注入的漏洞。

<select id="getByKeyID" resultType="java.util.HashMap" parameterType="java.util.HashMap">
    SELECT * FROM
    SALES
    WHERE ID IN (${keyid}) AND USERID=#{userid}
</select>

而静态变量#{userid}则是安全的,因此在使用mybatis时,只需要搜索所有的mapper文件中是否包含动态变量即可。当业务需要使用动态sql时,可以作为特例处理,比如在上层的代码逻辑中针对该变量进行严格的控制,以保证不会发生注入问题。


转载:https://blog.csdn.net/qq_42887496/article/details/125504136
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场