0

所以变量 ID 是从 URL 中获取的并被剥离以防止任何东西通过。

然后我们有一个 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...>
4

5 回答 5

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 注入,因为该语句在没有不安全数据的情况下发送到数据库,然后在额外的步骤中提供这些数据并由数据库安全地插入。

于 2013-01-09T22:06:21.307 回答
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

以及其他几个改进的功能。

于 2013-01-09T22:08:40.480 回答
2

如果您根本不想担心 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 已被弃用并且不再开发。

于 2013-01-09T22:03:49.563 回答
2

是的。

如果您没有绑定参数,那么您对 ​​SQL 注入持开放态度。

如果您正在使用不受信任的数据构建可执行的 SQL 代码,那么您对 ​​SQL 注入持开放态度。

使用 PDO 或 mysqli 是不够的。您仍然必须使用绑定参数。如果您将您的数据传递SELECT * FROM games WHERE ID = '$id'给 mysqli 或 PDO,则您对 SQL 注入持开放态度,因为您正在从不受信任的数据构建代码。您必须为该数据使用占位符和绑定参数。

于 2013-01-09T22:11:33.970 回答
1

理想的答案是您应该使用PDO(首选)或mysqli_*中的准备好的语句。自 PHP 5.5 起,这些mysql_函数已被弃用。在 2013 年,你不应该编写这样的代码。

如果你被 mysql_ 函数“卡住”(例如,你有一个巨大的遗留代码库,并且有太多的费用或风险从mysql_tomysqli_或 PDO 更改),那么你就在正确的轨道上。您不需要使用您在输入上执行的所有功能。事实上,下面的内容足以防止 SQL 注入攻击,因为我在 SQL 字符串中使用mysql_real_escape_string 并引用了参数。

$id = mysql_real_escape_string($_GET['id']);
$sql = mysql_query("SELECT * FROM games WHERE ID = '$id'");
于 2013-01-09T22:20:57.113 回答