【问题标题】:When you absolutely have to manually escape SQL in CakePHP 3.4.7当您必须在 CakePHP 3.4.7 中手动转义 SQL 时
【发布时间】:2017-10-20 14:41:47
【问题描述】:

所以我想在 CakePHP 3.4.7 中执行以下 SQL 查询:

DROP DATABASE $databasename

我发现这不起作用:

$conn->execute("DROP DATABASE :databasename", ['databasename' => $databasename]);

...因为 MySQL 不接受数据库和表名作为准备好的语句中的参数(请参阅Can PHP PDO Statements accept the table or column name as parameter?

我不能使用 CakePHP 的 Sanitize 类,因为它在 CakePHP 3 (https://book.cakephp.org/3.0/en/appendices/3-0-migration-guide.html#sanitize) 中已被弃用

我不能使用 mysqli::real_escape_string 因为 AFAIK 没有 mysqli 对象...

有人知道替代品吗?

【问题讨论】:

  • 转义不起作用,因为这将用于引号,引号不适用于表/列。您可以将允许的条款列入白名单,然后将其传入。
  • 我想我应该只担心插入分号?但我也在考虑采用白名单方式。
  • 我猜你有一个可以删除的数据库列表。您不能只检查该术语是否在该列表中吗?
  • 有一个列表,但我也不相信。

标签: php mysql cakephp-3.0


【解决方案1】:

当你不能依赖别人的代码来保证安全时,这真是太糟糕了,因为让我们面对现实吧,绝大多数人都没有做好安全工作。最好依赖这些库!

但是,在您无法做到的情况下(例如这种情况),请考虑为您期望的内容设置一个小的可能性白名单。想想你期望看到什么,并执行它。在我看来,我希望数据库名称由字母和下划线组成。这显然不会涵盖所有可能的表名称值(例如,数据库名称也可以有数字),但您的情况决定了什么是重要的。

考虑到这一点,一个可能的清理例程可能是一个简单的正则表达式,它强制传递的名称没有空格,以字母开头,之后可能有更多的字母或下划线,并且总字符数不能超过 16 个长:

if ( ! preg_match('/^[A-z][A-z_]{0,15}$/', $databasename) ) {
    # database name does not pass the project standards of alpha
    # letters and underscores only.  Likely crack attempt.
    die('No way, Joker!');   # or something more appropriate.
}

这不是 DB 驱动程序提供的完整性,但它简单、易于阅读,并且适用于 >90% 的所有数据库名称。通过上述健全性检查后,您可以直接编写一般认为在这种情况下安全的 SQL 字符串:

$conn->execute("DROP DATABASE $databasename");

【讨论】:

    猜你喜欢
    • 2012-05-15
    • 1970-01-01
    • 2020-07-01
    • 2011-05-21
    • 2018-08-28
    • 2014-06-07
    • 2016-11-26
    • 2018-12-26
    • 2017-10-10
    相关资源
    最近更新 更多