Php 即使使用SQLite3::escapeString()且不要求用户输入,也存在SQL注入漏洞?

Php 即使使用SQLite3::escapeString()且不要求用户输入,也存在SQL注入漏洞?,php,sqlite,sql-injection,Php,Sqlite,Sql Injection,我指的是另一个用户批评的,因为它容易受到SQL注入的攻击,即使没有请求用户输入并调用转义过程。 以下代码用于创建SQLite数据库的.sql转储,只使用PHP代码,不调用sqlite3工具(这是问题作者的原始请求) 在电子商务应用程序中命名表Order是非常合理的,但如果运行以下查询,则会导致语法错误: SELECT * FROM Order 为什么??因为订单是一个。它引入了一个orderby子句。以这种方式使用名为Order的表只会创建语法错误 SQLite允许您通过分隔表名,在保留字之后

我指的是另一个用户批评的,因为它容易受到SQL注入的攻击,即使没有请求用户输入并调用转义过程。 以下代码用于创建SQLite数据库的.sql转储,只使用PHP代码,不调用sqlite3工具(这是问题作者的原始请求)


在电子商务应用程序中命名表
Order
是非常合理的,但如果运行以下查询,则会导致语法错误:

SELECT * FROM Order
为什么??因为
订单
是一个。它引入了一个
orderby
子句。以这种方式使用名为
Order
的表只会创建语法错误

SQLite允许您通过分隔表名,在保留字之后命名表

这是我链接到的关于保留字的文档:

“关键字”单引号中的关键字是字符串文字

“关键字”双引号中的关键字是标识符

[关键字]方括号中的关键字是标识符。这不是标准的SQL。此引用机制由MS Access和SQL Server使用,并包含在SQLite中以实现兼容性

`关键字`用严重重音符号括起来的关键字(ASCII代码96)是一个标识符。这不是标准的SQL。MySQL使用这种引用机制,为了兼容性,它包含在SQLite中

因此,您可以使用名为
Order
的表,而不会出现如下错误:

SELECT * FROM "Order"
您不应该使用
SQLite3::escapeString($table[0])
,因为这是用于字符串文本的。请记住,从上面的列表中,单引号字符串是字符串文字。escapeString()函数只转义
字符,因此您可以将该字符串放在单引号内作为分隔符,因此可以使用类似
'O'Reilly'
的字符串

但是escapeString()对用于分隔表名的双引号没有任何作用。没有为此提供函数。因此,您必须确保没有包含
字符的表名,或者使用其他PHP函数来转义它们

$safeTable = str_replace('"', '\\"', $table[0]);
$rows = $db->query("SELECT * FROM \"{$safeTable}\"");

您还应该阅读8。本页接受双引号字符串文本:

如果您的表名中有一个包含空格或
-
或SQL保留字或其他内容,该怎么办?SQL注入不一定是恶意的,也不一定是试图访问未经授权的数据。实际上,SQL注入更常见的是simple error导致语法错误。此用户指的是SQL本身中的
$table[0]
。尽可能使用准备好的语句是一个好主意。@AlexBarker适当地指出,是的,我现在明白了,并对
$table[0]进行了转义
我想应该能解决这个问题吗?@BillKarwin和@AlexBarker我还是很想有一个最坏情况的明确例子,在这种情况下,即使风险因素与表名和列名/值的不可预测的组合可能会产生任何后果,使用
的SQLite3::escapeString($table[0])“
everywhere
$table[0]
插入到查询中,是一个可接受的解决方法吗?好的,通过跳过几个超链接,我找到了这个答案:我是一个狂热者,使用SQL或任何与计算机相关的东西都不是我的工作,所以我倾向于相信答案中所写的一切都是真实的,因为我无论如何都不知道。我错了多少直到现在…感谢您阅读了我读到的第一个“自sql注入的工作示例”。我从中得到的教训是“永远不要给表指定保留名称,但无论如何,在表名中使用\”是非常愚蠢的。确认了我的观点,即对于此用例,重复使用准备好的语句将过于工程化。准备好的语句无论如何都不会有帮助,因为不能对表名使用查询参数。上面的一些评论是错误的。查询参数只能代替常量值,不能代替标识符、SQL关键字、表达式等。
$safeTable = str_replace('"', '\\"', $table[0]);
$rows = $db->query("SELECT * FROM \"{$safeTable}\"");