7

为 HTML 属性上下文编码不受信任的数据的正确方法是什么?例如:

<input type="hidden" value="<?php echo $data; ?>" />

我通常使用htmlentities()htmlspecialchars()这样做:

<input type="hidden" value="<?php echo htmlentities($data); ?>" />

但是,我最近遇到了一个问题,当我需要传递的数据是一个需要传递给 JavaScript 以更改页面位置的 URL 时,这会破坏我的应用程序:

<input id="foo" type="hidden" value="foo?bar=1&amp;baz=2" />
<script>
    // ...
    window.location = document.getElementById('foo').value;
    // ...
</script>

在这种情况下,foo是一个 C 程序,它不理解 URL 中的编码字符和段错误。

我可以简单地在 JavaScript 中获取值并执行类似的操作value.replace('&amp;', '&'),但这看起来很笨拙,并且仅适用于 & 符号。

所以,我的问题是:有没有更好的方法来编码或解码注入 HTML 属性的数据?

我已经阅读了所有OWASP 的 XSS 预防备忘单,在我看来,只要我小心地引用我的属性,那么我需要编码的唯一字符就是引用本身 ( ") - 在这种情况下,我可以使用类似的东西str_replace('"', '&quot;', ...)- 但是,我不确定我是否正确理解它。

4

5 回答 5

11

您当前的使用方法htmlentities()orhtmlspecialchars()是正确的方法。

您提供的示例是正确的 HTML:

<input id="foo" type="hidden" value="foo?bar=1&amp;baz=2" />

value 属性中的 & 确实需要进行 HTML 编码,否则您的 HTML 无效。大多数浏览器都会&在其中正确解析它,但这并不会改变它无效的事实,并且您正确地对其进行编码。

您的问题不在于值的编码,这很好,而在于您使用的 Javascript 代码无法正确解码。

事实上,我对此感到惊讶,因为您的 JS 代码正在访问 DOM,而 DOM 应该返回解码后的值。

我写了一个 JSfiddle 来向自己证明这一点:http: //jsfiddle.net/qRd4Z/

运行它,它会给我一个警报框,其中包含我预期的解码值。将其更改为console.log也给出我期望的结果。所以我不确定为什么你会得到不同的结果?也许您使用的是不同的浏览器?可能值得指定您正在测试哪个。或者您可能错误地对实体进行了双重编码?你能确认不是这样吗?

于 2012-07-10T21:31:07.013 回答
5

为 HTML 属性上下文编码不受信任的数据的正确方法是什么?

如果在属性值周围添加双引号,则 htmlspecialchars() 就足够了。

 <input id="foo" type="hidden" value="foo?bar=1&amp;baz=2" />

这是正确的,浏览器将发送foo?bar=1&baz=2(解码&amp;)到服务器。如果服务器没有看到foo?bar=1&baz=2,则您必须对该值进行了两次编码。

在 javascript 中获取值foo?bar=1&baz=2也应该返回(例如document.getElementById('foo').value必须返回foo?bar=1&baz=2)。

使用浏览器查看页面的源代码并查看输入字段的实际源代码。

如果您使用 Javascript 修改输入字段的值,则脚本必须对其进行双重编码。

顺便说一句,您的程序不应该因为错误的用户输入而出现段错误;)

于 2012-07-10T21:26:52.680 回答
0

您可以使用 DOM 来解码值:

function decodeHTMLSpecialChars(input){
  var div = document.createElement('div');
  div.innerHTML = input;
  return div.childNodes.length === 0 ? "" : div.childNodes[0].nodeValue;
}

这将呈现以下字符串:

'http://someurl.com/foo?bar=1&amp;baz=2'

对此:

decodeHTMLSpecialChars('http://someurl.com/foo?bar=1&amp;baz=2');
// => 'http://someurl.com/foo?bar=1&baz=2

不,对于 HTML 编码和解码,htmlspecialchars和 html 转义是标准方法,并且对您来说做得很好。

于 2012-07-10T21:25:20.783 回答
0

请注意,htmlentities按原样使用没有帮助!

默认情况下它只是编码" < > &

它不会逃脱',这会造成问题!

确保对函数使用标志,您可以在此处找到用法和示例

于 2013-03-24T00:27:49.067 回答
0

你能不能只使用html_entity_decodePHPJS 中的函数:

http://phpjs.org/functions/html_entity_decode

除此之外,您可以使用 base64 对您的数据进行编码...

于 2012-07-11T02:42:52.107 回答