在直接回答问题之前,值得注意的是,即使攻击者所能做的只是读取他不应该能够做到的数据,那通常仍然是真的坏的。考虑到通过使用来自系统表的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 OUTFILE 或 INTO DUMPFILE 子句将结果转储到文件中。因为通过使用UNION,任何任意结果都可以是SELECTed,这允许在运行mysqld 的用户可以访问的任何位置写入具有任意内容的新文件。可以想象,这不仅可以被利用来修改 MySQL 数据库中的数据,还可以通过 shell 访问运行它的服务器 - 例如,通过将 PHP 脚本写入 webroot 然后向它发出请求,如果MySQL 服务器与 PHP 服务器共同托管。
缓解
许多因素降低了这种听起来令人印象深刻的攻击的实际可利用性:
- MySQL永远不会让您使用
INTO OUTFILE 或INTO 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 GitHub 和a quick Stack Overflow search 来看——至少有几百个用户。它添加了一个名为sys_exec 的函数来运行shell 命令。如 #2 所述,可以从 SELECT 中调用函数;希望其影响是显而易见的。引用the source 的话,这个函数“可能有安全隐患”。
缓解
大多数系统都没有安装这个扩展。