这个PHP代码SQL容易受到攻击吗?

时间:2013-01-09 21:58:51

标签: php mysql sql

因此,从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...>

5 个答案:

答案 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'");