假设您让用户插入他们的名字(或任何东西到表中),并且有人尝试SQL注入,但您正确使用准备好的语句,因此查询不受影响。
$stmt = $db->prepare("INSERT INTO users (user_name) VALUES (?)");
$stmt->bindParam(1, $_POST['user_name']);
但是现在您使用插入到user_name
列中的值并将其插入到另一个表中。
$stmt = $db->prepare("INSERT INTO different_table (name) VALUES (
SELECT user_name FROM users WHERE userId = ?
)");
user_name
是否被视为字符串(假设varchar
数据类型)?换句话说,您是否只需要在用户输入第一次被插入并来自客户端时准备它?
编辑
如果user_name
中的值包含注入,现在我想在另一个表中插入此值,我是否需要首先运行select
以获得值,然后在准备好的语句中使用它,当我做插入?像这样?
$stmt = $db->prepare("SELECT user_name FROM users WHERE user_id = 1");
然后
$stmt = $db->prepare("INSERT INTO another_table (name) VALUES (?)");
$stmt->bindParam(1, $resultFromFirstQuery['user_name']);
或者我可以这样做吗?
$stmt = $db->prepare("INSERT INTO different_table (name) SELECT user_name FROM users WHERE userId = ?");
我认为没有SQL注入是可能的,因为没有SQL语句被构造。换句话说,SQL注入只能发生在创建SQL语句的编程语言中,而不能发生在SQL语句本身中。
详细说明:SQL注入攻击的核心是未经检查的用户输入使用生成超出用户输入原始目的的SQL语句。例如,如果你的程序这样做
$sql = "SELECT * FROM Users WHERE Email = '{input.email}'"
和用户输入
hacker@example.com' OR 1 = 1; --
{输入。,那么变量$sql
最终是
SELECT * FROM Users WHERE Email = 'hacker@example.com' OR 1 = 1; -- '
安全风险现在来自于在数据库上执行这个未检查的语句。
在你的例子中没有SQL正在被构造。如果执行语句
INSERT INTO table1 SELECT * FROM table2
则不允许将未经检查的用户输入附加到查询字符串中。SELECT
的结果可能包含在被视为SQL时不安全的输入,但是文本字段的值永远不会作为数据库上的语句运行,因此表中是否包含12345
或hacker@example.com' OR 1 = 1; --
是无关的。
我能想到的唯一情况是,如果您的数据库服务器有一个错误,并且在特定位置的内存中有一些特定的字节集可能导致内存溢出,然后打开攻击向量。但这是你无法控制的,数据库供应商可能会很快修复;这也是你不能做的事情,与SQL注入无关。