首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >07 | SQL注入:明明设置了强密码,为什么还会被别人登录?

07 | SQL注入:明明设置了强密码,为什么还会被别人登录?

作者头像
小黑同学
发布于 2020-11-24 02:04:05
发布于 2020-11-24 02:04:05
96400
代码可运行
举报
文章被收录于专栏:E=mc²E=mc²
运行总次数:0
代码可运行

在上一讲中,我们介绍了 XSS 攻击。今天,我们来介绍另外一种常见的 Web 攻击:SQL 注入。

在讲正文之前,让我们先来看一个案例。某天,当你在查看应用的管理后台时,发现有很多异常的操作。接着,你很快反应过来了,这应该是黑客成功登录了管理员账户。于是,你立刻找到管理员,责问他是不是设置了弱密码。管理员很无辜地表示,自己的密码非常复杂,不可能泄露,但是为了安全起见,他还是立即修改了当前的密码。奇怪的是,第二天,黑客还是能够继续登录管理员账号。问题来了,黑客究竟是怎么做到的呢?你觉得这里面的问题究竟出在哪里呢?你可以先自己思考一下,然后跟着我开始今天的学习!

▌SQL 注入攻击是如何产生的?

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

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

这么说可能还是有点理论,不够具体。接下来,我就以几个简单而又经典的示例,来给你介绍两种主要的 SQL 注入方式。

1. 修改 WHERE 语句

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
uName = getRequestString("username");
uPass = getRequestString("password");
sql = 'SELECT * FROMUsersWHERE Username ="' + uName + '"ANDPassword ="' + uPass + '"'

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT * FROMUsersWHERE Username ="admin"ANDPassword ="123456"

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

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

SELECT * FROMUsersWHERE Username ="“ANDPassword =”“or”"=""

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

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

2. 执行任意语句

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

在 MySQL 中,实现任意语句执行最简单的方法,就是利用分号将原本的 SQL 语句进行分割。这样,我们就可以一次执行多个语句了。比如,下面这个语句在执行的时候会先插入一个行,然后再返回 Users 表中全部的数据。

INSERTINTOUsers (Username, Password) VALUES(“test”,“000000”); SELECT * FROMUsers;

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
uid = getRequestString("userId");
sql = "SELECT * FROMUsersWHERE UserId = " + uid;

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT * FROMUsersWHERE UserId = 1;DROPTABLEUsers

SQL 注入的“姿势”还有很多(比如:没有回显的盲注、基于 INSERT 语句的注入等等),它们的原理都是一样的,都是通过更改 SQL 的语义来执行黑客设定的 SQL 语句。如果你有兴趣,可以通过我前面给出的链接去进一步了解。

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

通过上面对 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 * FROMUsersWHERE UserId = 1UNIONSELECT * FROMUsers

4. 消耗资源

通过第 1 讲对 CIA 三元组的学习,我们知道,除了获取数据之外,影响服务可用性也是黑客的目标之一。

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

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

▌如何进行 SQL 注入防护 ?

在认识到 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 中,我们可以通过执行下面的代码将解析和执行分开:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
String sql = "SELECT * FROMUsersWHERE UserId = ?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1, userId);
ResultSet results = statement.executeQuery();

为了实现相似的效果,在 PHP 中,我们可以使用 PDO(PHP Data Objects);在 C# 中,我们可以使用 OleDbCommand 等等。

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
String sql = "SELECT * FROMUsersWHERE UserId = " + userId;
PreparedStatement statement = connection.prepareStatement(sql);
ResultSet results = statement.executeQuery();
2. 使用存储过程

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
delimiter $$  #将语句的结束符号从分号;临时改为两个$$(可以是自定义)
CREATEPROCEDURE select_user(IN p_id INTEGER)
BEGIN
SELECT * FROMUsersWHERE 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 或者存储过程。

▌总结

好了,这一节内容差不多了,下面我来带你总结回顾一下,你要掌握的重点内容。

SQL 注入就是黑客通过相关漏洞,篡改 SQL 语句的攻击。通过 SQL 注入,黑客既可以影响正常的 SQL 执行结果,从而绕过验证,也可以执行额外的 SQL 语句,对数据的机密性、完整性和可用性都产生影响。

为了避免 SQL 注入的出现,我们需要正确地使用 PreparedStatement 方法或者存储过程,尽量避免在 SQL 语句中出现字符串拼接的操作。除此之外,SQL 注入的防护也可以和 XSS 一样,对用户的输入进行验证、检测并过滤 SQL 中的关键词,从而避免原有语句被篡改。

今天的内容比较多,为了方便你记忆,我总结了一个知识脑图,你可以通过它来对今天的重点内容进行复习巩固。

▌思考题

好了,今天的内容差不多了,我们来看一道思考题。

假设有下面这样一个语句:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT Username FROMUsersWHERE UserId = 1

你现在已经知道,WHERE 语句中存在了 SQL 注入的点。那么,我们怎么才能获取到除了 Username 之外的其他字段呢?这里我给你一个小提示,你可以先了解一下“盲注”这个概念,之后再来思考这个问题。

欢迎留言和我分享你的思考和疑惑,也欢迎你把文章分享给你的朋友。我们下一讲再见!

▌下一讲

CSRF/SSRF:为什么避免了XSS,还是“被发送”了一条微博?

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/08/18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
SQL注入之万能密码:原理、实践与防御全解析
的密码字段就突破了系统防线。这个被称为"万能密码"的经典攻击方式,至今仍在OWASP十大Web安全威胁榜单中占据重要位置。本文将深入解析万能密码的运行机制,通过代码实例揭示其危险性,并提供企业级防御方案。
是山河呀
2025/04/19
8890
如何全面防御SQL注入
随着技术的进步,Web应用技术在得以快速发展的同时,其自身的漏洞和伴随的风险也在不断迭代与增加着。自2003年以来,SQL注入攻击已持续位列OWASP应用安全风险Top 10之中,并值得各类公司持续予以严防死守。在本文中,我们根据如下的议题,来深入探讨SQL注入攻击的特点,及其防御方法。具体议题如下:
二月春风似剪刀
2019/02/23
7.2K0
如何全面防御SQL注入
防止黑客SQL注入的方法
一、SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库。 二、SQL注入攻击的总体思路 1.寻找到SQL注入的位置 2.判断服务器类型和后台数据库类型 3.针对不通的服务器和数据库特点进行SQL注入攻击 三、SQL注入攻击实例 比如在一个登录界面,要求输入用户名和密码: 可以这样输入实现免帐号登录: 用户名: ‘or 1 = 1 – 密 码: ‘or 1 = 1 – 点登陆,如若没有做特
企鹅号小编
2018/01/26
1.8K0
SQL 注入
在网络安全领域,SQL 注入是一种极为流行且危害严重的攻击手段。它利用了 Web 应用程序与数据库交互过程中的漏洞,可能导致数据库信息泄露、数据篡改甚至整个系统的瘫痪。本文将介绍 SQL 注入的相关概念,从攻击者和防御者的角度探讨其原理、常见场景以及相应的防范措施,并在必要时给出相关代码示例。
恒辉信达
2024/11/23
4680
Java代码审计 -- SQL注入
在JDBC下有两种方法执行SQL语句,分别是Statement和PrepareStatement,即其中,PrepareStatement为预编译
Gh0st1nTheShel
2021/12/31
1.7K0
什么是SQL注入攻击?
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。当应用程序使用输入内容来构造动态SQL语句以访问数据库时,会发生SQL注入攻击。如果代码使用存储过程,而这些存储过程作为包含未筛选的用户输入的字符串来传递,也会发生SQL注入。 黑客通过SQL注入攻击可以拿到网站数据库的访问权限,之后他们就可以拿到网站数据库中所有的数据,恶意的黑客可以通过SQL注入功能篡改数据库中的数据甚至会把数据库中的数据毁坏掉。
用户10358987
2024/04/23
2470
Fortify Audit Workbench 笔记 SQL Injection SQL注入
通过不可信来源的输入构建动态 SQL 指令,攻击者就能够修改指令的含义或者执行任意 SQL 命令。
用户1637609
2020/03/17
1.9K0
Web安全系列——注入攻击
在Web应用程序开发中,防SQL注入最基本的安全防护要求了。其实除了SQL注入, 还有很多其他的注入攻击方式。注入攻击是最常见的Web应用攻击方式之一。
windealli
2023/10/13
2.9K0
Web安全系列——注入攻击
Spring Boot中的跨站点脚本攻击(XSS)与SQL注入防护
在现代Web应用程序开发中,安全性是一个至关重要的课题。跨站点脚本攻击(XSS)和SQL注入是最常见的两种攻击类型,它们可以严重威胁到应用程序的安全。本文将介绍XSS和SQL注入的概念,并提供一些在Spring Boot应用中防止这些攻击的实践方法。
小马哥学JAVA
2024/06/15
8690
SQL注入解读
攻击者通过在应用程序中输入恶意的SQL语句,欺骗服务器执行非预期的数据库操作。说SQL注入的基本步骤:
一个风轻云淡
2024/07/12
2620
代码审计(二)——SQL注入代码
当访问动态网页时,以MVC框架为例,浏览器提交查询到控制器(①),如是动态请求,控制器将对应sql查询送到对应模型(②),由模型和数据库交互得到查询结果返回给控制器(③),最后返回给浏览器(④)。
黑伞安全
2022/01/26
7.2K0
代码审计(二)——SQL注入代码
Java项目防止SQL注入的四种方案
SQL注入是一种常见的安全漏洞,它可以导致应用程序数据库泄露、数据损坏甚至系统崩溃。在Java项目中,防止SQL注入攻击至关重要。本文将介绍四种常见的防止SQL注入的方案,并提供代码示例以帮助读者更好地理解这些方法。
IT_陈寒
2023/12/13
1.2K0
Java项目防止SQL注入的四种方案
sql注入及用PrepareStatement就不用担心sql注入了吗?
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到sql注入攻击。
全栈程序员站长
2022/09/02
1.5K0
SQL注入详解,看这篇就够了
相信大家对于学校们糟糕的网络环境和运维手段都早有体会,在此就不多做吐槽了。今天我们来聊一聊SQL注入相关的内容。
释然IT杂谈
2022/10/27
2K0
SQL注入详解,看这篇就够了
1.sql注入基础
sys: 存储过程、自定义函数、视图帮助我们快速的了解系统的元数据信息。(元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等)
tea9
2022/09/08
5740
SQL注入问题
sql注入是一种通过在输入中注入sql语句,来达到攻击数据库的效果。今天使用Java语言,来分析一下sql注入的相关问题。
ZackSock
2020/02/14
1.2K0
JDBC 通过PreparedStatement 解决SQL注入(5)
常见的SQL注入 数字注入 在浏览器地址栏输入:test.com/sql/article.php?id=1,这是请求方式为get的接口,发送这个请求相当于调用一个查询语句 $sql = "select
桑鱼
2020/03/17
1.9K0
SQL注入及如何解决
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
俊才
2021/01/04
2K0
SQL注入及如何解决
SQL注入专项整理(持续更新中)
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。(百度百科) SQL注入是Web安全常见的一种攻击手段,其主要存在于数据库中,用来窃取重要信息,在输入框、搜索框、登录窗口、交互式等等都存在注入可能;是否是输入函数无法判断其输入的合法性并将其作为PHP等语言代码来执行,或整体逻辑出现缺陷,或关键字关键命令关键字符没过滤全,包括编码加密命令是否进行了过滤,这些种种环节的防护不严都将导致SQL注入的成功。(本人拙见)
用户8909609
2023/10/23
4700
SQL注入专项整理(持续更新中)
SQL注入与XSS漏洞
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求 的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网 站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容 易受到SQL注入式攻击 当应用程序使用输入内容来构造动态sql语句以访问数据库时,会发生sql注入攻击。如果代码使用存储过程,而这些存储过程作为包含未筛选的用户输入的字符串来传递,也会发生sql注入。sql注入可能导致攻击者使用应用程序登陆在数据库中执行命令。如
赵腰静
2018/03/09
2.4K0
相关推荐
SQL注入之万能密码:原理、实践与防御全解析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档