即使使用 SQLite3::escapeString() 并且没有询问用户输入,也会存在 SQL 注入漏洞?
Vulnerability to SQL injection even when SQLite3::escapeString() is used and no user input is asked?
我指的是 this answer of mine to another question,另一位用户批评它容易受到 SQL 注入,即使没有请求用户输入并调用转义过程。
以下代码用于创建 SQLite 数据库的 .sql 转储,仅使用 PHP 代码,没有调用 sqlite3 工具(这是原始请求问题的作者)。
<?php
$db = new SQLite3(dirname(__FILE__)."/your/db.sqlite");
$db->busyTimeout(5000);
$sql="";
$tables=$db->query("SELECT name FROM sqlite_master WHERE type ='table' AND name NOT LIKE 'sqlite_%';");
while ($table=$tables->fetchArray(SQLITE3_NUM)) {
$sql.=$db->querySingle("SELECT sql FROM sqlite_master WHERE name = '{$table[0]}'").";\n\n";
$rows=$db->query("SELECT * FROM {$table[0]}");
$sql.="INSERT INTO {$table[0]} (";
$columns=$db->query("PRAGMA table_info({$table[0]})");
$fieldnames=array();
while ($column=$columns->fetchArray(SQLITE3_ASSOC)) {
$fieldnames[]=$column["name"];
}
$sql.=implode(",",$fieldnames).") VALUES";
while ($row=$rows->fetchArray(SQLITE3_ASSOC)) {
foreach ($row as $k=>$v) {
$row[$k]="'".SQLite3::escapeString($v)."'";
}
$sql.="\n(".implode(",",$row)."),";
}
$sql=rtrim($sql,",").";\n\n";
}
file_put_contents("sqlitedump.sql",$sql);
在对这个答案的评论中,用户@Dharman 坚称这段代码存在漏洞,在要求提供一个完整的案例说明它如何导致问题之后,他告诉我只打开一个关于事.
我个人认为这段代码不可能 "explode" 因为数据库中已经存在的内容将被转储,但我没有权限。
所以我问你。
在电子商务应用程序中命名 table Order
是非常合理的,但是如果您 运行 像这样的查询,这会导致语法错误:
SELECT * FROM Order
为什么?因为 Order
是一个 reserved keyword in SQLite。它引入了一个 ORDER BY
子句。以这种方式使用名为 Order
的 table 只会产生语法错误。
SQLite 允许您通过分隔 table 名称来在保留字之后命名 tables。
这是我链接到的关于保留字的文档:
'keyword' A keyword in single quotes is a string literal.
"keyword" A keyword in double-quotes is an identifier.
[keyword] A keyword enclosed in square brackets is an identifier. This is not standard SQL. This quoting mechanism is used by MS Access and SQL Server and is included in SQLite for compatibility.
`keyword` A keyword enclosed in grave accents (ASCII code 96) is an identifier. This is not standard SQL. This quoting mechanism is used by MySQL and is included in SQLite for compatibility.
因此您可以使用名为 Order
的 table 而不会像这样出现错误:
SELECT * FROM "Order"
您不应该使用 SQLite3::escapeString($table[0])
,因为那是针对字符串文字的。请记住上面的列表,单引号字符串是字符串文字。 escapeString() 函数只转义 '
个字符,因此您可以将该字符串放在单引号内作为分隔符,因此您可以使用 'O\'Reilly'
.
这样的字符串
但是 escapeString() 对用于分隔 table 名称的双引号没有任何作用。没有为此提供的功能。因此,您要么必须确保没有包含 "
字符的 table 名称,要么使用其他 PHP 函数来转义它们。
$safeTable = str_replace('"', '\"', $table[0]);
$rows = $db->query("SELECT * FROM \"{$safeTable}\"");
您还应该阅读 8。本页接受双引号字符串文字:https://www.sqlite.org/quirks.html
我指的是 this answer of mine to another question,另一位用户批评它容易受到 SQL 注入,即使没有请求用户输入并调用转义过程。 以下代码用于创建 SQLite 数据库的 .sql 转储,仅使用 PHP 代码,没有调用 sqlite3 工具(这是原始请求问题的作者)。
<?php
$db = new SQLite3(dirname(__FILE__)."/your/db.sqlite");
$db->busyTimeout(5000);
$sql="";
$tables=$db->query("SELECT name FROM sqlite_master WHERE type ='table' AND name NOT LIKE 'sqlite_%';");
while ($table=$tables->fetchArray(SQLITE3_NUM)) {
$sql.=$db->querySingle("SELECT sql FROM sqlite_master WHERE name = '{$table[0]}'").";\n\n";
$rows=$db->query("SELECT * FROM {$table[0]}");
$sql.="INSERT INTO {$table[0]} (";
$columns=$db->query("PRAGMA table_info({$table[0]})");
$fieldnames=array();
while ($column=$columns->fetchArray(SQLITE3_ASSOC)) {
$fieldnames[]=$column["name"];
}
$sql.=implode(",",$fieldnames).") VALUES";
while ($row=$rows->fetchArray(SQLITE3_ASSOC)) {
foreach ($row as $k=>$v) {
$row[$k]="'".SQLite3::escapeString($v)."'";
}
$sql.="\n(".implode(",",$row)."),";
}
$sql=rtrim($sql,",").";\n\n";
}
file_put_contents("sqlitedump.sql",$sql);
在对这个答案的评论中,用户@Dharman 坚称这段代码存在漏洞,在要求提供一个完整的案例说明它如何导致问题之后,他告诉我只打开一个关于事.
我个人认为这段代码不可能 "explode" 因为数据库中已经存在的内容将被转储,但我没有权限。 所以我问你。
在电子商务应用程序中命名 table Order
是非常合理的,但是如果您 运行 像这样的查询,这会导致语法错误:
SELECT * FROM Order
为什么?因为 Order
是一个 reserved keyword in SQLite。它引入了一个 ORDER BY
子句。以这种方式使用名为 Order
的 table 只会产生语法错误。
SQLite 允许您通过分隔 table 名称来在保留字之后命名 tables。
这是我链接到的关于保留字的文档:
'keyword' A keyword in single quotes is a string literal.
"keyword" A keyword in double-quotes is an identifier.
[keyword] A keyword enclosed in square brackets is an identifier. This is not standard SQL. This quoting mechanism is used by MS Access and SQL Server and is included in SQLite for compatibility.
`keyword` A keyword enclosed in grave accents (ASCII code 96) is an identifier. This is not standard SQL. This quoting mechanism is used by MySQL and is included in SQLite for compatibility.
因此您可以使用名为 Order
的 table 而不会像这样出现错误:
SELECT * FROM "Order"
您不应该使用 SQLite3::escapeString($table[0])
,因为那是针对字符串文字的。请记住上面的列表,单引号字符串是字符串文字。 escapeString() 函数只转义 '
个字符,因此您可以将该字符串放在单引号内作为分隔符,因此您可以使用 'O\'Reilly'
.
但是 escapeString() 对用于分隔 table 名称的双引号没有任何作用。没有为此提供的功能。因此,您要么必须确保没有包含 "
字符的 table 名称,要么使用其他 PHP 函数来转义它们。
$safeTable = str_replace('"', '\"', $table[0]);
$rows = $db->query("SELECT * FROM \"{$safeTable}\"");
您还应该阅读 8。本页接受双引号字符串文字:https://www.sqlite.org/quirks.html