php strip_tags()容易受到脚本攻击吗?

ki1q1bka  于 2023-05-05  发布在  PHP
关注(0)|答案(6)|浏览(164)

是否有已知的XSS或其他攻击使其通过

$content = "some HTML code";
$content = strip_tags($content);

echo $content;


manual有一个警告:
此函数不会修改您允许使用allowable_tags的标签上的任何属性,包括style和onmouseover属性,恶作剧的用户在发布将显示给其他用户的文本时可能会滥用这些属性。
但这与仅使用allowable_tags参数有关。

未设置允许的标签strip_tags()是否容易受到攻击?

Chris Shiflett似乎说它是安全的:
使用成熟的解决方案
如果可能,使用成熟的现有解决方案,而不是尝试创建自己的解决方案。strip_tags()和htmlentities()等函数是不错的选择。
对吗?如果可能的话,请引用来源。
我知道HTML净化器,htmlspecialchars()等-我不是在寻找净化HTML的最佳方法。我只想知道这个具体问题。这是一个出现在here上的理论问题。
参考:PHP源代码中的strip_tags()实现

csbfibhn

csbfibhn1#

正如它的名字所暗示的,strip_tags应该删除所有HTML标记。我们唯一能证明的方法就是分析源代码。下一个分析应用于strip_tags('...')调用,对于列入白名单的标记没有第二个参数。
首先,一些关于HTML标签的理论:标签以<开头,后跟非空白字符。如果此字符串以?开头,则不应对其进行解析。如果这个字符串以!--开头,它被认为是一个注解,下面的文本也不应该被解析。注解以-->结尾,在这样的注解中,允许使用<>这样的字符。属性可以出现在标签中,它们的值可以选择用引号字符('")括起来。如果存在这样的引用,则必须关闭它,否则如果遇到>,则标记不会关闭。
代码<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>

PHP函数strip_tags在ext/standard/string.c的第4036行引用。该函数调用内部函数php_strip_tags_ex。
存在两个缓冲区,一个用于输出,另一个用于“内部HTML标记”。名为depth的计数器保存开放尖括号(<)的数量。
变量in_q包含引号字符('")(如果有),否则包含0。最后一个字符存储在变量lc中。
函数保持五种状态,其中三种在函数的上面的描述中提到。基于该信息和函数体,可以导出以下状态:

  • 状态0是输出状态(不在任何标记中)
  • 状态1意味着我们在一个普通的html标签中(标签缓冲区包含<
  • 状态2意味着我们在一个php标记中
  • 状态3:我们来自输出状态,遇到了<!字符(标记缓冲区包含<!
  • 状态4:HTML注解内部

我们只需要小心,没有标签可以插入。也就是说,<后跟一个非空格字符。第4326行检查带有<字符的情况,如下所述:

  • 如果在引号内(例如<a href="inside quotes">),则<字符被忽略(从输出中删除)。
  • 如果下一个字符是空白字符,则**<被添加到输出缓冲区**。
  • 如果在HTML标记之外,则状态变为1(“在HTML标记之内”),最后一个字符lc设置为<
  • 否则,如果在a HTML标记中,名为depth的计数器将递增,字符将被忽略。

如果在标签打开时满足>state == 1),则in_q变为0(“不在引号中”),state变为0(“不在标签中”)。标签缓冲区被丢弃。
属性检查(对于像'"这样的字符)是在标记缓冲区上完成的,该标记缓冲区将被丢弃。所以结论是:
没有标签白名单的strip_tags可以安全地包含在标签之外,不允许任何标签。
所谓“外部标记”,我的意思是不在<a href="in tag">outside tag</a>中的标记中。文本可以包含<>,如>< a>>。结果不是有效的HTML,<>&仍然需要转义,特别是&。这可以通过htmlspecialchars()来实现。
不带白名单参数的strip_tags的描述为:
确保返回的字符串中不存在HTML标记。

4jb9z9bj

4jb9z9bj2#

我无法预测未来的攻击,特别是因为我还没有查看PHP源代码。然而,过去也有过漏洞利用,因为浏览器接受看似无效的标签(如<s\0cript>)。因此,将来可能有人能够利用奇怪的浏览器行为。
除此之外,将输出作为一个完整的HTML块直接发送到浏览器应该永远不会不安全:

echo '<div>'.strip_tags($foo).'</div>'

但这并不安全:

echo '<input value="'.strip_tags($foo).'" />';

因为可以通过"轻松地结束引用并插入脚本处理程序。
我认为总是将杂散的<转换为&lt;要安全得多(引号也是如此)。

kqhtkvqz

kqhtkvqz3#

根据this online tool,这个字符串将被“完美”转义,但结果是另一个恶意的!

<<a>script>alert('ciao');<</a>/script>

在字符串中,“真实的的”标签是<a></a>,因为<script>本身不是标签。

**我希望我是错的,或者这只是因为PHP的旧版本,但最好检查一下你的环境。

tyg4sfes

tyg4sfes4#

strip_tags()易受脚本攻击,直到(至少)PHP 8。不要用它来防止XSS。你应该使用filter_input()

strip_tags()易受攻击的原因是它不能递归运行。也就是说,在有效标签被剥离之后,它不检查是否将保留有效标签。例如,字符串
<<a>script>alert(XSS);<</a>/script>将成功剥离<a>标签,但无法看到该标签
<script>alert(XSS);</script>
在安全环境中,可以看到here

rdrgkggo

rdrgkggo5#

Strip标签是完全安全的-如果你所做的只是将文本输出到html主体。
把它放进mysql或url属性中不一定安全。

e37o9pze

e37o9pze6#

我刚刚能够通过strip_tags()在href中注入脚本pn PHP 8:
测试使用:

<a href="javascript:alert(1)">Click me!</a>

显然,这需要用户交互,但通过此函数。

相关问题