在sql中不能逃避我的输入是安全的

时间:2018-05-24 16:08:17

标签: php sql pdo escaping sql-injection

我想知道我是否应该仅为用户输入使用命名参数,或者我必须为所有人使用例如

$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的命名参数,因为那是用户输入,但是对于配置文件,从我输入的状态是不是很糟糕且不安全?我应该为那些使用命名参数

2 个答案:

答案 0 :(得分:4)

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

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

  • 阅读文件
  • 打开网址,例如调用网络服务
  • 从您自己的数据库中读取

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

示例:假设您要查找与用户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注入,虽然风险更可能是一个简单的错误,而不是任何险恶的黑客攻击。

另一方面,有一些黑客故意在网站上注册其“名称”,以便利用SQL注入或跨站点脚本。当攻击者的名字后来被网站用于其他一些查询或网络输出时,它就成功地进行了攻击。我不是在开玩笑。

通常,解决方案是使用带有查询参数的预准备语句:

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

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

  

“解释存在;它们一直存在;每个人类问题都有一个众所周知的解决方案 - 整洁,合理和错误。” - H. L. Mencken

答案 1 :(得分:1)

如果您接受用户输入而不是以某种方式逃避它,那将是不安全的。

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

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

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