gpt4 book ai didi

php - 这个函数是否容易受到 SQL 注入(inject)攻击?

转载 作者:可可西里 更新时间:2023-11-01 06:36:41 29 4
gpt4 key购买 nike

我构建了一个函数来使用 PDO 检查数据库中是否存在表,但我不确定我是否已正确保护它。

public function tableExists($table){
try{
$this->query('SELECT 1 FROM `'.str_replace('`', '', $table).'` LIMIT 1');
}catch(\PDOException $e){
if($e->errorInfo[1] == 1146){
return false;
}
throw $e;
}
return true;
}

如果 $table 是直接从用户输入提供的,攻击者是否有可能破坏查询? (极端情况)

最佳答案

不,您的代码不容易受到 SQL 注入(inject)攻击

然而,这也许更多的是侥幸而不是其他任何事情。

要正确处理用户提供的值,通常希望转义任何具有特殊含义的字符(而不是简单地删除它们)。如 Schema Object Names 下所述:

Identifier quote characters can be included within an identifier if you quote the identifier. If the character to be included within the identifier is the same as that used to quote the identifier itself, then you need to double the character. The following statement creates a table named a`b that contains a column named c"d:

mysql> <strong>CREATE TABLE `a``b` (`c"d` INT);</strong>

那么我们如何允许任何表名,包括那些包含反引号的表名?

允许转义——尝试 1

您可能想修改您的函数以使用以下内容:

$this->query('SELECT 1 FROM `'.str_replace('`', '``', $table).'` LIMIT 1');

不要!上面的代码易受攻击的(在模糊的边缘情况下)。

str_replace()是一个简单的字节函数(它不是字符集感知的,因此与具有多字节字符的字符串编码一起使用是不安全的)。

如果您的数据库连接使用多字节字符集,例如 GBK,那么恶意表名将无法正确转义:

// malicious user-provided value
$_POST['tableName'] = "\x8c`; DROP TABLE users; -- ";

// call your function with that value
tableExists($_POST['tableName']);

以上将导致使用以下字符串参数调用 query():

SELECT 1 FROM `宍`; DROP TABLE users; -- ` LIMIT 1

这是因为当 str_replace() 逐字节遍历输入的字符串时——天真地替换了任何出现的 '`' 字符,即字节 0x60——它这样做并没有理解MySQL会认为该字符串使用GBK编码,其中0x8c60是单个字符'宍';因此它将这些字符变成 0x8c6060 代表 '宍`'。那就是 str_replace() 引入了一个以前没有的终止反引号!

允许转义——尝试 2

不过,这个问题可以通过使用字符集感知替换函数来解决。 PHP 默认情况下没有,尽管有一些可选的扩展,如 Multibyte String在典型的托管环境中相当普遍。

如果采用这种方法,您必须确保使用数据库连接的字符编码执行替换。

允许转义——尝试 3

从 MySQL v5.7.6 开始,您可以使用 mysql_real_escape_string_quote()使用数据库连接的字符集正确转义 SQL 标识符。然而遗憾的是,PDO API(还没有?)提供这个 C 函数的接口(interface)......

白名单呢?

白名单通常被认为比转义更安全可靠。然而(除非事先知道它们不包含特殊字符),仍然必须转义白名单值——所以这并不能真正帮助推进大多数一般情况,尽管它确实限制了损害如果转义被证明是错误的,可以这样做。

那么结论是什么?

实际上很难以安全的方式使用任意的、用户提供的 SQL 标识符。

幸运的是,这不是一个常见的要求。作为一般规则,一个人的架构应该是静态的(没有任何需要修改架构的代码库更改)并且符合principle of orthogonal design : 如果满足这两个条件,SQL 标识符将始终是静态代码的一部分,并且不需要在其位置使用用户输入。

关于php - 这个函数是否容易受到 SQL 注入(inject)攻击?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29320592/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com