我试图找出一种避免SQL注入的简单方法,到目前为止,我只能提出两个想法:
这是我目前的代码:
<?php
$hash = $_GET['file'];
if (isset($hash))
{
$db = new SQLite3("Files.db");
if ($db != null)
{
$hash = preg_replace('/[^A-Za-z0-9 _.\-+=]/', '_', $hash);
if ($response = $db->query("SELECT [FILE] FROM '$hash'"))
{
echo $response->fetchArray()[0]; // File name is returned if successful.
}
}
}
?>
我的问题是我是以正确的方式解决这个问题还是有更好的方法来做到这一点?
答案 0 :(得分:5)
让您的数据库库为您完成。 PHP Sqlite3库支持prepared statements:
$stmt = $db->prepare('SELECT bar FROM foo WHERE id=:id');
$stmt->bindValue(':id', 1, SQLITE3_INTEGER);
答案 1 :(得分:1)
防止SQL注入的常见建议是使用准备好的查询并使用参数将动态内容组合到SQL表达式中。
但这仅适用于使用动态内容代替单个标量值,例如数字或带引号的字符串或日期文字。
在您的情况下,您将显示一个PHP变量替换FROM子句中的表名。您无法使用参数进行此用法。实际上,您显示的用法在任何情况下都不起作用,因为您使用单引号引用表名,就好像它是一个字符串文字。我不认为SQLite支持这一点。
为了帮助防止动态表名的SQL注入,最佳做法是使用白名单。也就是说,将输入与已知有效表名列表进行比较,如果用户尝试输入不在该列表中的任何内容,则拒绝它。
<?php
$valid_tables = array('table1', 'table2', 'table3');
$hash = $_GET['file'];
if (array_search($hash, $valid_tables)) {
...do your query...
} else {
...issue an error or else some default behavior...
}
您可以通过硬编码,阅读配置文件来创建$valid_tables
数组,也可以query your SQLite database for all the currently existing tables。