XSS攻击绕过值属性中的htmlspecialchars()函数

2022-08-30 16:10:26

假设我们有这个表单,用户注入恶意代码的可能部分是下面的

...
<input type=text name=username value=
       <?php echo htmlspecialchars($_POST['username']); ?>>
...

我们不能简单地放一个标签,或者一个javascript:alert();call,因为值将被解释为字符串,并且htmlspecialchars过滤掉了<,>,',“,因此我们不能用引号关闭值。

我们可以使用String.fromCode(.....)来绕过引号,但我仍然无法弹出一个简单的警报框。

有什么想法吗?


答案 1

此外,重要的是要提到,允许人们将HTML或JavaScript注入你的页面(而不是你的数据源)本身并不附带固有的安全风险。已经存在浏览器扩展,允许您修改网页上的DOM和脚本,但由于它只是客户端,因此它们是唯一知道的。

XSS成为问题的地方是当人们a)使用它来绕过客户端验证或输入过滤或b)当人们使用它来操作输入字段时(例如,更改ACL中OPTACT标签的值以授予他们不应该拥有的权限)。防止这些攻击的唯一方法是在服务器端清理和验证输入,而不是在客户端验证之外进行验证。

为了清除输入中的HTML,htmlspecialchars是完全足够的,除非您想要允许某些标签,在这种情况下,您可以使用像HTMLPurifier这样的库。如果您将用户输入放在 HREF、ONCLICK 或任何允许编写脚本的属性中,那么您只是在自找麻烦。

编辑:看看你的代码,看起来你没有引用你的属性!这很愚蠢。如果有人将他们的用户名设置为:

john onclick="alert('hacking your megabits!1')"

然后,您的脚本将解析为:

<input type=text name=username value=john onclick="alert('hacking your megabits!1')">

始终在属性两边使用引号。即使它们不是用户输入的,这也是一个好习惯。

<input type="text" name="username" value="<?php echo htmlspecialchars($_POST['username']); ?>">

答案 2

只有一种方法。你没有传递 htmlspecialchars() 第三个编码参数或正确检查编码,所以:

$source = '<script>alert("xss")</script>';
$source = mb_convert_encoding($source, 'UTF-7');
$source = htmlspecialchars($source); //defaults to ISO-8859-1
header('Content-Type: text/html;charset=UTF-7');
echo '<html><head>' . $source . '</head></html>';

仅当您可以a)将页面设置为输出UTF-7或b)诱使页面这样做(例如,在没有明确字符集的页面上使用iframe)时才有效。解决方案是确保所有输入都是正确的编码,并且在htmlspecialchars()上正确设置了预期的编码。

它是如何工作的?在 UTF-7 中,<>“字符的码位与 UTF-8/ISO/ASCII 不同,因此除非将输出转换为 UTF-8 以确保(请参阅 iconv 扩展),否则不会对其进行转义。


推荐