因此,从URL中抓取变量ID并将其去除以防止任何事情发生。
然后我们有一个IF语句来检查$ ok是否是一个数字,如果是,它现在被引用为$ id,将在下面的SQL查询中使用。
在编码以防止访问时,我应该采取哪些其他预防措施?
$ok=mysql_real_escape_string(htmlspecialchars(stripslashes(trim(strip_tags(strtoupper($_GET['id']))))));
if(is_numeric($ok)){$id=$ok;}
$sql=mysql_query("SELECT * FROM games WHERE ID = '$id'");
<...more code here...>
答案 0 :(得分:9)
防止SQL注入的一种好方法是使用预准备语句: http://php.net/manual/de/mysqli.quickstart.prepared-statements.php
例如:
$mysqli = new mysqli("example.com", "user", "password", "database");
// Note the '?', it's a placeholder
$stmt = $mysqli->prepare("SELECT * FROM games WHERE ID = ?");
// Providing an actual value for the placeholder
$stmt->bind_param("i", $_GET['id']);
$stmt->execute()
这是针对SQL注入的保存,因为语句在没有不安全数据的情况下被发送到数据库,然后在额外的步骤中提供并由DB安全地插入。
答案 1 :(得分:4)
Mysql已被弃用,不再支持/维护。运行mysql_函数很容易受到像SQL注入这样的攻击如果你已经习惯了mysql,那么很容易过渡到mysqli。您也可以使用PDO。
mysqli中的i表示“改进”。它得到了改进,因为它支持几个新的东西:
两个界面: http://php.net/manual/en/mysqli.quickstart.dual-interface.php
1)程序(你可能习惯使用mysql)
$mysqli = mysqli_connect("example.com", "user", "password", "database");
if (mysqli_connect_errno($mysqli)) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
2)面向对象,其中对象具有可调用的方法和属性。
(例如这里......“ new ”mysqli正在创建一个新的mysqli对象。这个特殊的对象有一个可以调用的“connect_errno”方法。)
$mysqli = new mysqli("example.com", "user", "password", "database");
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: " . $mysqli->connect_error;
}
准备好的声明: http://php.net/manual/en/mysqli.quickstart.prepared-statements.php
存储过程: http://php.net/manual/en/mysqli.quickstart.stored-procedures.php
多个语句: http://php.net/manual/en/mysqli.quickstart.multiple-statement.php
以及其他一些改进的功能。
答案 2 :(得分:2)
是。
如果您没有绑定参数,则可以使用SQL注入。
如果使用不受信任的数据构建可执行的SQL代码,则可以使用SQL注入。
使用PDO或mysqli是不够的。您仍然必须使用绑定参数。如果将SELECT * FROM games WHERE ID = '$id'
传递给mysqli或PDO,则可以使用SQL注入,因为您正在从不受信任的数据构建代码。您必须使用占位符并绑定该数据的参数。
答案 3 :(得分:1)
如果您不想在所有使用预准备语句中担心SQL注入。
在PHP中使用mysqli API并准备好语句,您的代码可能类似于以下示例。请注意,我正在使用程序样式。还可以使用面向对象的样式。
<?php
$link = mysqli_connect("localhost", "user", "password", "dbname");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
// taken from your example
$id = trim(strip_tags(strtoupper($_GET['id'])));
if(!is_numeric($id)) {
die('BAD id');
}
/* create a prepared statement */
if ($stmt = mysqli_prepare($link, "SELECT * FROM games WHERE ID =?")) {
/* bind parameters for markers */
mysqli_stmt_bind_param($stmt, "s", $id);
/* execute query */
$result = mysqli_stmt_execute($stmt);
/* bind result variables */
mysqli_stmt_bind_result($stmt, $col1, $col2, ...);
/* fetch values */
while (mysqli_stmt_fetch($stmt)) {
printf("%s %s\n", $col1, $col2, ...);
}
/* close statement */
mysqli_stmt_close($stmt);
}
/* close connection */
mysqli_close($link);
准备语句使示例中的$id
等查询数据与SQL语法分开。因此无法将数据解析为SQL语法。这是首选方式。
如果您想在PHP和MySQL中使用预准备语句,则必须使用mysqli api或PDO_MySQL api。无论如何你应该改为其中一个,因为PHP的'老旧'mysql api已被弃用且不再开发。
答案 4 :(得分:1)
理想答案是您应该使用来自PDO(首选)或mysqli_
*的预准备语句。自PHP 5.5起,mysql_
函数已被弃用。在2013年,您不应该编写这样的代码。
您很可能“陷入”mysql_函数(例如,您可能拥有庞大的遗留代码库,而且从mysql_
更改为mysqli_
或支付的风险或风险太大PDO),那么你就是在正确的轨道上。您不需要使用您在输入上执行的所有功能。实际上,以下内容足以防止SQL注入攻击,因为我使用了mysql_real_escape_string
和引用了SQL字符串中的参数。
$id = mysql_real_escape_string($_GET['id']);
$sql = mysql_query("SELECT * FROM games WHERE ID = '$id'");