1 漏洞描述

SQL 注入攻击(SQL Injection),被广泛用于非法获取网站控制权,是发生在应用程序的数据库层上的安

全漏洞。

在设计不良的程序当中,忽略了对输入字符串中夹带的 SQL 指令的检查,那么这些夹带进去的指令就会

被数据库误认为是正常的 SQL 指令而运行,从而使数据库受到攻击,可能导致数据被窃取、更改、删除,以及进一步导致网站被嵌入恶意代码、被植入后门程序等危害。

XSS 是黑客通过篡改 HTML 代码,来插入并执行恶意脚本的一种攻击。其实,SQL 注入和 XSS 攻击很类似,都是黑客通过篡改代码逻辑发起的攻击。那么,不同的点是什么?SQL 注入到底是什么呢?

通常来说,我们会将应用的用户信息存储在数据库中。每次用户登录时,都会执行一个相应的 SQL 语句。这时,黑客会通过构造一些恶意的输入参数,在应用拼接 SQL 语句的时候,去篡改正常的 SQL 语意,从而执行黑客所控制的 SQL 查询功能。这个过程,就相当于黑客“注入”了一段 SQL 代码到应用中。这就是我们常说的 SQL 注入

1. 修改 WHERE 语句

我们先来看一个例子。现在有一个简单的登录页面,需要用户输入 Username 和 Password 这两个变量来完成登录。具体的 Web 后台代码如下所示:

uName = getRequestString("username");
uPass = getRequestString("password");
sql = 'SELECT * FROM Users WHERE Username ="' + uName + '" AND Password ="' + uPass + '"'

当用户提交一个表单(假设 Username 为 admin,Password 为 123456)时,Web 将执行下面这行代码:

SELECT * FROM Users WHERE Username ="admin" AND Password ="123456"

用户名密码如果正确的话,这句 SQL 就能够返回对应的用户信息;如果错误的话,不会返回任何信息。因此,只要返回的行数 ≥1,就说明验证通过,用户可以成功登录。

所以,当用户正常地输入自己的用户名和密码时,自然就可以成功登录应用。那黑客想要在不知道密码的情况下登录应用,他又会输入什么呢?他会输入 " or “”="。这时,应用的数据库就会执行下面这行代码:

SELECT * FROM Users WHERE Username ="" AND Password ="" or ""=""

我们可以看到,WHERE 语句后面的判断是通过 or 进行拼接的,其中"“=”"的结果是 true。那么,当有一个 or 是 true 的时候,最终结果就一定是 true 了。因此,这个 WHERE 语句是恒为真的,所以,数据库将返回全部的数据。

这样一来,也就是说,黑客只需要在登录页面中输入 " or “”=",就可以在不知道密码的情况下,成功登录后台了。而这,也就是所谓的“万能密码”。而这个“万能密码”,其实就是通过修改 WHERE 语句,改变数据库的返回结果,实现无密码登录。

2. 执行任意语句

除此之外,大部分的数据库都支持多语句执行。因此,黑客除了修改原本的 WHERE 语句之外,也可以在原语句的后面,插入额外的 SQL 语句,来实现任意的增删改查操作。在实际工作中,MySQL 是最常用的数据库,我们就以它为例,来介绍一下,任意语句是如何执行的。

INSERT INTO Users (Username, Password) VALUES("test","000000"); SELECT * FROM Users;

接下来,我们来看一个具体的例子。在用户完成登录后,应用通常会通过 userId 来获取对应的用户信息。
其 Web 后台的代码如下所示:

uid = getRequestString("userId");
sql = "SELECT * FROM Users WHERE UserId = " + uid;

在这种情况下,黑客只要在传入的 userId 参数中加入一个分号,就可以执行任意的 SQL 语句了。比如,黑客想“删库跑路”的话,就令 userId 为 1;DROP TABLE Users,那么,后台实际执行的 SQL 就会变成下面这行代码,而数据库中所有的用户信息就都会被删除。

SELECT * FROM Users WHERE UserId = 1;DROP TABLE Users

SQL 注入的“姿势”还有很多(比如:没有回显的盲注、基于 INSERT 语句的注入等等),它们的原理都是一样的,都是通过更改 SQL 的语义来执行黑客设定的 SQL 语句。

  1. 通过 SQL 注入攻击,黑客能做什么?

SQL 注入会令 Web 后台执行非常规的 SQL 语句,从而导致各种各样的问题。那么通过 SQL 注入攻击,黑客究竟能够干些什么呢 ?下面我们就一一来看。

  1. 绕过验证

    在上面的内容中,我们已经介绍过," or “”=" 作为万能密码,可以让黑客在不知道密码的情况下,通过登录认证。因此,SQL 注入最直接的利用方式,就是绕过验证,也就相当于身份认证被破解了。

  2. 任意篡改数据

    除了绕过验证,我们在任意语句执行的部分中讲到,SQL 注入漏洞导致黑客可以执行任意的 SQL 语句。因此,通过插入 DML 类的 SQL 语句( INSERT、UPDATE、DELETE、TRUNCATE、DROP 等),黑客就可以对表数据甚至表结构进行更改,这样数据的完整性就会受到损害。比如上面例子中,黑客通过插入 DROP TABLE Users,删除数据库中全部的用户。

  3. 窃取数据

    在 XSS 漏洞中,黑客可以通过窃取 Cookie 和“钓鱼”获得用户的隐私数据。那么,在 SQL 注入中,黑客会怎么来获取这些隐私数据呢?

    在各类安全事件中,我们经常听到“拖库”这个词。所谓“拖库”,就是指黑客通过类似 SQL 注入的手段,获取到数据库中的全部数据(如用户名、密码、手机号等隐私数据)。最简单的,黑客利用 UNION 关键词,将 SQL 语句拼接成下面这行代码之后,就可以直接获取全部的用户信息了。

SELECT * FROM Users WHERE UserId = 1 UNION SELECT * FROM Users
  1. 消耗资源

    SQL 注入破坏可用性十分简单,可以通过完全消耗服务器的资源来实现。比如,在 Web 后台中,黑客可以利用 WHILE 打造死循环操作,或者定义存储过程,触发一个无限迭代等等。在这些情况下,数据库服务器因为 CPU 被迅速打满,持续 100%,而无法及时响应其他请求。

    总结来说,通过 SQL 注入攻击,黑客可以绕过验证登录后台,非法篡改数据库中的数据;还能执行任意的 SQL 语句,盗取用户的隐私数据影响公司业务等等。所以,我认为,SQL 注入相当于让黑客直接和服务端的数据库进行了交互。正如我们一直所说的,应用的本质是数据,黑客控制了数据库,也就相当于控制了整个应用。

2. 解决办法

在认识到 SQL 注入的危害之后,我们知道,一个简单的 SQL 查询逻辑,能够带来巨大的安全隐患。因此,我们应该做到在开发过程中就避免出现 SQL 注入漏洞。那具体应该怎么做呢?接下来,我会为你介绍 3 种常见的防护方法,它们分别是:使用 PreparedStatement、使用存储过程和验证输入。接下来,我们一一来看。

1. 使用 PreparedStatement

通过合理地使用 PreparedStatement,我们就能够避免 99.99% 的 SQL 注入问题。你肯定很好奇,我为什么会这么说。接下来,让我们一起看一下它的实现过程。

当数据库在处理一个 SQL 命令的时候,大致可以分为两个步骤:
将 SQL 语句解析成数据库可使用的指令集。我们在使用 EXPLAIN 关键字分析 SQL 语句,就是干的这个事情;
将变量代入指令集,开始实际执行。之所以在批量处理 SQL 的时候能够提升性能,就是因为这样做避免了重复解析 SQL 的过程。

那么 PreparedStatement 为什么能够避免 SQL 注入的问题呢?

这是因为,SQL 注入是在解析的过程中生效的,用户的输入会影响 SQL 解析的结果。因此,我们可以通过使用 PreparedStatement,将 SQL 语句的解析和实际执行过程分开,只在执行的过程中代入用户的操作。这样一来,

无论黑客提交的参数怎么变化,数据库都不会去执行额外的逻辑,也就避免了 SQL 注入的发生。

在 Java 中,我们可以通过执行下面的代码将解析和执行分开:

String sql = "SELECT * FROM Users WHERE UserId = ?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1, userId);
ResultSet results = statement.executeQuery();

这里有一点需要你注意,前面我们说了,通过合理地使用 PreparedStatement 就能解决 99.99% 的 SQL 注入问题,那到底怎么做才算“合理地”使用呢?

PreparedStatement 为 SQL 语句的解析和执行提供了不同的“方法”,你需要分开来调用。但是,如果你在使用 PreparedStatement 的时候,还是通过字符串拼接来构造 SQL 语句,那仍然是将解析和执行放在了一块,也就不会产生相应的防护效果了。我这里给你展示了一个错误案例,你可以和上面的代码进行对比。

String sql = "SELECT * FROM Users WHERE UserId = " + userId;
PreparedStatement statement = connection.prepareStatement(sql);
ResultSet results = statement.executeQuery();

2. 使用存储过程

接下来,我们说一说,如何使用存储过程来防止 SQL 注入。实际上,它的原理和使用 PreparedStatement 类似,都是通过将 SQL 语句的解析和执行过程分开,来实现防护。区别在于,存储过程防注入是将解析 SQL 的过程,由数据库驱动转移到了数据库本身。

还是上述的例子,使用存储过程,我们可以这样来实现:

delimiter $$  # 将语句的结束符号从分号 ; 临时改为两个 $$(可以是自定义)
CREATE PROCEDURE select_user(IN p_id INTEGER)
BEGINSELECT * FROM Users WHERE UserId = p_id;
END$$
delimiter;  # 将语句的结束符号恢复为分号
call select_user(1);

3. 验证输入

防护的核心原则是,一切用户输入皆不可信。因此,SQL 注入的防护手段和 XSS 其实也是相通的,

主要的不同在于:

SQL 注入的攻击发生在输入的时候,因此,我们只能在输入的时候去进行防护和验证;

大部分数据库不提供针对 SQL 的编码,因为那会改变原有的语意,所以 SQL 注入没有编码的保护方案。

因此,对所有输入进行验证或者过滤操作,能够很大程度上避免 SQL 注入的出现。比如,在通过 userId 获取 Users 相关信息的示例中,我们可以确认 userId 必然是一个整数。因此,我们只需要对 userId 参数,进行一个整型转化(比如,Java 中的 Integer.parseInt,PHP 的 intval),就可以实现防护了。

当然,部分场景下,用户输入的参数会比较复杂。我们以用户发出的评论为例,其内容完全由用户定义,应用无法预判它的格式。这种情况下,应用只能通过对部分关键字符进行过滤,来避免 SQL 注入的发生。比如,在 MySQL 中,需要注意的关键词有" % ’ \ _。

这里我简单地总结一下,在实际使用这些防护方法时的注意点。对于验证输入来说,尤其是在复杂场景下的验证输入措施,其防护效果是最弱的。因此,避免 SQL 注入的防护方法,首要选择仍然是 PreparedStatement 或者存储过程。

  1. 其他解决方案
  • 所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中。
  • 对进入数据库的特殊字符 '"\<>&*; 等进行转义处理,或编码转换。
  • 确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存储字段必须对应为 int 型。
  • 数据长度应该严格规定,能在一定程度上防止比较长的 SQL 注入语句无法正确执行。
  • 网站每个数据层的编码统一,建议全部使用 UTF-8 编码,上下层编码不一致有可能导致一些过滤模型被绕过。
  • 严格限制网站所用数据库账号的权限,给此用户仅提供能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。
  • 避免网站显示 SQL 错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。

注意:

如果后端开发使用Mybatis ,则需要注意 :

在编写MyBatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“${xxx}”这样的参数,要手工
地做好过滤工作,来防止SQL注入攻击。

SQL 注入漏洞介绍及解决办法相关推荐

  1. sql注入漏洞与如何解决

    关于sql注入漏洞 这个问题说白了其实很简单,就是因为sql语句使用拼接字符串导致的 举例 String sql="SELECT * FROM userdata WHERE user=&qu ...

  2. WEB安全:XSS漏洞与SQL注入漏洞介绍及解决方案

    对web安全方面的知识非常薄弱,这篇文章把Xss跨站攻击和sql注入的相关知识整理了下,希望大家多多提意见. 对于防止sql注入发生,我只用过简单拼接字符串的注入及参数化查询,可以说没什么好经验,为避 ...

  3. JDBC的SQL注入漏洞分析和解决

    SQL注入漏洞分析 SQL注入漏洞解决 需要采用PreparedStatement对象解决SQL注入漏洞.这个对象将SQL预先进行编译,使用?作为占位符.?所代表内容是SQL所固定.再次传入变量(包含 ...

  4. thinkphp日志泄漏漏洞_ThinkPHP框架通杀所有版本的一个SQL注入漏洞详细分析及测试方法...

    ThinkPHP 3.1.3及之前的版本存在一个SQL注入漏洞,漏洞存在于ThinkPHP/Lib/Core/Model.class.php 文件 根据官方文档对"防止SQL注入" ...

  5. 测试php框架漏洞,ThinkPHP框架通杀所有版本的一个SQL注入漏洞详细分析及测试方法...

    作者: seay 下面是摘自thinkphp官方的一个公告,官方直接贴出这些东西是非常不负责的行为,跟上次apache公开的Struts2的代码执行一样的行为,会造成很多用户被黑.建议类似的厂商不要再 ...

  6. /plus/recommend.php sql注入漏洞,代码审计:ThinkPHP框架通杀所有版本的一个SQL注入漏洞详细分析及测试方法 | Seay 渗透 编程 代码审计 网络安全博客...

    显示不全请点击全屏阅读 下面是摘自thinkphp官方的一个公告,官方直接贴出这些东西是非常不负责的行为,跟上次apache公开的Struts2的代码执行一样的行为,会造成很多用户被黑.建议类似的厂商 ...

  7. SQL注入漏洞解决方法

    本文只指针编码层次的SQL注入漏洞解决方法,例子代码是以java为主. 1,参数化的预编译查询语句 不安全例子 String query = "SELECT account_balance ...

  8. 为解决存储型xss和sql注入漏洞,创建对应的全局过滤器

    1.存储型xss漏洞 系统由于未对参数过滤,导致可以存储html特殊标签,且返回的数据未经处理显示在web页面中导致存在存储型xss,攻击者可利用xss对用户发起鱼叉攻击获取cookie进入系统.为解 ...

  9. SQL注入漏洞攻防必杀技

    SQL注入是常见的利用程序漏洞进行攻击的方法,是很多入门级"黑客"喜欢采用的攻击方式,近来网上 对它的讨论很热烈,所以我在本期专题中为读者揭示SQL攻击的主要原理以及如何防范这种攻 ...

  10. [转]SQL注入漏洞攻防必杀技

    SQL注入是常见的利用程序漏洞进行攻击的方法,是很多入门级"黑客"喜欢采用的攻击方式,近来网上 对它的讨论很热烈,所以我在本期专题中为读者揭示SQL攻击的主要原理以及如何防范这种攻 ...

最新文章

  1. 拼多多谋定500个供应链品牌 农民丰收节交易会“拼农货”
  2. elasticsearch6.x {error:Content-Type header [application/x-www-form-urlencoded] is not supported
  3. ASP.NET Core 3.0:将会拥有更少的依赖
  4. java 中的正则表达式_Java中的正则表达式–软介绍
  5. 想象力比知识更重要——专访首位吴文俊人工智能最高成就奖得主陆汝钤
  6. GO语言学习之路17
  7. python.pandas数据清洗(数据填充与条件删除)
  8. 【OSG】安装编译小结
  9. QT创建和使用动态链接库
  10. F28335中断系统
  11. 二叉搜索树 根据前序序列求中序序列
  12. 【数学建模】模型的评价、模型的推广与改进
  13. 做美食与互联网产品的关系
  14. 上了学这么久,我才知道他们为什么可以这么爽
  15. 织梦模板安装后不能显示css的解决办法
  16. 无线物理层安全技术的研究进展
  17. mysql错误代码1068_数据库1068错误
  18. 大疆无人机,赛尔倾斜相机,合作打造高效行业应用解决方案
  19. 【SQL】通过SQL语句对学生信息表(学号、学生姓名、班级)、学习成绩表(学号、学科、成绩)的数据进行创建、查询、删除、更新
  20. cad批量逐个填充lisp_快速填充的多选问题 - AutoLISP/Visual LISP 编程技术 - CAD论坛 - 明经CAD社区 - Powered by Discuz!...

热门文章

  1. 强制换行的css属性
  2. 九度OJ题目1000: A + B(数学)
  3. Qt 酷炫动画 PictureFlow
  4. nginx处理域名后面多一个点
  5. DPDK X710 DDP PPPoE 实践
  6. LAN7500 Mac OS X Device Driver
  7. 使用SSE指令集优化memcpy
  8. import/export win7中电源计划
  9. python最小特征值_阿里巴巴举荐,Python视频,免费分享,用python求解特征向量和拉普拉斯矩阵...
  10. qt值qml制作足球动画(参考qmlbook)