MySQL 注入 - 使用 SELECT 查询来更新/删除

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5759603/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 19:36:57  来源:igfitidea点击:

MySQL Injection - Use SELECT query to UPDATE/DELETE

mysqlsecurityselectcode-injectionsql-delete

提问by Simon

I've got one easy question: say there is a site with a query like:

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

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

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

Is there any way to get something updated/deleted in the database (MySQL)? Until now I've never seen an injection that was able to delete/update using a SELECT query, so, is it even possible?

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

采纳答案by a1ex07

If you say you use mysql_querythat doesn't support multiple queries, you cannot directly add DELETE/UPDATE/INSERT, but it's possible to modify data under some circumstances. For example, let's say you have the following function

如果你说你使用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 //

Now you can call this function in SELECT:
SELECT id, name, message FROM messages WHERE id = NULL OR testP()(id = NULL- always NULL(FALSE), so testP() always gets executed.

现在,你可以调用这个函数SELECT
SELECT id, name, message FROM messages WHERE id = NULL OR testP()id = NULL-总是NULL(FALSE),所以testP()总会被执行。

回答by Mark Amery

Before directly answering the question, it's worth noting that even if all an attacker can do is readdata that he shouldn't be able to, that's usuallystill really bad. Consider that by using JOINs and SELECTing from system tables (like mysql.innodb_table_stats), an attacker who starts with a SELECTinjection and no other knowledge of your databasecan map your schema and then exfiltrate the entirety of the data that you have in MySQL. For the vast majority of databases and applications, that alreadyrepresents a catastrophic security hole.

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

But to answer the question directly: there are a few ways that I know of by which injection into a MySQL SELECTcan be used to modify data. Fortunately, they all require reasonablyunusual circumstances to be possible. All example injections below are given relative to the example injectable query from the question:

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

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

1. "Stacked" or "batched" queries.

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

The classic injection technique of just putting an entire other statement after the one being injected into. As suggested in another answer here, you could set $_GET['q']to 1; DELETE FROM users; --so that the query forms two statements which get executed consecutively, the second of which deletes everything in the userstable.

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

In mitigation

在缓解

Most MySQL connectors - notably including PHP's (deprecated) mysql_*and (non-deprecated) mysqli_*functions - don't support stacked or batched queries at all, so this kind of attack just plain doesn't work. However, some do- notably including PHP's PDO connector (although the support can be disabled to increase security).

大多数 MySQL 连接器——特别是包括 PHP 的(不推荐使用的)mysql_*和(非推荐使用的)mysqli_*函数——根本不支持堆叠或批量查询,因此这种攻击是行不通的。但是,有些是这样做的——特别是包括 PHP 的 PDO 连接器(尽管可以禁用该支持以提高安全性)。

2. Exploiting user-defined functions

2. 利用用户定义的函数

Functions can be called from a SELECT, and can alter data. If a data-altering function has been created in the database, you could make the SELECTcall it, for instance by passing 0 OR SOME_FUNCTION_NAME()as the value of $_GET['q'].

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

In mitigation

在缓解

Most databases don't contain any user-defined functions - let alone data-altering ones - and so offer no opportunity at all to perform this sort of exploit.

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

3. Writing to files

3. 写入文件

As described in Muhaimin Dzulfakar's (somewhat presumptuously named) paper Advanced MySQL Exploitation, you can use INTO OUTFILEor INTO DUMPFILEclauses on a MySQL select to dump the result into a file. Since, by using a UNION, any arbitrary result can be SELECTed, this allows writing new files with arbitrary content at any location that the user running mysqldcan access. Conceivably this can be exploited not merely to modify data in the MySQL database, but to get shell access to the server on which it is running - for instance, by writing a PHP script to the webroot and then making a request to it, if the MySQL server is co-hosted with a PHP server.

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

In mitigation

在缓解

Lots of factors reduce the practical exploitability of this otherwise impressive-sounding attack:

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

  • MySQL will neverlet you use INTO OUTFILEor INTO DUMPFILEto overwrite an existing file, nor write to a folder that doesn't exist. This prevents attacks like creating a .sshfolder with a private key in the mysqluser's home directory and then SSHing in, or overwriting the mysqldbinary itself with a malicious version and waiting for a server restart.
  • Any halfway decent installation package will set up a special user (typically named mysql) to run mysqld, and give that user only very limited permissions. As such, it shouldn't be able to write to most locations on the file system - and certainly shouldn't ordinarily be able to do things like write to a web application's webroot.
  • Modern installations of MySQL come with --secure-file-privset by default, preventing MySQL from writing to anywhere other than a designated data import/export directory and thereby rendering this attack almost completely impotent... unless the owner of the server has deliberately disabled it. Fortunately, nobody would ever just completely disable a security feature like that since that would obviously be - oh wait never mind.
  • MySQL永远不会让您使用INTO OUTFILEINTO DUMPFILE覆盖现有文件,也不会写入不存在的文件夹。这可以防止攻击,例如.sshmysql用户的主目录中创建一个带有私钥的文件夹然后通过 SSH 进入,或者mysqld用恶意版本覆盖二进制文件本身并等待服务器重启。
  • 任何像样的安装包都会设置一个特殊的用户(通常名为mysql)来运行mysqld,并且只给该用户非常有限的权限。因此,它不应该能够写入文件系统上的大多数位置 - 当然通常也不应该能够执行诸如写入 Web 应用程序的 webroot 之类的操作。
  • MySQL 的现代安装--secure-file-priv默认带有set,防止 MySQL 写入指定的数据导入/导出目录以外的任何地方,从而使这种攻击几乎完全无效……除非服务器的所有者故意禁用它。幸运的是,没有人会完全禁用这样的安全功能,因为这显然是 -哦,等等,别介意

4. Calling the sys_exec()function from lib_mysqludf_systo run arbitrary shell commands

4. 调用sys_exec()函数 fromlib_mysqludf_sys运行任意 shell 命令

There's a MySQL extension called lib_mysqludf_systhat - judging from its stars on GitHuband a quick Stack Overflow search- has at least a few hundred users. It adds a function called sys_execthat runs shell commands. As noted in #2, functions can be called from within a SELECT; the implications are hopefully obvious. To quote from the source, this function "can be a security hazard".

有一个名为lib_mysqludf_sys它的 MySQL 扩展——从它在 GitHub 上的星星和一个快速的 Stack Overflow 搜索来看——至少有几百个用户。它添加了一个名为sys_exec运行 shell 命令的函数。如#2 中所述,可以从SELECT; 中调用函数。其影响是显而易见的。引用来源,此功能“可能存在安全隐患”

In mitigation

在缓解

Most systems don't have this extension installed.

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

回答by Demento

It depends on the DBMS connector you are using. Most of the time your scenario should not be possible, but under certain circumstances it could work. For further details you should take a look at chapter 4 and 5 from the Blackhat-Paper Advanced MySQL Exploitation.

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

回答by Pentium10

Yes it's possible.

是的,这是可能的。

$_GET['q'] would hold 1; DELETE FROM users; --

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

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