为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&baz=2" />
<script>
// ...
window.location = document.getElementById('foo').value;
// ...
</script>
在这种情况下,foo
是一个C程序,它不理解URL和段错误中的编码字符。
我可以简单地抓取JavaScript中的值并执行类似value.replace('&', '&')
的操作,但这看起来很糟糕,只适用于&符号。
所以,我的问题是:是否有更好的方法来对注入HTML属性的数据进行编码或解码?
我已经阅读了OWASP's XSS Prevention Cheatsheet的所有内容,只要我小心引用我的属性,我就会发出声音,然后我需要编码的唯一字符是引号本身("
) - 在这种情况下,我可以使用类似str_replace('"', '"', ...)
的东西 - 但是,我不确定我是否正确理解它。
答案 0 :(得分:11)
您当前使用htmlentities()
或htmlspecialchars()
的方法是正确的做法。
您提供的示例是正确的HTML:
<input id="foo" type="hidden" value="foo?bar=1&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&baz=2" />
这是正确的,浏览器会将foo?bar=1&baz=2
(解码&
)发送到服务器。如果服务器没有看到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&baz=2'
到此:
decodeHTMLSpecialChars('http://someurl.com/foo?bar=1&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)