即使使用SQLite3::escapeString()并且没有要求用户输入,SQL注入漏洞也存在吗? - php

我指的是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坚持认为此代码易受攻击,并在要求提供有关如何导致问题的完整示例之后,他告诉我只想就此问题进行提问。

我个人觉得此代码无法“爆炸”,因为要转储的数据库中已经存在这些内容,但是我没有权限。
所以我问你。

参考方案

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

SELECT * FROM Order

为什么?因为Order是reserved keyword in SQLite。它引入了ORDER BY子句。以这种方式使用名为Order的表只会产生语法错误。
SQLite允许您通过分隔表名来在保留字之后命名表。
这是我链接到的文档中有关保留字的内容:

'keyword'单引号中的关键字是字符串文字。
“关键字”用双引号引起来的关键字是一个标识符。
[关键字]用方括号括起来的关键字是一个标识符。这不是标准的SQL。此引用机制由MS Access和SQL Server使用,并且包含在SQLite中以实现兼容性。
`keyword`用重音符号(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。本页接受双引号的字符串文字:https://www.sqlite.org/quirks.html

PHP-MySQL结果转换为JSON - php

我试图了解如何将MySQL结果转换为JSON格式,以便以后可以在Javascript中使用此JSON来构建HTML表。但是我的代码只是产生大量的空值,我还不明白为什么。$result = mysqli_query($con, "SELECT * FROM Customers"); $test = json_encode($result);…

PHP Count数组元素 - php

嗨,有人可以解释为什么这会返回“数组由0个元素组成”。 :$arr = array(1,3,5); $count = count($arr); if ($count = 0) { echo "An array is empty."; } else { echo "An array has $count elements.…

PHP:从函数返回值并直接回显它? - php

这可能是一个愚蠢的问题,但是……的PHPfunction get_info() { $something = "test"; return $something; } html<div class="test"><?php echo get_info(); ?></div> 有没有办…

PHP:将数据从二维数组复制到一维数组的最快方法 - php

我有一个巨大的二维PHP数组,带有500万行。$t = [ [ "id" => 1, "name" => "foo" ], [ "id" => 2, "name" => "bar" ] ]; 现在,我必须将此数组的I…

PHP str_replace是否具有大于13个字符的限制? - php

直到击中第13个字符为止。一旦str_ireplace在cyper数组中击中“ a”,str_ireplace就停止工作。数组的大小有限制吗?请记住,如果键入“ abgf”,我会得到“ nots”,但是如果键入“ abgrf”,我应该得到“ notes”,那么我就会得到“ notrs”。机架使我的大脑无法解决。$_cypher = array("n…