【问题标题】:MySQL Injection - Use SELECT query to UPDATE/DELETEMySQL 注入 - 使用 SELECT 查询来更新/删除
【发布时间】:2011-04-22 20:10:31
【问题描述】:

我有一个简单的问题:假设有一个网站的查询如下:

SELECT id, name, message FROM messages WHERE id = $_GET['q']

有什么方法可以在数据库 (MySQL) 中更新/删除某些内容?到目前为止,我从未见过能够使用 SELECT 查询 删除/更新的注入,那么,这可能吗?

【问题讨论】:

  • 我会注意到,从受感染的数据库中检索到的信息通常具有更高的价值,然后才能够破坏数据。数据库内容很容易从备份中恢复,但是一旦数据被盗,就无法取回。

标签: mysql security select code-injection sql-delete


【解决方案1】:

在直接回答问题之前,值得注意的是,即使攻击者所能做的只是读取他不应该能够做到的数据,那通常仍然是真的坏的。考虑到通过使用来自系统表的JOINs 和SELECTing(如mysql.innodb_table_stats),以SELECT 注入开始并且不了解您的数据库的攻击者可以映射您的数据库。架构,然后泄露您在 MySQL 中的全部数据。对于绝大多数数据库和应用程序而言,这已经代表了一个灾难性的安全漏洞。

但要直接回答这个问题:我知道有几种方法可以通过注入 MySQL SELECT 来修改数据。幸运的是,它们都需要合理地不寻常的情况。下面的所有示例注入都是相对于问题中的示例可注入查询给出的:

SELECT id, name, message FROM messages WHERE id = $_GET['q']

1。 “堆叠”或“批量”查询。

经典的注入技术,在被注入的语句之后放置一个完整的其他语句。正如another answer here 中所建议的那样,您可以将$_GET['q'] 设置为1; DELETE FROM users; --,以便查询形成两个连续执行的语句,其中第二个语句删除users 表中的所有内容。

缓解

大多数 MySQL 连接器——特别是包括 PHP 的(不推荐使用的)mysql_* 和(不推荐使用的)mysqli_* 函数——根本不支持堆叠或批量查询,所以这种攻击根本不起作用。然而,有些 - 特别是包括 PHP 的 PDO 连接器(虽然支持 can be disabled to increase security)。

2。利用用户定义的函数

可以从SELECT 调用函数,并且可以更改数据。如果在数据库中创建了数据更改函数,您可以让SELECT 调用它,例如将0 OR SOME_FUNCTION_NAME() 作为$_GET['q'] 的值传递。

缓解

大多数数据库不包含任何用户定义的函数——更不用说改变数据的函数了——因此根本没有机会进行这种利用。

3。写入文件

如 Muhaimin Dzulfakar 的(有点冒昧地命名)论文 Advanced MySQL Exploitation 中所述,您可以在 MySQL 选择上使用 INTO OUTFILEINTO DUMPFILE 子句将结果转储到文件中。因为通过使用UNION,任何任意结果都可以是SELECTed,这允许在运行mysqld 的用户可以访问的任何位置写入具有任意内容的新文件。可以想象,这不仅可以被利用来修改 MySQL 数据库中的数据,还可以通过 shell 访问运行它的服务器 - 例如,通过将 PHP 脚本写入 webroot 然后向它​​发出请求,如果MySQL 服务器与 PHP 服务器共同托管。

缓解

许多因素降低了这种听起来令人印象深刻的攻击的实际可利用性:

  • MySQL永远不会让您使用INTO OUTFILEINTO DUMPFILE 覆盖现有文件,也不会写入不存在的文件夹。这可以防止攻击,例如在 mysql 用户的主目录中使用私钥创建 .ssh 文件夹,然后通过 SSH 进入,或使用恶意版本覆盖 mysqld 二进制文件本身并等待服务器重启。
  • 任何半途而废的安装包都会设置一个特殊用户(通常命名为mysql)来运行mysqld,并且只授予该用户非常有限的权限。因此,它不应该能够写入文件系统上的大多数位置——当然也不应该通常能够执行诸如写入 Web 应用程序的 webroot 之类的事情。
  • 现代安装的 MySQL 默认设置了--secure-file-priv,防止 MySQL 写入指定数据导入/导出目录以外的任何地方,从而使这种攻击几乎完全无效......除非服务器的所有者故意禁用它。幸运的是,没有人会完全禁用这样的安全功能,因为那显然是 - oh wait never mind

4。从lib_mysqludf_sys调用sys_exec()函数运行任意shell命令

有一个名为lib_mysqludf_sys 的MySQL 扩展——从它的星号on GitHuba quick Stack Overflow search 来看——至少有几百个用户。它添加了一个名为sys_exec 的函数来运行shell 命令。如 #2 所述,可以从 SELECT 中调用函数;希望其影响是显而易见的。引用the source 的话,这个函数“可能有安全隐患”

缓解

大多数系统都没有安装这个扩展。

【讨论】:

    【解决方案2】:

    如果你说你使用不支持多查询的mysql_query,你不能直接添加DELETE/UPDATE/INSERT,但是在某些情况下可以修改数据。例如,假设您有以下功能

    DELIMITER //
    CREATE DEFINER=`root`@`localhost` FUNCTION `testP`()
    RETURNS int(11)
    LANGUAGE SQL
    NOT DETERMINISTIC
    MODIFIES SQL DATA
    SQL SECURITY DEFINER
    COMMENT ''  
    BEGIN      
      DELETE FROM test2;
      return 1;
    END //
    

    现在您可以在SELECT 中调用此函数:
    SELECT id, name, message FROM messages WHERE id = NULL OR testP() (id = NULL - 总是 NULL(FALSE),所以 testP() 总是被执行。

    【讨论】:

      【解决方案3】:

      这取决于您使用的 DBMS 连接器。大多数情况下,您的方案不应该是可能的,但在某些情况下它可以工作。有关更多详细信息,您应该查看Blackhat-Paper Advanced MySQL Exploitation 中的第 4 章和第 5 章。

      【讨论】:

        【解决方案4】:

        是的,这是可能的。

        $_GET['q'] 将持有1; DELETE FROM users; --

        SELECT id, name, message FROM messages WHERE id = 1; DELETE FROM users; -- whatever here');
        

        【讨论】:

        • MySQL 不支持堆叠查询
        • @Kevin,确实如此。例如,如果您复制该确切查询并在 phpmyadmin 中运行它,它将无错误地运行。但是,如果您使用不支持多个查询的 mysql 库,则会出现错误。例如,如果您使用 php 的函数 mysql_query 并输入该 sql 查询,您将得到一个错误,它不支持一次调用中的多个查询,但如果您使用 mysqli 库,则查询运行良好。
        • php 中的 mysql_query 不支持它:|我猜这是基于 PHP 的网站中最常用的一种……有没有办法解决这个问题?
        • 任何包含“最常用”或“我猜”的答案都是不正确的。
        猜你喜欢
        • 2011-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-02
        • 2021-07-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-05
        相关资源
        最近更新 更多