Php 直接来自数据库的值是否需要转义?

Php 直接来自数据库的值是否需要转义?,php,mysql,security,sql-injection,Php,Mysql,Security,Sql Injection,我是否需要转义/过滤来自数据库的数据?即使所述数据已经“转义”过一次(在插入数据库的时间点) 例如,假设我允许用户通过具有标题输入和文本区域输入的表单提交博客文章 恶意用户提交博客文章 title: Attackposttitle');DROP TABLE posts;-- 文本区:哈哈哈,你的网站noobzors被核爆了 现在,当它被插入到我的数据库中时,我将使用mysql\u real\u escape\u字符串对其进行转义,但一旦它进入数据库,我将稍后在我的php博客应用程序中使用以下内

我是否需要转义/过滤来自数据库的数据?即使所述数据已经“转义”过一次(在插入数据库的时间点)

例如,假设我允许用户通过具有标题输入和文本区域输入的表单提交博客文章

恶意用户提交博客文章

title: Attackposttitle');DROP TABLE posts;--
文本区:哈哈哈,你的网站noobzors被核爆了

现在,当它被插入到我的数据库中时,我将使用mysql\u real\u escape\u字符串对其进行转义,但一旦它进入数据库,我将稍后在我的php博客应用程序中使用以下内容引用该数据:

sql="SELECT posttitle FROM posts WHERE id=50";
$posttitlearray = mysql_fetch_array(mysql_query($sql));
这就是我关心的问题所在,例如,如果我运行以下查询以获取帖子内容,该怎么办

sql="SELECT postcontent FROM posts WHERE posttitle=$posttitlearray[posttitle]";
理论上,我不是自己吗?即,我是否没有有效地运行查询:

sql="SELECT postcontent FROM posts WHERE posttitle=Attackposttitle');DROP TABLE posts;--";
或者“Attackposttitle”);DROP TABLE posts;--“数据在数据库中之后是否继续转义?”

我是否需要像这样不断地逃避它:

sql="SELECT postcontent FROM posts WHERE posttitle=msql_real_escape_string($posttitlearray[posttitle])";
或者,数据在第一次插入数据库时首先转义后是否安全


谢谢Stack

一旦放入数据库,它就不会继续被转义。你必须再次逃离它

$sql="SELECT postcontent FROM posts WHERE posttitle='".mysql_real_escape_string($posttitlearray[posttitle])."'";

一旦它被放入数据库,它就不会继续被转义。你必须再次逃离它

$sql="SELECT postcontent FROM posts WHERE posttitle='".mysql_real_escape_string($posttitlearray[posttitle])."'";

尝试使用绑定变量。这将消除完全转义数据的需要


唯一的缺点是,您只能将它们与SQL server中的存储过程一起使用,其他数据库中的任何事情都可以使用它们。

尝试使用绑定变量。这将消除完全转义数据的需要


唯一的缺点是,您只能将它们与SQL server中的存储过程一起使用,其他数据库中的存储过程您可以将它们用于任何事情。

每次插入SQL查询之前,都应该对该值进行转义。不是出于神奇的安全原因,但是要确保结果查询的语法是正确的。

逃脱绳子对许多人来说听起来很神奇,就像是抵御某种神秘危险的盾牌,但事实上它并不是什么神奇的东西。这只是启用查询正在处理的特殊字符的方法。

最好的办法就是看看逃跑到底能做什么。假设输入字符串为:

Attackposttitle');DROP TABLE posts;--
逃逸后:

Attackposttitle\');DROP TABLE posts;--
事实上,它只漏掉了一条斜线。这是您需要确保的唯一一件事——当您在查询中插入字符串时,语法将是正确的

insert into posts set title = 'Attackposttitle\');DROP TABLE posts;--'
它不像危险盾牌之类的东西那么神奇,只是为了确保生成的查询具有正确的语法(当然,如果没有,它可以被利用)

查询解析器然后查看\'序列,知道它仍然是变量,而不是其值的结尾。它将删除反斜杠,以下内容将存储在数据库中:

Attackposttitle');DROP TABLE posts;--
与用户输入的值完全相同。这正是您希望数据库中包含的内容

因此,这意味着,如果您从数据库获取该字符串并希望在查询中再次使用它,则需要再次对其进行转义,以确保生成的查询具有正确的语法

但是,在您的示例中,非常重要的一点是
magic\u quotes\u gpc
指令! 此功能自动转义所有用户输入(gpc-\u GET、\u POST和\u COOKIE)这是一个针对不知道sql注入的人的邪恶特性。它是邪恶的,有两个原因。第一个原因是,然后你必须区分第一个和第二个查询的情况——第一个查询你不能逃避,第二个查询你可以逃避。大多数人所做的是要么关闭“功能”(我更喜欢这个解决方案),要么首先取消用户输入,然后在需要时再次退出。unescape代码可能如下所示:

function stripslashes_deep($value)
{
        return is_array($value) ?
               array_map('stripslashes_deep', $value) :
               stripslashes($value);
}

if (get_magic_quotes_gpc()) {
        $_POST = stripslashes_deep($_POST);
        $_GET = stripslashes_deep($_GET);
        $_COOKIE = stripslashes_deep($_COOKIE);
}
这是邪恶的第二个原因,是因为没有什么比“普遍引用”更好的了。 引用时,您总是引用某些特定输出的文本,如:

  • mysql查询的字符串值
  • like
    mysql查询表达式
  • html代码
  • json
  • mysql正则表达式
  • php正则表达式
  • 对于每种情况,都需要不同的引用,因为每种用法都存在于不同的语法上下文中。这也意味着,引用不应该在输入到PHP时进行,而应该在特定的输出时进行!这就是为什么像
    magic\u quotes\u gpc
    这样的功能被破坏的原因(永远不要忘记处理它,或者最好确保它已关闭!!!

    那么,在这些特殊情况下,人们会用什么方法引用?(请随意纠正我,可能有更现代的方法,但这些方法对我有效)

  • mysql\u real\u escape\u字符串($str)
  • mysql\u real\u escape\u字符串(addcslashes($str,“%”)
  • htmlspecialchars($str)
  • json\u encode()
    -仅适用于utf8!我使用iso-8859-2的功能
  • mysql\u real\u escape\u string(addcslashes($str,,^.[]$()*+?{}'))
    -在这种情况下不能使用preg_quote,因为反斜杠将被转义两次
  • preg_quote()

  • 每次插入SQL查询之前都应转义该值。不是出于安全原因,而是为了确保结果查询的语法正确。

    逃脱绳子对许多人来说听起来很神奇,就像是抵御某种神秘危险的盾牌,但事实上它并不是什么神奇的东西。这只是启用查询正在处理的特殊字符的方法。

    最好的办法就是看看逃跑到底能做什么。假设输入字符串为:

    Attackposttitle');DROP TABLE posts;--
    
    逃逸后:

    Attackposttitle\');DROP TABLE posts;--
    
    其实