strip_tags()容易受到脚本攻击吗?
是否有一个已知的XSS或其他攻击,使其通过一个
$content = "some HTML code"; $content = strip_tags($content); echo $content;
?
手册有一个警告:
此function不会修改您允许使用allowable_tags的标签上的任何属性,包括恶作剧的用户在发布将显示给其他用户的文本时可能会滥用的样式和onmouseover属性。
但是这与仅使用allowable_tags
参数有关。
没有设置允许的标签 , strip_tags()
容易受到攻击?
Chris Shiflett似乎说这是安全的:
使用成熟的解决scheme
如果可能,请使用成熟的现有解决scheme,而不是尝试创build自己的解决scheme 像strip_tags()和htmlentities()这样的函数是很好的select。
它是否正确? 请尽可能引用来源。
我知道关于HTML净化器,htmlspecialchars()等 – 我不是在寻求最好的方法来消毒HTML。 我只想知道这个具体问题。 这是一个理论上的问题。
参考: PHP源代码中的strip_tags()
实现
顾名思义, strip_tags
应该删除所有的HTML标签。 我们唯一可以certificate的方法是通过分析源代码。 下一个分析适用于strip_tags('...')
调用,白名单标签没有第二个参数。
首先,关于HTML标签的一些理论:一个标签以<
后跟非空白字符开头。 如果这个string以一个?
,它不应该被parsing 。 如果这个string以!--
开头,则它被认为是一个注释,下面的文本不应该被parsing。 注释以-->
结束,在这样的注释中,允许像<
和>
这样的字符。 属性可以出现在标签中,它们的值可以有select地被一个引号字符( '
或"
)包围。如果这样的引用存在,它必须被closures,否则如果遇到>
,标签是不会closures的。
代码<a href="example>xxx</a><a href="second">text</a>
在Firefox中被解释为:
<a href="http://example.com%3Exxx%3C/a%3E%3Ca%20href=" second"="">text</a>
在ext / standard / string.c的第4036行中引用了PHP函数strip_tags
。 该函数调用内部函数php_strip_tags_ex 。
存在两个缓冲区,一个用于输出,另一个用于“内部HTML标签”。 名为depth
的计数器保存打开的尖括号( <
)的数量。
variablesin_q
包含引号字符( '
或"
),否则为0
,最后一个字符保存在variableslc
。
这个函数有五个状态,上面的描述中提到了三个函数。 根据这些信息和函数体,可以得出以下状态:
- 状态0是输出状态(不在任何标签中)
- 状态1意味着我们在一个正常的html标签内(标签缓冲区包含
<
) - 状态2意味着我们在一个php标签内
- 状态3:我们来自输出状态,遇到
<
和!
字符(标签缓冲区包含<!
) - 状态4:在HTML注释中
我们只需要小心,不能插入标签。 也就是, <
后跟一个非空白字符。 第4326行用<
字符检查一个案例,如下所述:
- 如果在引号内(例如
<a href="inside quotes">
),<
字符将被忽略(从输出中删除)。 - 如果下一个字符是空格字符,则
<
被添加到输出缓冲区 。 - 如果在HTML标签之外,则状态变为
1
(“在HTML标签内部”),并且最后的字符lc
被设置为<
- 否则,如果在HTML标签内,名为
depth
的计数器会增加,并忽略该字符。
如果在标签打开state == 1
( state == 1
)时满足>
,则in_q
变为0
(“不在引用中”)并且state
变为0
(“不在标签中”)。 标签缓冲区被丢弃。
属性检查(对于像'
和'
这样'
字符)是在被丢弃的标签缓冲区上完成的,所以结论是:
没有标签白名单的strip_tags对于包含在标签之外是安全的,没有标签将被允许。
通过“外部标签”,我的意思不是像<a href="in tag">outside tag</a>
。 尽pipe文本可能包含<
和>
,如>< a>>
。 结果是无效的HTML虽然, <
, >
和&
仍然需要转义,尤其是&
。 这可以用htmlspecialchars()
。
没有白名单参数的strip_tags
的描述是:
确保返回的string中不存在HTML标记。
我无法预测未来的漏洞,特别是因为我没有看过PHP的源代码。 然而,由于浏览器接受看起来无效的标签(如<s\0cript>
),过去也有过漏洞。 所以有可能在将来有人可能会利用奇怪的浏览器行为。
除此之外,将输出直接发送到浏览器作为一个完整的HTML块永远不应该是不安全的:
echo '<div>'.strip_tags($foo).'</div>'
但是,这是不安全的:
echo '<input value="'.strip_tags($foo).'" />';
因为可以通过"
轻松结束引用"
并插入脚本处理程序。
我认为总是把stream浪<
转化<
(和引号相同)。
Strip标签是完全安全的 – 如果你正在做的只是将文本输出到html正文。
将它放入mysql或url属性中并不一定安全。
根据这个在线工具 ,这个string将会“完美地”逃脱,但结果是另一个恶意的!
<<a>script>alert('ciao');<</a>/script>
在string中,“真实”标签是<a>
和</a>
,因为<
和script>
本身不是标签。
我希望我错了,或者只是因为旧版本的PHP,但最好检查一下你的环境。