PHP:HTML属性编码/ JavaScript解码

时间:2012-05-01 20:36:14

标签: php javascript html xss html-entities

为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's XSS Prevention Cheatsheet的所有内容,只要我小心引用我的属性,我就会发出声音,然后我需要编码的唯一字符是引号本身(" ) - 在这种情况下,我可以使用类似str_replace('"', '&quot;', ...)的东西 - 但是,我不确定我是否正确理解它。

5 个答案:

答案 0 :(得分:11)

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

您提供的示例是正确的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也会得到我期望的结果。所以我不确定你为什么得到不同的结果?也许你正在使用不同的浏览器?可能值得指定您正在测试哪一个。或许你错误地对实体进行了双重编码?你能否证实情况并非如此?

答案 1 :(得分: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修改输入字段的值,则脚本必须对其进行双重编码。

顺便说一下,由于用户输入错误,您的程序不应该出现段错误;)

答案 2 :(得分: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转义是标准方法,并且正在为您完成工作。

答案 3 :(得分:0)

你能不能只使用PHPJS中的html_entity_decode函数:

http://phpjs.org/functions/html_entity_decode

除此之外,你可以对数据进行base64编码......

答案 4 :(得分:0)

请注意,使用htmlentities原样无效!

默认情况下,它只对" < > &

进行编码

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

确保使用Flags作为函数,您可以找到用法和示例here