XSS attack still works despite htmlspecialchars() doing its work

yvg*_*dwo 2 php security xss

hi i am trying to filter outputs of users who will put free text and wanna prevent XSS attacks so i tried this function i made to check

<?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\0script: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 } ?>
Run Code Online (Sandbox Code Playgroud)

i used htmlspecialchars(htmlspecialchars($pattern)) to encode any < or > but it does not seem to prevent the attacks

and iframe without allow-script always runs the script as soon as it opens

i was wondering how to sanitize the input completely to prevent this attack completey

i only expect urls and when second link is clicked it runs a script too

Pou*_*abi 5

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

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


  1. 用户输入放置在 HTML 中:
<p><?php echo $user_entered_variable; ?></p>
Run Code Online (Sandbox Code Playgroud)

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

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

解决方案:

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

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

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

解决方案:

    <img title='<?php echo htmlspecialchars($user_entered_variable,ENT_QUOTES);?>'/>
Run Code Online (Sandbox Code Playgroud)
  1. 用户输入放置在 URL 属性内: src, href, formaction,...
    <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>

Run Code Online (Sandbox Code Playgroud)

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

htmlspecialchars 文档

PHP文档

此函数不会阻止这些向量,因为它们没有任何 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>

Run Code Online (Sandbox Code Playgroud)
  1. 用户输入放置在 JavaScript 标签内,不带任何引号
<script>
  var inputNumber = <?php echo $user_entered_variable; ?>
</script>
Run Code Online (Sandbox Code Playgroud)

攻击向量: 1;alert(1)

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

解决方案:

<script>
  var inputNumber = <?php echo intval($user_entered_variable); ?>
</script>
Run Code Online (Sandbox Code Playgroud)

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