如果插入用户输入而不修改SQL查询,则应用程序容易受到SQL注入的攻击,如下例所示:
$unsafe_variable = $_POST['user_input'];
mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");
Run Code Online (Sandbox Code Playgroud)
这是因为用户可以输入类似的内容value'); DROP TABLE table;--,查询变为:
INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')
Run Code Online (Sandbox Code Playgroud)
可以采取哪些措施来防止这种情况发生?
假设我有这样的代码:
$dbh = new PDO("blahblah");
$stmt = $dbh->prepare('SELECT * FROM users where username = :username');
$stmt->execute( array(':username' => $_REQUEST['username']) );
Run Code Online (Sandbox Code Playgroud)
PDO文件说:
准备语句的参数不需要引用; 司机为你处理.
这真的是我需要做的就是避免SQL注入吗?这真的很容易吗?
如果它有所作为,你可以假设MySQL.另外,我真的只是对使用针对SQL注入的预处理语句感到好奇.在这种情况下,我不关心XSS或其他可能的漏洞.
我一直在读很多关于准备好的陈述,在我读过的所有内容中,没有人谈到使用它们的缺点.因此,我想知道是否有人会忽视的"有龙"斑点?
这是一个类似的问题"何时不使用预备语句?" ,但使用"how-to"-part和PostgreSQL.
我知道我需要准备好的语句,因为我在一个脚本中对数据库进行了多次调用.
我想得到关于以下句子的具体例子
查看类型转换,验证和清理变量以及将PDO与预准备语句一起使用.
通过验证和消毒变量,我知道他的意思.但是,我并不完全确定准备好的陈述.我们如何准备陈述?通过过滤器,即通过消毒?或者通过一些PDO层?层的定义是什么?
准备好的陈述在声明中意味着什么?请使用具体的例子.
我正在制作一个小型Web应用程序,它将定期接收用户输入的数据.在研究如何确保数据输入首先被清理时,为此它似乎是准备好的语句是要走的路.
然而,我发现了这个问题,因为我的应用程序(至少据我所知)每页请求不会执行多个查询,看起来我真正需要的是将值绑定到参数中查询.
我一直在浏览PDO和mysqli上的PHP手册,但我找不到任何值与普通查询绑定的示例.我发现的所有例子都$stmt->prepare在绑定之前的某个地方.
是否该语句是"准备好"由数据库的支持决定的东西,并且准备语句将始终在代码中?或者有没有办法将参数直接绑定到$dbh->query(...)?
为了解释为什么我要查看它是否可能不使用prepare,是由于我之前在帖子中链接的SO问题的声明:
何时不使用准备好的陈述?在数据库连接消失之前,您只需要运行一次语句.
何时不使用绑定查询参数(这实际上是大多数人使用预处理语句获取的)?
还有这个
我个人也不会打扰.伪准备语句可能对他们可能提供的安全变量引用有用.
从PHP 手册中,它指出:
PDO :: ATTR_EMULATE_PREPARES启用或禁用预准备语句的模拟.某些驱动程序不支持本机预处理语句或对它们的支持有限.使用此设置可强制PDO始终模拟预准备语句(如果为TRUE),或尝试使用本机预准备语句(如果为FALSE).如果驱动程序无法成功准备当前查询,它将始终回退到模拟预准备语句.需要布尔.
我有一个像这样的查询:
$type = PDO::PARAM_INT;
if($_POST['code'] == "") $type = PDO::PARAM_NULL;
$stmt = $dbh->prepare("UPDATE Product SET code=? WHERE id=?");
$stmt->bindValue(1, $_POST['code'], $type);
$stmt->bindValue(2, $_SESSION['id'], PDO::PARAM_INT);
$stmt->execute();
Run Code Online (Sandbox Code Playgroud)
我意识到,如果不设置以下语句,我将使用上面的代码获取'0'一个NULL值(而不是$_POST['code'] == "")到我的数据库中.为什么会这样?
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Run Code Online (Sandbox Code Playgroud)
更新:
虽然禁用仿真对我有用,但我更喜欢使用它,因为像这个问题中的OP一样,基本上我的所有查询只在每次执行脚本时执行一次.因此,准备好语句不会给我带来任何好处,并且会创建对数据库的不必要调用,如下面的常规查询日志中所示:
Emulation Disabled
22 Connect user@localhost on Database
22 Prepare UPDATE Product SET code=? WHERE id=?
22 Execute UPDATE Product SET code='abc' WHERE id='123'
22 Close stmt
22 Quit
Emulation Enabled
22 Connect user@localhost on …Run Code Online (Sandbox Code Playgroud) 我只是想知道是否有一种方法可以在MySQL中使用某种形式的预处理语句,所以我不必转义所有输入,我不必将我的所有文件从MySQL切换到MySQLi.我真的不相信转义函数,所以如果有任何替代方法可以在常规MySQL中运行,那就太棒了.