4

我读过这个:

将帮助您不反对注射。因为转义只是一种字符串格式化工具,绝不是注入防止器。去搞清楚。但是,转义与准备好的语句有一些共同点:如果您仅针对臭名昭著的“用户输入”使用转义,它们都不能保证您不会被注入,而不是作为构建任何查询的严格规则,尽管有数据源。如果您需要插入的不是数据,而是标识符或关键字。

在以下帖子中:使用 sql 转义的动态 mysql 查询是否与准备好的语句一样安全?

所以我的问题是使用:

$Var = "UserInput Data Possible SQL Injection";
$mysqli->real_escape_string($Var);

不提供针对 SQL 注入的保护?

我想使用$mysqli->query();所以我可以使用因为坦率地说,我不知道如何在使用语句fetch_array(MYSQLI_ASSOC);后将结果作为数组获取。prepared

所以如果我的数据库连接中有这个:

$STD = new mysqli('localhost', 'root', 'xx', 'xx');
$STD->set_charset('utf8');

if ($STD->connect_error) {
    die("Standard Access Has Been Revoked. Please Contact Administration"); 
}elseif (!$STD){
die ("Other problem With Connecting To Database, Please Contact Administration");
}

如手册中所述real_escape_string

http://php.net/manual/en/mysqli.real-escape-string.php

以上列举:

注意 安全性:默认字符集 字符集必须在服务器级别设置,或者使用 API 函数 mysqli_set_charset() 设置,以影响 mysqli_real_escape_string()。有关更多信息,请参阅字符集的概念部分。

链接到: http: //php.net/manual/en/mysqli.set-charset.php


我的整体问题可以分为三个选项,第一个是要求语句的fetch_array()等价物prepared,这将提供完整的 SQL 注入预防,因为准备好的语句将数据作为原始数据发送。


这种格式的第一个问题如下:

我正在使用查询作为:

$GetCompletedQuery = $STD->query("SELECT Status FROM UserCompletion WHERE `UserID`=' ". $STD->real_escape_string($_SESSION['UID']) ."'");
$GetCompletedArray = $GetCompletedQuery->fetch_array(MYSQLI_ASSOC);

返回:

数组([状态] => 1)

但是使用准备好的语句:

$GetCompletedQuery = $STD->prepare("SELECT Status FROM UserCompletion WHERE `UserID`=?");
$GetCompletedQuery->bind_param('i', $_SESSION['UID']);
$GetCompletedQuery->execute();

$GetCompletedArray = $GetCompletedQuery->fetch_row;

print_r($GetCompletedArray);

返回:

致命错误:在第 17 行的 /var/www/New/API/Constants.php 中的非对象上调用成员函数 fetch_row()

当我尝试fetch_array()我知道不能与准备好的语句一起使用时,也会出现同样的情况。

那么使用准备好的语句有什么选择呢?


第二个问题

如果我使用 My Usual Query 作为:

$GetCompletedQuery = $STD->query("SELECT Status FROM UserCompletion WHERE `UserID`=' ". $STD->real_escape_string($_SESSION['UID']) ."'");

使我能够使用fetch_array(); 的数据是从 SQL 注入中正确保护的吗?


第三个问题:

我是否应该为 a 逃避/保护 SQL 注入,$_SESSION['UID'];因为这是在以下庄园中分配的:

$InnerJoinQuery = $STD->query("
        SELECT Users.ID, Users.Username, Users.Password, UserInformation.LastName, UserInformation.Firstname, UserInformation.DOB
        FROM Users
        INNER JOIN UserInformation
        ON Users.ID = UserInformation.UserID WHERE Users.Username = '".$_SESSION['real_name']."'");
        $InnerJoinArray = $InnerJoinQuery->fetch_array(MYSQLI_ASSOC);

    $_SESSION['UID'] = $InnerJoinArray['ID'];
    $_SESSION['Password'] = $InnerJoinArray['Password'];
    $_SESSION['Firstname'] = $InnerJoinArray['Firstname'];
    $_SESSION['LastName'] = $InnerJoinArray['LastName'];
    $_SESSION['DOB'] = $InnerJoinArray['DOB'];

这个片段解释了:

用户使用用户名和密码登录,文件从数据库中获取信息,$_SESSION['real_name']; 并将结果添加到 $_SESSION 数组中,将每个结果添加到不同的键中。

$_SESSION['UID'];这个块的问题是,当通过数据库分配时,我是否应该逃避/保护 SQL 注入$_SESSION['real_name'];

感谢您抽出宝贵时间阅读这一庞大的内容。

4

1 回答 1

6
  1. http://php.net/manual/en/mysqli-stmt.get-result.php
  2. 是的,但这是非常糟糕的做法:
    • 在这种情况下它会帮助你,但只有在这种情况下才会欺骗你
    • 手动转义很傻,最好让司机帮你做
  3. 是的,因为没有像 SQL 注入这样的东西,只是格式不正确

是否使用$mysqli->real_escape_string($Var);不提供针对 SQL 注入的保护?

我没有改变主意:当然,它没有。
仅当您将结果值括在引号中(并使用mysqli_set_charset()严格设置正确的编码)时才会这样做。

看,SQL 注入不是必需的,它本身就存在,但它只是一个结果。格式不正确的查询的结果。
创建查询时,您必须正确格式化查询的每个部分。不是因为任何“注射”,而是为了它。当你要在查询中插入一个字符串时,你必须把它放在引号中,否则你会得到一个语法错误。当你要在查询中插入一个字符串时,你必须转义这些用来分隔这个字符串的引号,否则你会得到一个语法错误。等等。你应该关心的是正确的格式,而不是关于注射的可怕故事。只要您根据其类型正确格式化每个动态查询部分 - 就不可能进行注入

所以,变量的来源或它的价值永远不应该是你关心的问题。但只有它位于查询中:

  • 字符串必须用引号括起来并转义这些引号。
  • 数字必须转换为它的类型。
  • 标识符必须包含在反引号中,并将这些反引号加倍

当它用于查询的静态部分时,在脚本中硬编码,我们不使用如此严格的标准 - 例如,我们没有将每个标识符都包含在反引号中。
但是当它用于查询的动态部分时,应用格式化规则应该是严格的规则,因为我们无法确定变量内容。

By the way, there is another way to format your strings and numbers - prepared statements. It is not as convenient as it should be, but because it is using placeholders to represent your data in the query, it it recommended to use over silly manual formatting.

于 2013-01-14T04:20:07.587 回答