在 sql 中不转义我的输入是否安全

is it safe to not escape my input in sql

我想知道我应该只对用户输入使用命名参数,还是必须对所有用户都使用命名参数,例如

$id = $_POST['id'] ; 

$update = $conn->prepare("UPDATE users SET profile ='reset', 
status='closed' WHERE id = :id ") ;
$update->bindValue(":id",$id,PDO::PARAM_INT) ;
$update->execute() ;

我对 id 使用了命名参数,因为那是用户输入的,但是至于配置文件,那是我输入的状态,这是不好的和不安全的吗?我也应该为那些使用命名参数吗

只有当您接受用户输入而不以某种方式转义它时才不安全。

您自己的 而非 来自 $_POST$_GET$_COOKIE$_REQUEST 的输入是完全安全的。


Edit 正如 Bill Karwin 指出的那样,当然还有其他潜在的危险源。我想我应该澄清我的观点:

不要相信任何可能被用户输入污染的数据源

认为您只需要担心用户输入的想法是错误的。

您的代码可以从任何来源获取不安全的内容,例如:

  • 正在读取文件
  • 打开一个URL,就像调用网络服务
  • 正在从您自己的数据库中读取

没错,即使已经安全地插入到您自己的数据库中的数据也可能成为不安全的内容。

示例:假设您要查找与用户 123 同名的所有用户(我知道这可以通过 JOIN 来完成,但这只是一个示例,请耐心等待):

$name = $conn->query("SELECT name FROM users WHERE id=123")->fetchColumn();

$data = $conn->query("SELECT * FROM users WHERE name = '$name'")->fetchAll();

这里安全吗? $name 是我从数据库中得到的东西,我们假设它是在早些时候安全插入的。我自己数据库中的数据怎么会成为 SQL 注入的风险?

如果名字是"O'Reilly"怎么办?这至少会导致第二个查询出现语法错误,因为单引号会不平衡。

从技术上讲,这是 SQL 注入,但与任何险恶的黑客攻击尝试相比,风险更可能是一个简单的错误。

另一方面,在真实案例中,黑客故意在网站上注册他们的 "name",从而利用 SQL 注入或跨站点脚本。当网站稍后在其他查询或网络输出中使用攻击者的名字时,它就成功地进行了黑客攻击。我没开玩笑。

像往常一样,解决方案是使用带有查询参数的准备语句:

$stmt = $conn->prepare("SELECT * FROM users WHERE name = ?");
$stmt->execute([$name]);
$data = $stmt->fetchAll();

SQL 注入仅来自用户输入的猜测让我想起了这句话:

"Explanations exist; they have existed for all time; there is always a well-known solution to every human problem — neat, plausible, and wrong." — H. L. Mencken