在用户提交的数据中保留未转换的&符号是否存在安全风险?

jer*_*ahs 4 html security string validation escaping

在显示用户生成/提交的信息时,是否存在逃避其他特殊字符但未触及&符号的安全风险?我想让我的用户自由输入html实体,十六进制和十进制特殊字符,而不会给我的清洁剂增加不必要的复杂性.

小智 5

tldr; 如果编码正确,离开&符号(或其他"特殊字符")不是安全问题.也就是说,输出/使用是重要的,而不是输入.

这一切都取决于最终如何使用数据.做<input value="<? echo $input ?>" />不正确编码,任意输入,例如.

现在的&往往是少得多"问题"比其他字符(发言权',",<>),但它可能会导致一些文物(包括错误和不确定的行为),在某些情况下,或者是用于添加一个额外的查询参数一个URL

  • ..但是如果在输出时 URL没有被适当编码,则它没有被正确编码 1
  • ..当然,如果a &逐字写入XML/HTML流,那么它就没有正确编码 2
  • ..如果程序以原始&[从用户输入]传递到"shell字符串执行",那么它[很可能] 没有正确编码 3
  • ..这一切都归结为使用.

我倾向于不改变输入,除了以使其符合业务规则-而这并没有包括以上提到的情况!(但根本不接受&符号,这可能是完全有效的商业规则.)

在适当的时间适当地逃避(或者更好的是,不需要[手动]逃逸的方法)会照顾其余部分,并确保通过良好的使用编码,减轻琐碎的攻击或意外的错误.

事实上,我认为这种"输入清理"表明对其他地方使用的方法/代码缺乏信任,并且可能导致需要撤消 "清理"的更多问题.魔术引用任何人?


1这是&用户输入中的一个实际上可以引起注入形式的情况.想象一下:format("http://site/view={0}", user_input)哪里user_input包含1&buy=1.结果将是"http://site/view=1&buy=1".正确的方法是对URI进行URI编码(也称为Percent编码),这将导致"http://site/view=1%26buy%3D1".(请注意,在正确编码的情况下只有一个查询参数.如果意图是允许"原始"输入通过,则仔细定义/分析允许的规则并查看以下段落.)

2虽然"裸" &可以在HTML流中有效,但用户输入不应该被视为"有效的HTML".也就是说,无论是针对XML还是HTML,都应该使用正确的输出/呈现转义机制.(转义机制可能选择不对"裸"进行编码&,但这是次要问题.懒惰的程序员将继续对所有适用的输出使用相同的转义技术,以获得一致,可靠和安全的输出.)

3使用exec-form接受参数列表,而不是使用shell-execute来获取必须解析的单个参数字符串.后者[通常]防止产生shell和相关的shell-hacks.当然,永远不要让用户手动指定可执行文件..

  • 强调用户输入的+1应该在输出之前进行转义,每次都是这样,就是这样. (2认同)

Gum*_*mbo 5

这完全取决于数据放入的上下文。

在HTML中,&用字符引用表示平原的主要原因是为了避免歧义,因为这&也是这种字符引用的开始。此类歧义的一个流行示例是&将HTML属性简单地作为URL参数的一部分,如下所示:

<a href="/?lang=en&sect=foobar">
Run Code Online (Sandbox Code Playgroud)

此处&没有使用相应的字符引用对它们进行适当的编码,因此解析器将其视为字符引用的开始。并且由于sectHTML中已知实体,代表断面字符 §,因此该属性值实际上被解释为/?lang=en§=foobar

因此,保持&原样不会像HTML中的其他特殊字符那样造成实际威胁,因为它们可以更改数据放入的上下文:

  • 标签定界符,<并且>可以开始或结束标签声明,
  • 属性值定界符"'可以开始或结束属性值声明。

为了安全起见,你应该使用htmlspecialcharsdouble_encode设置参数false,以避免已经存在的字符引用的双编码:

var_dump(htmlspecialchars('<"&amp;\'>', ENT_QUOTES, 'UTF-8', false) === '&lt;&quot;&amp;&#039;&gt;'); // bool(true)
Run Code Online (Sandbox Code Playgroud)

  • @pst这种确切的行为实际上是[HTML 5](http://www.w3.org/TR/html5/tokenization.html#consume-a-character-reference)所指定的:“如果正在引用字符作为属性的一部分使用,并且匹配的最后一个字符不是“`;”(U + 003B)字符,下一个字符是“`=”(U + 003D)字符或范围在ASCII中数字,大写ASCII字母或小写ASCII字母,然后由于历史原因,U + 0026 AMPERSAND字符(`&`)之后匹配的所有字符都必须不使用,并且不返回任何内容。” (2认同)