SQL注入一文快速了解:介绍、注入和预防

admin 2022年7月15日02:03:07评论13 views字数 6018阅读20分3秒阅读模式

1前言

SQL注入,一般通过输入或参数提交,通过SQL语句,攻击数据库,会造成严重的安全隐患。SQL注入是网络攻击中比较常见的方式之一,它不是利用操作系统的bug来实现攻击,而是攻击程序员的疏忽或漏洞。

2什么是SQL注入?

SQL注入是一个 Web 安全漏洞,允许攻击者干扰应用程序对其数据库进行的查询。它通常允许攻击者查看他们通常无法检索的数据。这可能包括属于其他用户的数据,或应用程序本身能够访问的任何其他数据。在许多情况下,攻击者可以修改或删除此数据,从而导致应用程序的内容或行为持续更改。

在某些情况下,攻击者可以升级 SQL 注入攻击以破坏基础服务器或其他后端基础结构,或者执行拒绝服务攻击。

成功的 SQL 注入攻击可导致对敏感数据(如密码、信用卡详细信息或个人用户信息)的未经授权的访问。近年来,许多备受瞩目的数据泄露事件都是SQL注入攻击的结果,导致声誉受损和监管罚款。在某些情况下,攻击者可以获得进入组织系统的持久后门,从而导致长期危害,并可能在很长一段时间内被忽视。

SQL注入攻击的危害性

  • SQL 注入攻击允许攻击者欺骗身份、篡改现有数据、导致拒绝问题(如取消事务或更改余额)、允许完全泄露系统上的所有数据、销毁数据或使其不可用,并成为数据库服务器的管理员。

  • SQL注入在PHP和ASP应用程序中非常普遍,因为较旧的功能接口很普遍。由于可用的编程接口的性质,J2EE 和 ASP.NET 应用程序不太可能轻易利用 SQL 注入。

  • SQL注入攻击的严重程度受到攻击者的技能和想象力的限制,在较小程度上,受到纵深防御对策的限制,例如与数据库服务器的低权限连接等。通常,将 SQL 注入视为高影响严重性。

SQL注入的影响范围

  • 语言:SQL
  • 平台:任何(需要与 SQL 数据库交互)

SQL 注入已成为数据库驱动网站的常见问题。该漏洞很容易被发现,并且很容易被利用,因此,任何具有最小用户群的网站或软件包都可能受到此类攻击的尝试。

3SQL 注入的工作原理

可以使用 SQL 注入执行的攻击类型因数据库引擎的类型而异。该攻击适用于动态 SQL 语句。动态语句是在运行时使用 Web 表单或 URI 查询字符串中的参数生成的语句。

让我们考虑一个带有登录表单的简单 Web 应用程序。HTML 表单的代码如下所示。

<form action=‘index.php’ method="post">

<input type="email" name="email" required="required"/>

<input type="password" name="password"/>

<input type="checkbox" name="remember_me" value="Remember me"/>

<input type="submit" value="Submit"/>

</form>

上面的表单接受电子邮件地址,然后密码将它们提交给名为 index.php 的 PHP 文件。它有一个选项,将登录会话存储在cookie中。我们从remember_me复选框中推断出这一点。它使用 post 方法提交数据。这意味着这些值不会显示在 URL 中。假设后端用于检查用户 ID 的语句如下所示

SELECT * FROM users WHERE email = $_POST[’email’] AND password = md5($_POST[‘password’]);
  1. 上面的语句直接使用 $_POST[] 数组的值,而不对其进行加工。
  2. 密码使用 MD5 算法进行加密。

现在让我们用第三方网站快速模拟一下SQL语句执行的场景。网站:http://sqlfiddle.com/

CREATE TABLE `users` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `email` VARCHAR(45NULL,
  `password` VARCHAR(45NULL,
  PRIMARY KEY (`id`));

insert into users (email,passwordvalues ('[email protected]',md5('admim123'));

在左边的文本框内输入以上代码,然后点击Build Schema

select * from users;

在右边的文本框内输入以上查询语句,点击Run SQL

SQL注入一文快速了解:介绍、注入和预防

返回了以下信息:SQL注入一文快速了解:介绍、注入和预防

假设用户使用[email protected] 作为账号和 admin123 作为密码。那么要对数据库执行的语句将是

SELECT * FROM users WHERE email = ‘admin@qianxin.com’ AND password = md5(‘admin123’);

可以通过注释掉密码部分并附加始终为真的条件来利用上述代码。假设攻击者在电子邮件地址字段中提供以下输入

[email protected]’ OR 1 = 1 LIMIT 1 — ‘ ]

生成的语句将如下所示。

SELECT * FROM users WHERE email = 'admim123'
OR 1 = 1 LIMIT 1 -- ' ] AND password = md5('123');

[email protected] 以单个引号结尾,该引号完成字符串引号 OR 1 = 1 LIMIT 1 是始终为 true 并将返回的结果限制为仅一条记录的条件。-- ' ]是消除密码部分的 SQL 注释。

复制上面的 SQL 语句并将其粘贴到 SQL Fiddle Run SQL 文本框中,如下所示SQL注入一文快速了解:介绍、注入和预防返回来所期待的结果SQL注入一文快速了解:介绍、注入和预防没有输入密码,但是返回了密码

  1. 该语句智能地假定使用了 md5 加密
  2. 完成单引号和右括号
  3. 将条件追加到语句中,该条件将始终为 true 通常,成功的 SQL 注入攻击会尝试许多不同的技术(如上面演示的技术)来执行成功的攻击。

其他 SQL 注入攻击类型SQL 注入可能会造成更大的危害,而不仅仅是通过传递数据。一些攻击包括

  1. 删除数据
  2. 更新数据
  3. 插入数据
  4. 在服务器上执行可下载和安装恶意程序(如木马程序)的命令
  5. 将有价值的数据(如信用卡详细信息、电子邮件和密码)导出到攻击者的远程服务器
  6. 获取用户登录详细信息等

4SQL注入的预防

验证过程旨在验证是否允许用户提交的输入类型。输入验证确保它是可接受的类型、长度、格式等。只能处理通过验证的值。它有助于防止输入字符串中插入的任何SQL语句。在某种程度上,这类似于在开门之前通过猫眼看看谁在敲门。

验证不应仅应用于允许用户键入输入的字段,这意味着您还应该以相同的程度处理以下情况:

  1. 使用正则表达式作为结构化数据(如姓名、年龄、收入、调查回复、邮政编码)的白名单,以确保强大的输入验证。
  2. 如果是一组固定的值(如下拉列表、单选按钮),请确定返回哪个值。输入数据应与提供的选项之一完全匹配。

下面显示了如何表名验证。

switch ($tableName) {
    case 'fooTable': return true;
    case 'barTable': return true;
    default: return new BadMessageException('unexpected value provided as table name');
}

然后,可以直接追加$tableName变量——它是表名的合法值和预期值之一。

对于下拉列表,验证数据非常容易。假设希望用户选择从 1 到 5 的分数,可以将 PHP 代码更改为如下所示:

<?php
if(isset($_POST["selRating"]))
{
    $number = $_POST["selRating"];
    if((is_numeric($number)) && ($number > 0) && ($number < 6))
    {
        echo "Selected rating: " . $number;
    }
    else
        echo "评分必须是 1 到 5 之间的数字!";
}

这里添加了两个简单的检查:

  1. 必须是一个数字(is_numeric()函数)。
  2. 要求$number大于 0 且小于 6,这样范围为 1–5。

必须验证从外部各方接收的数据。该规则不仅适用于网站的输入,也适用于供应商、合作伙伴、销售商或监管机构。这些供应商可能会受到攻击,甚至在他们不知情的情况下发送格式错误的数据。

参数化查询是预编译 SQL 语句的一种方法,以便您可以提供参数以便执行该语句。此方法使数据库能够识别代码并将其与输入数据区分开来。

用户输入会自动引用,并且提供的输入不会导致意图的更改,因此此编码样式有助于缓解 SQL 注入攻击。

可以将参数化查询与 MySQLi 扩展一起使用,但 PHP 5.1 在处理数据库时提供了一种更好的方法:PHP 数据对象 (PDO)。PDO 采用简化参数化查询使用的方法。此外,它使代码更易于阅读和更具可移植性,因为它在多个数据库上运行,而不仅仅是MySQL。

此代码使用带有参数化查询的 PDO 来防止 SQL 注入漏洞:

<?php
$id = $_GET['id'];
$db_connection = new PDO('mysql:host=localhost;dbname=sql_injection_example''dbuser''dbpasswd');
//准备查询
$sql = "SELECT username 
            FROM users
            WHERE id = :id"
;
$query = $db_connection->prepare($sql);
$query->bindParam(':id', $id);
$query->execute();
//获取结果
$query->setFetchMode(PDO::FETCH_ASSOC);
$result = $query->fetchColumn();
print(htmlentities($result));

存储过程 (SP) 要求开发人员将一个或多个 SQL 语句分组到一个逻辑单元中,以创建执行计划。后续执行允许自动参数化语句。简而言之,它是一种可以存储以供以后使用并多次使用的代码类型。

因此,每当需要执行查询时,只需调用存储过程,而不是一遍又一遍地编写查询。

下面是在MySQL服务器中创建存储过程的过程。例如,有一个如下所示的表:

CREATE TABLE `salary` (
    `empid` int(11NOT NULL,
    `sal` int(11DEFAULT NULL,
    PRIMARY KEY (`empid`)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

假设有一名员工需要从该表中获取有关公司工资的聚合数据。首先,您需要创建一个用户"tr":

CREATE USER 'tr'@'localhost' IDENTIFIED BY 'mypass';

该用户只需要对表所在的架构具有 EXECUTE 特权:

grant execute on hris.*  to tr@`%`

SP 的创建方式如下:


DELIMITER $$

CREATE PROCEDURE `avg_sal`(out avg_sal decimal)
BEGIN
 select avg(sal) into avg_sal from salary;
END

发出命令的过程将创建avg_sal SP,它将存储在数据库中,随时可以调用。

要从 PHP 应用程序调用 SP,可以使用 PDO:

$db_connection = new PDO('mysql:host=localhost;dbname=hris', 'tr', 'mypass');
  $query = $db_connection->exec('call avg_sal(@out)');
  $res = $query->query('
select @out')->fetchAll();
  print_r($res);

$res将根据用户的请求显示平均工资。然后,用户可以使用PHP执行输出过程。

SP 现在连接用户(员工)和表(工资),用户无法直接访问,使其成为数据库安全中必不可少的资产。

始终对每个数据库管理系统 (DBMS) 提供的用户输入使用字符转义函数。这样做是为了确保DBMS永远不会将其与开发人员提供的SQL语句混淆。

例如,在 PHP 中使用 mysql_real_escape_string() 来避免使用可能导致意外 SQL 命令的字符。登录绕过方案的修改版本如下所示:

$db_connection = mysqli_connect("localhost", "user", "password", "db");
  $username = mysqli_real_escape_string($db_connection, $_POST['username']);
  $password = mysqli_real_escape_string($db_connection, $_POST['password']);
  $query = "SELECT * FROM users WHERE username = '" . $username. "' AND password = '" . $password . "'"; 

进行小的更改将防止非法 SQL 注入。

避免管理权限不要使用具有 root 访问权限的帐户将应用程序连接到数据库。只有在绝对需要的情况下才应执行此操作,因为攻击者可以访问整个系统。即使是非管理帐户服务器也可能给应用程序带来风险,如果数据库服务器由多个应用程序和数据库使用,则风险更大。

因此,最好对数据库强制实施最小特权,以保护应用程序免受 SQL 注入的影响。确保每个应用程序都有自己的数据库凭据,并且这些凭据具有应用程序所需的最低权限。

与其尝试确定应取消哪些访问权限,不如专注于确定应用程序需要哪些访问权限或提升的权限。如果用户只需要访问某些部分,则可以创建严格执行此功能的模式。

5总结

SQL 注入是一种利用错误 SQL 语句的攻击类型 SQL 注入可用于绕过登录算法,检索、插入、更新和删除数据。SQL注入工具包括SQLMap,SQLPing和SQLSmack等。编写 SQL 语句时良好的安全策略可以帮助减少 SQL 注入攻击。

6写在最后

关于公众号

HackerDo安全专注于收集最新网络安全消息,发布各类漏洞信息以及修复方案,关注各大比赛,及时带来最新动态以及知识教程。我们会不定期分享漏洞PoC以及知识干货,不定期送出福利。

微信交流群

如果失效请在后台回复“粉丝群”获取最新加群方式!

SQL注入一文快速了解:介绍、注入和预防

QQ社区群

SQL注入一文快速了解:介绍、注入和预防


原文始发于微信公众号(HackerDo安全):SQL注入一文快速了解:介绍、注入和预防

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年7月15日02:03:07
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   SQL注入一文快速了解:介绍、注入和预防https://cn-sec.com/archives/1178761.html

发表评论

匿名网友 填写信息