博客

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

December 6, 2018
Jaap Karan Singh

简单来说,SQL(结构化查询语言)是与关系型数据库进行通信的语言;它是开发人员、数据库管理员和应用程序用来管理每天产生的大量数据的查询语言。

我们的数据正迅速成为世界上最有价值的商品之一……而一旦某样东西变得有价值,不法分子就会想方设法将其据为己有,以谋取私利。

攻击者正利用 SQL 注入——这一自1998 年以来最古老且最棘手的数据漏洞之一——窃取并篡改全球数百万数据库中的敏感信息。这种攻击手段极其隐蔽,为了保障数据安全,开发人员必须深入了解 SQL 注入及其防御方法。

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

  • 工作原理
  • 为何如此危险
  • 如何进行防御

理解 SQL 注入

理解 SQL 注入只需掌握一个词:上下文。

在应用程序中,存在两种上下文:数据上下文和代码上下文。代码上下文告诉计算机执行什么操作,并将其与待处理的数据区分开来。

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

以网站上的输入框为例,如果攻击者输入“' OR 1=1”,该内容会被附加到 SQL 查询语句的末尾。当查询执行时,它会对数据库中的每一行返回“真”,这意味着查询表中的所有记录都将被返回。

SQL 注入的后果可能是灾难性的。如果这种情况发生在登录页面,它可能会返回所有用户记录,甚至包括用户名和密码。如果简单的提取数据查询能够成功,那么修改数据的查询同样也能得逞。

让我们来看一些存在漏洞的代码,以便您能直观地了解 SQL 注入漏洞的真面目。

请看这段代码:

String query = "SELECT account balance FROM user_data WHERE user_name = "
+ request.getParameter("customerName");
try {
   Statement statement = connection.createStatement( ... );
   ResultSet results = statement.executeQuery( query );
}

这里的代码只是简单地将客户端提供的参数信息附加到 SQL 查询语句末尾,而没有任何验证。在这种情况下,攻击者可以在输入框或 URL 参数中输入代码,这些代码就会被执行。

关键点不在于攻击者只能在 SELECT 查询中添加“' OR 1=1”,而在于攻击者可以操纵任何类型的 SQL 查询(如 INSERT、UPDATE、DELETE、DROP 等),并利用数据库支持的任何功能对其进行扩展。目前公共领域有许多优秀的资源和工具,展示了这些攻击的可能性。

我们很快就会学习如何修复这个问题。首先,让我们了解一下它可能造成的破坏程度。

为什么 SQL 注入如此危险

以下是 SQL 注入导致数据泄露的三个典型案例:

  • 伊利诺伊州选举委员会网站 遭到入侵,原因正是 SQL 注入漏洞。攻击者窃取了 20 万名美国公民的个人数据。由于该漏洞的性质,攻击者本可以篡改数据,尽管他们最终没有这样做。
  • 南非网站托管公司 Hetzner 遭到入侵,导致 4 万条客户记录泄露。SQL 注入漏洞使得数据库中几乎所有客户记录都有被窃取的风险。
  • 美国明尼苏达州一家天主教金融服务提供商 遭到入侵,攻击者利用 SQL 注入窃取了近 13 万名客户的账户详情,包括账号信息。

敏感数据一旦泄露,可能被用于接管账户、重置密码、窃取资金或实施欺诈。

即使是那些不被视为敏感或个人身份信息的数据,也可能被用于其他攻击。地址信息或政府身份证件号码的后四位,都可能被攻击者利用来冒充您的身份与公司联系,或重置您的密码。

一旦攻击成功,客户对公司的信任度就会下降。修复系统损坏或应对监管罚款的成本可能高达数百万美元。

但这一切并非不可避免。

防御 SQL 注入

防御 SQL 注入的关键在于明确区分应用程序中的数据与代码,让计算机能够识别哪些部分是数据,哪些是需要执行的代码。使用参数化查询即可实现这一点。

当 SQL 查询使用参数时,SQL 解释器只会将参数视为数据,而不会将其作为代码执行。

例如,像“' OR 1=1”这样的攻击将不再奏效。数据库会搜索字符串“OR 1=1”,由于在数据库中找不到该内容,它只会返回“抱歉,找不到相关信息”。

以下是 Java 中参数化查询的一个示例:

Code example showing use of parameterized SQL queries to securely insert user data.

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

对象关系映射器 (ORM),例如 .NET 系列中的 Entity Framework,默认会对查询进行参数化处理。这无需您额外操作即可有效防范 SQL 注入。

然而,您必须了解所用 ORM 的具体工作原理。例如,Java 世界中流行的 ORM Hibernate,如果使用不当,仍然可能存在 SQL 注入风险。

参数化查询是首选的最佳防御手段,但除此之外还有其他方法。存储过程也支持 SQL 参数,可用于防止 SQL 注入。请记住,存储过程 必须构建正确 才能发挥作用。

// 此处确实也需要进行验证
String custname = request.getParameter("customerName");
// 执行输入验证以检测攻击
String query = "SELECT account_balance FROM user_data WHERE user_name = ? ";

PreparedStatement pstmt = connection.preparedStatement( query );
pstmt.setString(1, custname);
ResultSet results = pstmt.executeQuery( );

务必对输入内容进行验证和清理。由于合法的应用程序用户不会输入“OR 1=1”之类的字符,因此完全没有必要允许此类输入。您可以向用户显示错误消息,或在处理前将其从输入中剔除。

话虽如此,切勿仅依赖验证和清理来保护系统。聪明的攻击者总能找到绕过这些限制的方法。它们是很好的纵深防御 (DiD) 策略,但参数化才是确保万无一失的根本途径。

另一种有效的纵深防御策略是在数据库中实施“最小权限”原则并使用输入白名单。强制执行最小权限意味着您的应用程序在数据库中不具备无限的权限。即使攻击者获得了访问权限,他们能造成的破坏也极其有限。

OWASP 提供了一份出色的 SQL 注入速查表,展示了如何在多种语言和平台上处理此漏洞……但如果您想更进一步,现在就可以在我们的平台上,用您偏好的语言挑战 SQL 注入。以下是一些热门挑战,助您快速上手:

C# 中的 SQL 注入

Node.js 中的 SQL 注入

Python Django 中的 SQL 注入

Java Spring 中的 SQL 注入

旅程开始

您在理解 SQL 注入及其修复方法方面已经取得了长足进步。太棒了!

我们已经讨论了 SQL 注入的发生方式;通常是攻击者利用输入来控制您的数据库查询,以达到其不可告人的目的。

我们也见识了 SQL 注入漏洞被利用所造成的破坏:账户可能被盗,数百万美元可能付诸东流……这简直是一场代价高昂的噩梦。

我们已经了解了如何预防 SQL 注入:

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

现在,轮到您了。实践是持续学习和精进技能的最佳途径,何不查看我们关于 SQL 注入的 学习资源,然后试用我们的 免费演示 平台?您将很快成为一名真正的安全代码战士。

标语

在 AI 驱动的开发成果发布前实现有效治理

评估 AI 辅助风险,在提交代码时强制执行安全编码策略,并加速整个软件开发生命周期的安全交付。

预约演示
资源库

探索更多博客

获取有关安全编码、人工智能治理和软件风险管理的专家内容。

浏览全部
案例研究
筛选标签
这是 div 块中的一段文本。

Supercharged Security Awareness: How Tournaments are Inspiring Developers at Erste Group

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

了解更多
案例研究
筛选标签
这是 div 块中的一段文本。

Security as culture: How Blue Prism cultivates world-class secure developers

Learn how Blue Prism, the global leader in intelligent automation for the enterprise, used Secure Code Warrior's agile learning platform to create a security-first culture with their developers, achieve their business goals, and ship secure code at speed

了解更多
案例研究
筛选标签
这是 div 块中的一段文本。

统一的安全文化:Sage 如何打造其安全倡导者项目

了解 Sage 如何通过灵活且以关系为导向的方法提升安全性,成功培养了 200 多名安全倡导者,并实现了显著的风险降低。

了解更多
博客
筛选标签
这是 div 块中的一段文本。

2026年网络安全意识月:理解人工智能安全对企业防御至关重要

目前,大多数顶级人工智能公司已公开呼吁全球放缓人工智能的发展速度,以便安全防护措施能够跟上步伐。然而事实是,严重的安全问题已经显现。随着人工智能实施带来的经济成本和风险不断累积,无数安全领导者和高管团队正处于紧迫的境地。

了解更多
博客
筛选标签
这是 div 块中的一段文本。

赋能要素 8:打造项目品牌

成功的安全编码项目不仅需要优质的内容。赋能要素 8 展示了如何通过品牌化将参与过程转变为一种令人向往、以地位为驱动的体验。

了解更多
博客
筛选标签
这是 div 块中的一段文本。

每一位员工现在都处于 AI 网络安全的最前线

企业技术格局正以一种鲜有人预料到的速度发生剧变,直到为时已晚。我们已正式跨越了从人工编写代码和基础辅助编程,进入“智能体开发生命周期”(ADLC)的时代。虽然自主 AI 智能体有望在多个职能领域实现前所未有的效率,但它们也带来了全新的安全和监管风险。

了解更多

在产品发布前确保 AI 驱动的开发安全

洞察开发风险,执行安全策略,并在整个软件开发生命周期中预防漏洞。

预约演示
未找到相关项目。