SCW图标
英雄背景无分隔线
博客

程序员征服安全:分享与学习-SQL 注入

Jaap Karan Singh
发表于 2018 年 12 月 06 日
最后更新于 2026年3月10日

简而言之,SQL(或结构化查询语言)是用于与关系数据库通信的语言;它是开发人员、数据库管理员和应用程序用来管理关系数据库的查询语言 每天都会生成大量数据

我们的数据正迅速成为世界上最有价值的大宗商品之一... 当某些东西有价值时,坏人会为了自己的利益而想要获得这些数据。

攻击者正在使用 SQL 注入,这是最古老的注入之一 (自 1998 年起!)还有最讨厌的数据漏洞——窃取和更改全球数百万个数据库中可用的敏感信息。这很阴险,如果我们要确保数据安全,开发人员需要了解 SQL 注入(以及如何防御)。

为此,我们将讨论 SQL 注入的三个关键方面:

  • 它是如何运作的
  • 为什么这么危险
  • 如何防御

了解 SQL 注入

SQL 注入可以用一个词来理解:上下文。

在应用程序中,存在两个上下文:一个用于数据,另一个用于代码。代码上下文告诉计算机要执行什么并将其与要处理的数据分开。

当攻击者输入的数据被 SQL 解释器错误地视为代码时,就会发生 SQL 注入。

一个例子是网站上的输入字段,攻击者在其中输入 “” OR 1=1”,然后将其附加到 SQL 查询的末尾。执行此查询时,它将为数据库中的每一行返回 “true”。这意味着将返回查询表中的所有记录。

SQL 注入的影响可能是灾难性的。如果这发生在登录页面上,它可能会返回所有用户记录,可能包括用户名和密码。如果提取数据的简单查询成功,那么更改数据的查询也会成功。

让我们来看看一些易受攻击的代码,这样你就可以看到 SQL 注入漏洞的实际情况。

看看这个代码:

字符串查询 = “从用户数据中选择账户余额,其中 user_name =”
+ request.getParameter (“客户名称”);
试试 {
语句语句 = connection.createStatement (...);
ResultSet 结果 = Statement.executeQuery(查询);
}

这里的代码只是在没有验证的情况下将来自客户端的参数信息附加到 SQL 查询的末尾。发生这种情况时,攻击者可以在输入字段或 URL 参数中输入代码,它将被执行。

关键不是攻击者只能在每个 SELECT 查询中添加 '” 或 1=1”,而是攻击者可以操纵任何类型的 SQL 查询(插入、更新、删除、删除等),并使用数据库支持的任何内容对其进行扩展。有很棒的 资源 以及公共领域中可用的工具,这些工具可以证明什么是可能的。

我们将很快学习如何纠正这个问题。首先,让我们了解可以造成多少伤害。

为什么 SQL 注入如此危险

以下是由 SQL 注入导致的漏洞的三个示例:

  • 伊利诺伊州选举委员会网站 被突破了 由于 SQL 注入漏洞。攻击者窃取了20万美国公民的个人数据。发现的漏洞的性质意味着攻击者也可以更改数据,尽管他们没有。
  • Hetzner,一家南非的网站托管公司, 被突破了 高达 40,000 条客户记录。SQL 注入漏洞导致其数据库中的所有客户记录都可能被盗。
  • 美国明尼苏达州的一家天主教金融服务提供商, 被突破了 使用 SQL 注入。包括账号在内的近13万名客户的账户详细信息被盗。

敏感数据可用于接管帐户、重置密码、窃取金钱或进行欺诈。

即使不被视为敏感或无法识别个人身份的信息也可以用于其他攻击。地址信息或政府识别号码的后四位数字可用于在公司中冒充您,或重置您的密码。

攻击成功后,客户可能会失去对公司的信任。从系统损坏或监管罚款中恢复可能要花费数百万美元。

但对你来说,不必以这种方式结束。

击败 SQL 注入

通过明确标记应用程序的各个部分,可以打败 SQL 注入,这样计算机就可以知道某个部分是要执行的数据还是代码。这可以使用参数化查询来完成。

当 SQL 查询使用参数时,SQL 解释器将仅使用该参数作为数据。它不把它当作代码执行。

例如,像 '” OR 1=1 这样的攻击将不起作用。数据库将搜索字符串 “OR 1=1”,但在数据库中找不到。它只会耸耸肩说:“对不起,我找不到适合你的那个。”

Java 中参数化查询的示例如下所示:

大多数开发框架都提供了针对 SQL 注入的内置防御措施。

对象关系映射器 (ORM),例如 实体框架 在 .NET 系列中,默认情况下将参数化查询。这将完成 SQL 注入,无需您付出任何努力。

但是,你必须知道你的特定 ORM 是如何工作的。例如, 休眠,Java 世界中流行的 ORM, 仍然可能受到攻击 如果使用不当,则为 SQL 注入。

参数化查询是第一种也是最好的防御措施,但还有其他防御措施。存储过程还支持 SQL 参数,可用于防止 SQL 注入。请记住,存储过程 还必须正确构建 让它起作用。

//这也应该经过验证
字符串 custname = request.getParameter(“客户名称”);
//执行输入验证以检测攻击
字符串查询 = “从用户数据中选择账户余额,其中 user_name =?“;

PreparedStatement pstmt = connection.PreparedStatement(查询);
pstmt.setString (1, 自定义名称);
ResultSet 结果 = pstmt.executeQuery ();

务必验证和清理您的输入。由于应用程序的合法用户不会输入某些字符,例如 “OR 1=1”,因此无需允许它们。您可以向用户显示错误消息,或者在处理输入之前将其从您的输入中删除。

话虽如此,不要仅仅依靠验证和消毒来保护你。聪明的人已经找到了绕过这个问题的方法。它们是很好的深度防御(DiD)策略,但是参数化是覆盖所有基地的必经之路。

另一个好的 DiD 策略是在数据库中使用 “最小权限” 并将输入列入白名单。强制执行最低权限意味着您的应用程序在数据库中没有无限的功能。如果攻击者获得访问权限,他们所能造成的伤害是有限的。

OWASP 有很棒的体验 SQL 注入备忘单 可以展示如何使用多种语言和平台处理此漏洞... 但如果你想做得更好,你可以立即在我们的平台上用你喜欢的语言玩 SQL 注入挑战;以下是一些比较受欢迎的入门游戏:

C# 中的 SQL 注入

Node.js 中的 SQL 注入

Python Django 中的 SQL 注入

Java Spring 中的 SQL 注入

旅程开始了

在理解 SQL 注入以及修复该问题所需的步骤方面,你已经取得了一些长足的进步。太棒了!

我们已经讨论了 SQL 注入是如何发生的;通常是攻击者出于自己的恶意目的使用输入来控制您的数据库查询。

我们还看到了利用 SQL 注入漏洞所造成的损失:账户可能遭到入侵,损失数百万美元... 这是一场噩梦,也是一场代价高昂的噩梦。

我们已经看到了如何防止 SQL 注入:

  • 参数化查询
  • 使用对象关系映射器和存储过程
  • 验证用户输入并将其列入白名单

现在,由你决定。练习是继续学习和培养精通能力的最佳方式,那么为什么不看看我们的 学习资源 关于 SQL 注入,然后试试我们的 免费演示 平台的?你将顺利成为一名安全代码勇士。

查看资源
查看资源

攻击者正在使用 SQL 注入,这是最古老的注入之一(自 1998 年以来!)还有最讨厌的数据漏洞——窃取和更改全球数百万个数据库中可用的敏感信息。

对更多感兴趣?

Jaap Karan Singh是一位安全编码布道者,首席辛格和Secure Code Warrior 的共同创始人。

了解更多

Secure Code Warrior可帮助您的组织在整个软件开发生命周期中保护代码,并营造一种将网络安全置于首位的文化。无论您是应用安全经理、开发人员、首席信息安全官还是任何与安全相关的人员,我们都能帮助您的组织降低与不安全代码相关的风险。

预约演示
分享到:
领英品牌社交x 标志
作者
Jaap Karan Singh
发表于2018年12月06日

Jaap Karan Singh是一位安全编码布道者,首席辛格和Secure Code Warrior 的共同创始人。

分享到:
领英品牌社交x 标志

简而言之,SQL(或结构化查询语言)是用于与关系数据库通信的语言;它是开发人员、数据库管理员和应用程序用来管理关系数据库的查询语言 每天都会生成大量数据

我们的数据正迅速成为世界上最有价值的大宗商品之一... 当某些东西有价值时,坏人会为了自己的利益而想要获得这些数据。

攻击者正在使用 SQL 注入,这是最古老的注入之一 (自 1998 年起!)还有最讨厌的数据漏洞——窃取和更改全球数百万个数据库中可用的敏感信息。这很阴险,如果我们要确保数据安全,开发人员需要了解 SQL 注入(以及如何防御)。

为此,我们将讨论 SQL 注入的三个关键方面:

  • 它是如何运作的
  • 为什么这么危险
  • 如何防御

了解 SQL 注入

SQL 注入可以用一个词来理解:上下文。

在应用程序中,存在两个上下文:一个用于数据,另一个用于代码。代码上下文告诉计算机要执行什么并将其与要处理的数据分开。

当攻击者输入的数据被 SQL 解释器错误地视为代码时,就会发生 SQL 注入。

一个例子是网站上的输入字段,攻击者在其中输入 “” OR 1=1”,然后将其附加到 SQL 查询的末尾。执行此查询时,它将为数据库中的每一行返回 “true”。这意味着将返回查询表中的所有记录。

SQL 注入的影响可能是灾难性的。如果这发生在登录页面上,它可能会返回所有用户记录,可能包括用户名和密码。如果提取数据的简单查询成功,那么更改数据的查询也会成功。

让我们来看看一些易受攻击的代码,这样你就可以看到 SQL 注入漏洞的实际情况。

看看这个代码:

字符串查询 = “从用户数据中选择账户余额,其中 user_name =”
+ request.getParameter (“客户名称”);
试试 {
语句语句 = connection.createStatement (...);
ResultSet 结果 = Statement.executeQuery(查询);
}

这里的代码只是在没有验证的情况下将来自客户端的参数信息附加到 SQL 查询的末尾。发生这种情况时,攻击者可以在输入字段或 URL 参数中输入代码,它将被执行。

关键不是攻击者只能在每个 SELECT 查询中添加 '” 或 1=1”,而是攻击者可以操纵任何类型的 SQL 查询(插入、更新、删除、删除等),并使用数据库支持的任何内容对其进行扩展。有很棒的 资源 以及公共领域中可用的工具,这些工具可以证明什么是可能的。

我们将很快学习如何纠正这个问题。首先,让我们了解可以造成多少伤害。

为什么 SQL 注入如此危险

以下是由 SQL 注入导致的漏洞的三个示例:

  • 伊利诺伊州选举委员会网站 被突破了 由于 SQL 注入漏洞。攻击者窃取了20万美国公民的个人数据。发现的漏洞的性质意味着攻击者也可以更改数据,尽管他们没有。
  • Hetzner,一家南非的网站托管公司, 被突破了 高达 40,000 条客户记录。SQL 注入漏洞导致其数据库中的所有客户记录都可能被盗。
  • 美国明尼苏达州的一家天主教金融服务提供商, 被突破了 使用 SQL 注入。包括账号在内的近13万名客户的账户详细信息被盗。

敏感数据可用于接管帐户、重置密码、窃取金钱或进行欺诈。

即使不被视为敏感或无法识别个人身份的信息也可以用于其他攻击。地址信息或政府识别号码的后四位数字可用于在公司中冒充您,或重置您的密码。

攻击成功后,客户可能会失去对公司的信任。从系统损坏或监管罚款中恢复可能要花费数百万美元。

但对你来说,不必以这种方式结束。

击败 SQL 注入

通过明确标记应用程序的各个部分,可以打败 SQL 注入,这样计算机就可以知道某个部分是要执行的数据还是代码。这可以使用参数化查询来完成。

当 SQL 查询使用参数时,SQL 解释器将仅使用该参数作为数据。它不把它当作代码执行。

例如,像 '” OR 1=1 这样的攻击将不起作用。数据库将搜索字符串 “OR 1=1”,但在数据库中找不到。它只会耸耸肩说:“对不起,我找不到适合你的那个。”

Java 中参数化查询的示例如下所示:

大多数开发框架都提供了针对 SQL 注入的内置防御措施。

对象关系映射器 (ORM),例如 实体框架 在 .NET 系列中,默认情况下将参数化查询。这将完成 SQL 注入,无需您付出任何努力。

但是,你必须知道你的特定 ORM 是如何工作的。例如, 休眠,Java 世界中流行的 ORM, 仍然可能受到攻击 如果使用不当,则为 SQL 注入。

参数化查询是第一种也是最好的防御措施,但还有其他防御措施。存储过程还支持 SQL 参数,可用于防止 SQL 注入。请记住,存储过程 还必须正确构建 让它起作用。

//这也应该经过验证
字符串 custname = request.getParameter(“客户名称”);
//执行输入验证以检测攻击
字符串查询 = “从用户数据中选择账户余额,其中 user_name =?“;

PreparedStatement pstmt = connection.PreparedStatement(查询);
pstmt.setString (1, 自定义名称);
ResultSet 结果 = pstmt.executeQuery ();

务必验证和清理您的输入。由于应用程序的合法用户不会输入某些字符,例如 “OR 1=1”,因此无需允许它们。您可以向用户显示错误消息,或者在处理输入之前将其从您的输入中删除。

话虽如此,不要仅仅依靠验证和消毒来保护你。聪明的人已经找到了绕过这个问题的方法。它们是很好的深度防御(DiD)策略,但是参数化是覆盖所有基地的必经之路。

另一个好的 DiD 策略是在数据库中使用 “最小权限” 并将输入列入白名单。强制执行最低权限意味着您的应用程序在数据库中没有无限的功能。如果攻击者获得访问权限,他们所能造成的伤害是有限的。

OWASP 有很棒的体验 SQL 注入备忘单 可以展示如何使用多种语言和平台处理此漏洞... 但如果你想做得更好,你可以立即在我们的平台上用你喜欢的语言玩 SQL 注入挑战;以下是一些比较受欢迎的入门游戏:

C# 中的 SQL 注入

Node.js 中的 SQL 注入

Python Django 中的 SQL 注入

Java Spring 中的 SQL 注入

旅程开始了

在理解 SQL 注入以及修复该问题所需的步骤方面,你已经取得了一些长足的进步。太棒了!

我们已经讨论了 SQL 注入是如何发生的;通常是攻击者出于自己的恶意目的使用输入来控制您的数据库查询。

我们还看到了利用 SQL 注入漏洞所造成的损失:账户可能遭到入侵,损失数百万美元... 这是一场噩梦,也是一场代价高昂的噩梦。

我们已经看到了如何防止 SQL 注入:

  • 参数化查询
  • 使用对象关系映射器和存储过程
  • 验证用户输入并将其列入白名单

现在,由你决定。练习是继续学习和培养精通能力的最佳方式,那么为什么不看看我们的 学习资源 关于 SQL 注入,然后试试我们的 免费演示 平台的?你将顺利成为一名安全代码勇士。

查看资源
查看资源

填写下面的表格下载报告

我们希望获得您的许可,以便向您发送有关我们的产品和/或相关安全编码主题的信息。我们将始终非常谨慎地对待您的个人信息,绝不会出于营销目的将其出售给其他公司。

提交
scw 成功图标
SCW 错误图标
要提交表单,请启用“分析”Cookie。完成后,可以随意再次禁用它们。

简而言之,SQL(或结构化查询语言)是用于与关系数据库通信的语言;它是开发人员、数据库管理员和应用程序用来管理关系数据库的查询语言 每天都会生成大量数据

我们的数据正迅速成为世界上最有价值的大宗商品之一... 当某些东西有价值时,坏人会为了自己的利益而想要获得这些数据。

攻击者正在使用 SQL 注入,这是最古老的注入之一 (自 1998 年起!)还有最讨厌的数据漏洞——窃取和更改全球数百万个数据库中可用的敏感信息。这很阴险,如果我们要确保数据安全,开发人员需要了解 SQL 注入(以及如何防御)。

为此,我们将讨论 SQL 注入的三个关键方面:

  • 它是如何运作的
  • 为什么这么危险
  • 如何防御

了解 SQL 注入

SQL 注入可以用一个词来理解:上下文。

在应用程序中,存在两个上下文:一个用于数据,另一个用于代码。代码上下文告诉计算机要执行什么并将其与要处理的数据分开。

当攻击者输入的数据被 SQL 解释器错误地视为代码时,就会发生 SQL 注入。

一个例子是网站上的输入字段,攻击者在其中输入 “” OR 1=1”,然后将其附加到 SQL 查询的末尾。执行此查询时,它将为数据库中的每一行返回 “true”。这意味着将返回查询表中的所有记录。

SQL 注入的影响可能是灾难性的。如果这发生在登录页面上,它可能会返回所有用户记录,可能包括用户名和密码。如果提取数据的简单查询成功,那么更改数据的查询也会成功。

让我们来看看一些易受攻击的代码,这样你就可以看到 SQL 注入漏洞的实际情况。

看看这个代码:

字符串查询 = “从用户数据中选择账户余额,其中 user_name =”
+ request.getParameter (“客户名称”);
试试 {
语句语句 = connection.createStatement (...);
ResultSet 结果 = Statement.executeQuery(查询);
}

这里的代码只是在没有验证的情况下将来自客户端的参数信息附加到 SQL 查询的末尾。发生这种情况时,攻击者可以在输入字段或 URL 参数中输入代码,它将被执行。

关键不是攻击者只能在每个 SELECT 查询中添加 '” 或 1=1”,而是攻击者可以操纵任何类型的 SQL 查询(插入、更新、删除、删除等),并使用数据库支持的任何内容对其进行扩展。有很棒的 资源 以及公共领域中可用的工具,这些工具可以证明什么是可能的。

我们将很快学习如何纠正这个问题。首先,让我们了解可以造成多少伤害。

为什么 SQL 注入如此危险

以下是由 SQL 注入导致的漏洞的三个示例:

  • 伊利诺伊州选举委员会网站 被突破了 由于 SQL 注入漏洞。攻击者窃取了20万美国公民的个人数据。发现的漏洞的性质意味着攻击者也可以更改数据,尽管他们没有。
  • Hetzner,一家南非的网站托管公司, 被突破了 高达 40,000 条客户记录。SQL 注入漏洞导致其数据库中的所有客户记录都可能被盗。
  • 美国明尼苏达州的一家天主教金融服务提供商, 被突破了 使用 SQL 注入。包括账号在内的近13万名客户的账户详细信息被盗。

敏感数据可用于接管帐户、重置密码、窃取金钱或进行欺诈。

即使不被视为敏感或无法识别个人身份的信息也可以用于其他攻击。地址信息或政府识别号码的后四位数字可用于在公司中冒充您,或重置您的密码。

攻击成功后,客户可能会失去对公司的信任。从系统损坏或监管罚款中恢复可能要花费数百万美元。

但对你来说,不必以这种方式结束。

击败 SQL 注入

通过明确标记应用程序的各个部分,可以打败 SQL 注入,这样计算机就可以知道某个部分是要执行的数据还是代码。这可以使用参数化查询来完成。

当 SQL 查询使用参数时,SQL 解释器将仅使用该参数作为数据。它不把它当作代码执行。

例如,像 '” OR 1=1 这样的攻击将不起作用。数据库将搜索字符串 “OR 1=1”,但在数据库中找不到。它只会耸耸肩说:“对不起,我找不到适合你的那个。”

Java 中参数化查询的示例如下所示:

大多数开发框架都提供了针对 SQL 注入的内置防御措施。

对象关系映射器 (ORM),例如 实体框架 在 .NET 系列中,默认情况下将参数化查询。这将完成 SQL 注入,无需您付出任何努力。

但是,你必须知道你的特定 ORM 是如何工作的。例如, 休眠,Java 世界中流行的 ORM, 仍然可能受到攻击 如果使用不当,则为 SQL 注入。

参数化查询是第一种也是最好的防御措施,但还有其他防御措施。存储过程还支持 SQL 参数,可用于防止 SQL 注入。请记住,存储过程 还必须正确构建 让它起作用。

//这也应该经过验证
字符串 custname = request.getParameter(“客户名称”);
//执行输入验证以检测攻击
字符串查询 = “从用户数据中选择账户余额,其中 user_name =?“;

PreparedStatement pstmt = connection.PreparedStatement(查询);
pstmt.setString (1, 自定义名称);
ResultSet 结果 = pstmt.executeQuery ();

务必验证和清理您的输入。由于应用程序的合法用户不会输入某些字符,例如 “OR 1=1”,因此无需允许它们。您可以向用户显示错误消息,或者在处理输入之前将其从您的输入中删除。

话虽如此,不要仅仅依靠验证和消毒来保护你。聪明的人已经找到了绕过这个问题的方法。它们是很好的深度防御(DiD)策略,但是参数化是覆盖所有基地的必经之路。

另一个好的 DiD 策略是在数据库中使用 “最小权限” 并将输入列入白名单。强制执行最低权限意味着您的应用程序在数据库中没有无限的功能。如果攻击者获得访问权限,他们所能造成的伤害是有限的。

OWASP 有很棒的体验 SQL 注入备忘单 可以展示如何使用多种语言和平台处理此漏洞... 但如果你想做得更好,你可以立即在我们的平台上用你喜欢的语言玩 SQL 注入挑战;以下是一些比较受欢迎的入门游戏:

C# 中的 SQL 注入

Node.js 中的 SQL 注入

Python Django 中的 SQL 注入

Java Spring 中的 SQL 注入

旅程开始了

在理解 SQL 注入以及修复该问题所需的步骤方面,你已经取得了一些长足的进步。太棒了!

我们已经讨论了 SQL 注入是如何发生的;通常是攻击者出于自己的恶意目的使用输入来控制您的数据库查询。

我们还看到了利用 SQL 注入漏洞所造成的损失:账户可能遭到入侵,损失数百万美元... 这是一场噩梦,也是一场代价高昂的噩梦。

我们已经看到了如何防止 SQL 注入:

  • 参数化查询
  • 使用对象关系映射器和存储过程
  • 验证用户输入并将其列入白名单

现在,由你决定。练习是继续学习和培养精通能力的最佳方式,那么为什么不看看我们的 学习资源 关于 SQL 注入,然后试试我们的 免费演示 平台的?你将顺利成为一名安全代码勇士。

观看网络研讨会
开始吧
了解更多

点击下面的链接并下载此资源的PDF。

Secure Code Warrior可帮助您的组织在整个软件开发生命周期中保护代码,并营造一种将网络安全置于首位的文化。无论您是应用安全经理、开发人员、首席信息安全官还是任何与安全相关的人员,我们都能帮助您的组织降低与不安全代码相关的风险。

查看报告预约演示
查看资源
分享到:
领英品牌社交x 标志
对更多感兴趣?

分享到:
领英品牌社交x 标志
作者
Jaap Karan Singh
发表于2018年12月06日

Jaap Karan Singh是一位安全编码布道者,首席辛格和Secure Code Warrior 的共同创始人。

分享到:
领英品牌社交x 标志

简而言之,SQL(或结构化查询语言)是用于与关系数据库通信的语言;它是开发人员、数据库管理员和应用程序用来管理关系数据库的查询语言 每天都会生成大量数据

我们的数据正迅速成为世界上最有价值的大宗商品之一... 当某些东西有价值时,坏人会为了自己的利益而想要获得这些数据。

攻击者正在使用 SQL 注入,这是最古老的注入之一 (自 1998 年起!)还有最讨厌的数据漏洞——窃取和更改全球数百万个数据库中可用的敏感信息。这很阴险,如果我们要确保数据安全,开发人员需要了解 SQL 注入(以及如何防御)。

为此,我们将讨论 SQL 注入的三个关键方面:

  • 它是如何运作的
  • 为什么这么危险
  • 如何防御

了解 SQL 注入

SQL 注入可以用一个词来理解:上下文。

在应用程序中,存在两个上下文:一个用于数据,另一个用于代码。代码上下文告诉计算机要执行什么并将其与要处理的数据分开。

当攻击者输入的数据被 SQL 解释器错误地视为代码时,就会发生 SQL 注入。

一个例子是网站上的输入字段,攻击者在其中输入 “” OR 1=1”,然后将其附加到 SQL 查询的末尾。执行此查询时,它将为数据库中的每一行返回 “true”。这意味着将返回查询表中的所有记录。

SQL 注入的影响可能是灾难性的。如果这发生在登录页面上,它可能会返回所有用户记录,可能包括用户名和密码。如果提取数据的简单查询成功,那么更改数据的查询也会成功。

让我们来看看一些易受攻击的代码,这样你就可以看到 SQL 注入漏洞的实际情况。

看看这个代码:

字符串查询 = “从用户数据中选择账户余额,其中 user_name =”
+ request.getParameter (“客户名称”);
试试 {
语句语句 = connection.createStatement (...);
ResultSet 结果 = Statement.executeQuery(查询);
}

这里的代码只是在没有验证的情况下将来自客户端的参数信息附加到 SQL 查询的末尾。发生这种情况时,攻击者可以在输入字段或 URL 参数中输入代码,它将被执行。

关键不是攻击者只能在每个 SELECT 查询中添加 '” 或 1=1”,而是攻击者可以操纵任何类型的 SQL 查询(插入、更新、删除、删除等),并使用数据库支持的任何内容对其进行扩展。有很棒的 资源 以及公共领域中可用的工具,这些工具可以证明什么是可能的。

我们将很快学习如何纠正这个问题。首先,让我们了解可以造成多少伤害。

为什么 SQL 注入如此危险

以下是由 SQL 注入导致的漏洞的三个示例:

  • 伊利诺伊州选举委员会网站 被突破了 由于 SQL 注入漏洞。攻击者窃取了20万美国公民的个人数据。发现的漏洞的性质意味着攻击者也可以更改数据,尽管他们没有。
  • Hetzner,一家南非的网站托管公司, 被突破了 高达 40,000 条客户记录。SQL 注入漏洞导致其数据库中的所有客户记录都可能被盗。
  • 美国明尼苏达州的一家天主教金融服务提供商, 被突破了 使用 SQL 注入。包括账号在内的近13万名客户的账户详细信息被盗。

敏感数据可用于接管帐户、重置密码、窃取金钱或进行欺诈。

即使不被视为敏感或无法识别个人身份的信息也可以用于其他攻击。地址信息或政府识别号码的后四位数字可用于在公司中冒充您,或重置您的密码。

攻击成功后,客户可能会失去对公司的信任。从系统损坏或监管罚款中恢复可能要花费数百万美元。

但对你来说,不必以这种方式结束。

击败 SQL 注入

通过明确标记应用程序的各个部分,可以打败 SQL 注入,这样计算机就可以知道某个部分是要执行的数据还是代码。这可以使用参数化查询来完成。

当 SQL 查询使用参数时,SQL 解释器将仅使用该参数作为数据。它不把它当作代码执行。

例如,像 '” OR 1=1 这样的攻击将不起作用。数据库将搜索字符串 “OR 1=1”,但在数据库中找不到。它只会耸耸肩说:“对不起,我找不到适合你的那个。”

Java 中参数化查询的示例如下所示:

大多数开发框架都提供了针对 SQL 注入的内置防御措施。

对象关系映射器 (ORM),例如 实体框架 在 .NET 系列中,默认情况下将参数化查询。这将完成 SQL 注入,无需您付出任何努力。

但是,你必须知道你的特定 ORM 是如何工作的。例如, 休眠,Java 世界中流行的 ORM, 仍然可能受到攻击 如果使用不当,则为 SQL 注入。

参数化查询是第一种也是最好的防御措施,但还有其他防御措施。存储过程还支持 SQL 参数,可用于防止 SQL 注入。请记住,存储过程 还必须正确构建 让它起作用。

//这也应该经过验证
字符串 custname = request.getParameter(“客户名称”);
//执行输入验证以检测攻击
字符串查询 = “从用户数据中选择账户余额,其中 user_name =?“;

PreparedStatement pstmt = connection.PreparedStatement(查询);
pstmt.setString (1, 自定义名称);
ResultSet 结果 = pstmt.executeQuery ();

务必验证和清理您的输入。由于应用程序的合法用户不会输入某些字符,例如 “OR 1=1”,因此无需允许它们。您可以向用户显示错误消息,或者在处理输入之前将其从您的输入中删除。

话虽如此,不要仅仅依靠验证和消毒来保护你。聪明的人已经找到了绕过这个问题的方法。它们是很好的深度防御(DiD)策略,但是参数化是覆盖所有基地的必经之路。

另一个好的 DiD 策略是在数据库中使用 “最小权限” 并将输入列入白名单。强制执行最低权限意味着您的应用程序在数据库中没有无限的功能。如果攻击者获得访问权限,他们所能造成的伤害是有限的。

OWASP 有很棒的体验 SQL 注入备忘单 可以展示如何使用多种语言和平台处理此漏洞... 但如果你想做得更好,你可以立即在我们的平台上用你喜欢的语言玩 SQL 注入挑战;以下是一些比较受欢迎的入门游戏:

C# 中的 SQL 注入

Node.js 中的 SQL 注入

Python Django 中的 SQL 注入

Java Spring 中的 SQL 注入

旅程开始了

在理解 SQL 注入以及修复该问题所需的步骤方面,你已经取得了一些长足的进步。太棒了!

我们已经讨论了 SQL 注入是如何发生的;通常是攻击者出于自己的恶意目的使用输入来控制您的数据库查询。

我们还看到了利用 SQL 注入漏洞所造成的损失:账户可能遭到入侵,损失数百万美元... 这是一场噩梦,也是一场代价高昂的噩梦。

我们已经看到了如何防止 SQL 注入:

  • 参数化查询
  • 使用对象关系映射器和存储过程
  • 验证用户输入并将其列入白名单

现在,由你决定。练习是继续学习和培养精通能力的最佳方式,那么为什么不看看我们的 学习资源 关于 SQL 注入,然后试试我们的 免费演示 平台的?你将顺利成为一名安全代码勇士。

目录

下载PDF
查看资源
对更多感兴趣?

Jaap Karan Singh是一位安全编码布道者,首席辛格和Secure Code Warrior 的共同创始人。

了解更多

Secure Code Warrior可帮助您的组织在整个软件开发生命周期中保护代码,并营造一种将网络安全置于首位的文化。无论您是应用安全经理、开发人员、首席信息安全官还是任何与安全相关的人员,我们都能帮助您的组织降低与不安全代码相关的风险。

预约演示下载
分享到:
领英品牌社交x 标志
资源中心

帮助您入门的资源

更多帖子
资源中心

帮助您入门的资源

更多帖子