12

我试图保护自己免受 sql 注入并正在使用:

mysql_real_escape_string($string);

发布 HTML 时,它看起来像这样:

<span class="\&quot;className\&quot;">
<p class="\&quot;pClass\&quot;" id="\&quot;pId\&quot;"></p>
</span>

我不确定 real_escape_string 添加了多少其他变体,所以不想只替换一些而错过其他变体......我如何将其“解码”回格式正确的 HTML,例如:

html_entity_decode(stripslashes($string));
4

9 回答 9

13

mysql_real_escape_string()手册页告诉您哪些字符被转义:

mysql_real_escape_string() 调用 MySQL 的库函数 mysql_real_escape_string,该函数在以下字符前添加反斜杠:\x00、\n、\r、\、'、" 和 \x1a。

您可以通过将这些转义字符替换为未转义的形式来成功反转转义。

mysql_real_escape_string()不过,不应该用来清理 HTML……在输出网页数据之前没有理由使用它。它应该只用于您将要放入数据库的数据。您的清理过程应如下所示:

输入

  1. 接受来自表单或 HTTP 请求的用户输入
  2. 使用创建数据库查询mysql_real_escape_string()

输出

  1. 从数据库中取出数据
  2. htmlspecialchars()在打印之前运行任何用户定义的数据

使用不同的数据库驱动程序(例如MySQLiPDO )将允许您使用准备好的语句,这些语句会为您转义大部分输入。但是,如果您不能切换或利用这些,那么一定要使用mysql_real_escape_string()... 只在插入数据之前使用它。

于 2010-04-04T02:23:07.527 回答
12

你把一切都搞砸了。

mysql_real_escape_string 不需要任何解码!

如果你用斜杠取回你的数据,这意味着它已经被转义了两次。而不是去掉多余的斜线,你不应该首先添加它们。

更不用说任何转义都是过时的,你应该

使用准备好的语句

而不是任何转义字符串。

所以,永远不要逃避,永远不要解码。
问题解决了。

于 2010-04-04T02:28:36.057 回答
8

mysql_real_escape_string用于在将用户提供的数据存储到数据库时防止 SQL 注入,但更好的方法是使用PDO的数据绑定(例如)。我总是建议使用它而不是搞乱转义。

话虽如此,关于您之后如何显示它的问题 - 数据存储后,当您检索它时,数据是完整且有效的,无需“转义”。除非您添加了自己的转义序列,否则请不要这样做。

于 2010-04-04T02:30:32.427 回答
1

在 HTML 页面上显示时使用以下函数删除斜杠:

带斜线();

例如。$html=stripslashes($html); 或 $html=stripslashes($row["fieldname"]);

于 2017-11-08T06:16:40.707 回答
0

不知道格式是怎么回事,因为我可以看到它,但你的 html 表单

<span class="\&quot;className\&quot;">
<p class="\&quot;pClass\&quot;" id="\&quot;pId\&quot;"></p>
</span>

应该是简单的;

<span class="className">
<p class="pClass" id="pId"></p>
</span>

当您取回它时,在将其放入数据库之前,您使用 mysql_real_escape_string() 对其进行转义,以确保您不会遭受 sql 注入攻击。

因此,您正在转义准备放置文本的值。

当您将其从数据库中取出(或将其中的任何内容作为 html 显示给用户)时,您会再次将其转义,以便使用 htmlentities() 等来保护您的用户免受 XSS 攻击。

这形成了咒语 FIEO、过滤器输入、逃生输出的 EO 部分,您应该在眼睑内侧纹身。

于 2010-04-04T10:16:52.850 回答
0

我想知道为什么这个例程没有附带的解码器例程。它可能被 MySQL 解释为完全一样的方式,就好像它没有被转义一样。当您执行时,您会得到未转义的结果$row=mysql_fetch_array($res, MYSQL_ASSOC)';

于 2013-09-22T01:48:11.287 回答
0

好吧,我尝试了这种老式的方式,到目前为止,我看不出我的方法有什么问题。显然它有点粗糙,但它完成了工作:

function mysql_unreal_escape_string($string) {
    $characters = array('x00', 'n', 'r', '\\', '\'', '"','x1a');
    $o_chars = array("\x00", "\n", "\r", "\\", "'", "\"", "\x1a");
    for ($i = 0; $i < strlen($string); $i++) {
        if (substr($string, $i, 1) == '\\') {
            foreach ($characters as $index => $char) {
                if ($i <= strlen($string) - strlen($char) && substr($string, $i + 1, strlen($char)) == $char) {
                    $string = substr_replace($string, $o_chars[$index], $i, strlen($char) + 1);
                    break;
                }
            }
        }
    }
    return $string;
}

这应该涵盖大多数情况。

于 2016-08-04T14:14:33.733 回答
-1

即使这是一个老问题……我也遇到过和彼得·克雷格一样的问题。事实上,我必须处理旧的 CMS。为了防止 SQL 注入,所有的 $_POST 和 $_GET 值都是“sql-escaped”的。不幸的是,这是在一个中心点完成的,因此您的所有模块都在接收所有 sql 转义的数据!在某些情况下,您想直接显示这些数据,因此您面临一个问题:如何在不从 DB 中获取它的情况下显示 sql 转义字符串?答案是:使用stripcslashes(不是stripslashes!!)

http://php.net/manual/en/function.stripcslashes.php

于 2017-01-30T13:11:29.490 回答
-2

我认为许多其他答案错过了明显的问题......

您在输入的内容上使用 mysql_real_escape_string (如果不使用准备好的语句,您应该这样做)。

您的问题与输出有关。

当前的问题是您正在调用 html_entity_decode。只需使用 stripslashes 即可恢复原始文本。html_entity_decode 是什么弄乱了你的报价等,因为它正在改变它们。您实际上想要输出 html,而不仅仅是纯文本(此时您将使用 html_entities 等)。你正在解码你想要编码的东西。

如果您只想显示文本版本,则可以使用实体。如果您担心标签不好,请使用 striptags 并只允许您想要的标签(例如 b、i 等)。

最后,请记住以正确的顺序进行编码和解码。如果你运行了 mysql_real_escape_String(htmlentities($str)),那么你需要运行 html_entity_decode(stripslashes($str))。操作顺序很重要。

更新:我没有意识到 html_entity_decode 也去掉了斜线。该页面上没有明确记录,我只是从未抓住它。不过,我仍然会自动运行它,因为我希望将呈现的大多数 html 作为实体保留,即使我不这样做,我也更愿意在我的 db 类之外根据具体情况做出决定。这样,我知道斜线消失了。

看来原始海报正在运行 htmlentities(或他的输入程序,就像 tinymce 正在为他做的那样),他想将其转回内容。因此, html_entity_decode($Str) 应该是所需要的。

于 2010-04-04T03:11:06.830 回答