使用MySQLI正确转义 查询准备好的语句

Dar*_*ill 4 php mysqli

我读过这个:

将帮助您不要注射.因为逃避只是一个字符串格式化设施,而不是任何方式的防喷射.去搞清楚.然而,转义与准备好的语句有一些共同之处:如果你只使用它来反对臭名昭着的"用户输入",它们都不能保证你注入,而不是作为建立任何查询的严格规则,尽管有数据源.如果你需要插入不是数据而是标识符或关键字.

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

所以我的问题是使用:

$Var = "UserInput Data Possible SQL Injection";
$mysqli->real_escape_string($Var);
Run Code Online (Sandbox Code Playgroud)

不提供针对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");
}
Run Code Online (Sandbox Code Playgroud)

如手册中所述 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()equlivant prepared,这将提供完整的SQL注入预防,因为准备好的语句将数据作为原始数据发送.


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

我使用的查询为:

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

哪个回报:

数组([Status] => 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);
Run Code Online (Sandbox Code Playgroud)

哪个回报:

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

我尝试的时候会出现相同的情况fetch_array(),我知道它不能用于准备好的陈述.

那么使用预准备语句的选项是什么?


第二个问题

如果我使用我的常用查询:

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

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


第三个问题:

我是否应该逃避/保护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'];
Run Code Online (Sandbox Code Playgroud)

这个片段解释说:

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

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

谢谢你花时间阅读这个巨大的块.

You*_*nse 5

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

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

我没有改变主意:当然,事实并非如此.
只有将结果值括在引号中(并使用mysqli_set_charset()严格设置正确的编码)时才会这样做.

看,SQL注入不是必需的东西,它本身就存在,但它仅仅是一种后果.查询格式不正确的后果.
创建查询时,必须正确格式化它的每个部分.不是因为"注射",而是为了它.当您要在查询中插入字符串时,您必须将其放入引号,否则您将收到语法错误.当您要在查询中插入字符串时,您必须转义这些引号用于分隔此字符串,否则您将收到语法错误.等等.适当的格式应该是你关注的问题,而不是关于注射的恐慌.而且只要你按照它的类型正确格式化每个动态查询部分-没有永远注射可能是可能的

因此,变量的来源或它的价值永远不应该是您的关注点.但只有它在查询中的位置:

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

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

顺便说一句,还有另一种格式化字符串和数字的方法 - 准备好的语句.它不是那么方便,但是因为它使用占位符来表示查询中的数据,所以建议使用过于愚蠢的手动格式化.