如果我使用PHP在MySQL数据库上运行查询,如下所示:
$query="SELECT * FROM tablename";
如何防止SQL注入这样的攻击?我听说过一些转义方法,但它们会不会在查询中留下斜杠呢?
你在问题中展示的查询没有使用用户提供的值,因此不存在SQL注入的情况,但在一般情况下:-
首先,在使用查询之前,必须验证所有用户输入(用户名、电子邮件等)。例如:如果您只允许用户名中包含字母数字字符,则必须检查输入是否实际为字母数字字符,然后才能继续形成数据库查询,并且您还必须检查所有输入的大小。
之后,在我看来,预处理语句是防止SQL注入的最佳选择。
mysql_real_escape_string()的问题:
由于mysql_real_escape_string()根据默认字符集转义字符,因此它比addslashes()函数更好,并且正确地净化由于多字节字符集的滥用而引起的SQL注入,但在另一篇文章这里,说明了一种解决方法,即仍然可以进行注入攻击。
解决方案:
因此,防止SQL注入的适当和更好的方式是使用预处理语句。它是一种技术,在插入用户输入(参数)之前预编译SQL语句,并将其视为可重用的SQL模板。因此,它将用户输入与实际SQL代码分离,并且SQL解析器永远不会解析用户输入。
除了安全性外,它还优化了SQL查询的速度。它有助于需要使用不同用户输入多次运行相同查询的情况。
您可以参考PHP手册以获取实现详细信息。
当你像这样制作时,就可以进行SQL注入
$query="SELECT * FROM tablename WHERE Name LIKE '" . $_GET["name"] . "'";
攻击者可以在get参数名称中简单地放置SQL注入 - 例如像 "' OR 1 OR '' = '" 这样的内容
确保每个get或post参数都通过mysql_real_escape_string或至少addslashes + intval进行传递。
$query="SELECT * FROM tablename WHERE Name LIKE '" . mysql_real_escape_string( $_GET["name"] ) . "'";
$query="SELECT * FROM tablename WHERE id = ".$_GET['id']
在这里,有可能会有人更改查询语句。
因此,您可以使用mysql_real_escape_string
正确的方法
$query="SELECT * FROM tablename WHERE id = '".mysql_real_escape_string($_GET['id'])."'";
这样做可以保护用户发送的参数。
但是,您应该始终验证来自用户的每个参数,并在此基础上通过上述常见方式进行安全保护。
首要建议,永远不要选择 * (全部),只选择必需的字段。如果所有字段都是必需的,则单独选择。这样,当其他开发人员继续项目时,他们会更快地了解情况。其次,为了保证查询的安全性,使用 mysql_real_escape_string();
函数。如果传递的是 HTML,请使用htmlentities();
函数。
column1
,column2
,column3
FROM table
WHERE column_name
='' - Grigor我已经使用了这段代码,请看一下它是否正确,现在是否无法注入
据我所知:如果我们运行插入查询,注入代码就可以被注入。请纠正我,我不是很有教育背景的程序员。
$rs=mysql_query("Select * from subcat where CATID='".mysql_real_escape_string($_GET['cat'])."' order by ID ASC");
while($row=mysql_fetch_array($rs))
{
echo '<td align="left" style="text-decoration:none;padding-left:1px; "><a href="detail.php?product='.$row['SUBCAT'].'" style="text-decoration:none;color:#000">'.$row['HEADING'].'</a>';
echo '<td align="CENTER" style="text-decoration:none;padding-left:1px"><a href="detail.php?product='.$row['SUBCAT'].'" style="text-decoration:none;color:#000;">BUY NOW</a>';
echo '<td align="CENTER" style="text-decoration:none;padding-left:50px"><a href="detail.php?product='.$row['SUBCAT'].'" style="text-decoration:none;font-weight:bold;color:#000">Rs.'.$row['PRICE'].'</a>';
echo '<tr><td colspan=5 style="border-bottom:1px #232323 solid;">';
}
mysql_
已经被弃用,应该使用mysqli_
或PDO代替。 - John Dvorak这是一个非常古老的帖子,但为了记录那些被搜索引擎转移的其他人:PDO Prepared Statements 是我的建议。
$connection = new PDO("mysql:host=" . _DBHOST_ . ";dbname=" . _DB_, _DBUSER_, _DBPASS_);
$statement = $connection->prepare("SELECT * FROM tablename WHERE id = :tid");
$statement->execute([':tid' => $_GET['id']]);
$result = $statement->fetch(); // or if you want multiple: $statement->fetchAll()
好的一点是,你可以构建一些包装类和函数来大大简化你的工作。
话虽如此,现今通常一个好的框架(如symfony)已经为你完成了大部分的工作。如果你只需要数据库组件,你也可以通过composer将ORM数据库层整合到你的项目中:https://www.doctrine-project.org/
WHERE
子句时才会发生。 假设您的查询语句是:SELECT * FROM tablename WHERE id='$_POST['id']'
假设我在 id 的表单字段中输入' OR '1'='1
。 现在,您的SQL查询将变为:SELECT * FROM tablename WHERE id='' OR '1' = '1'
这将始终返回所有字段。 - Pranav Hosangadi