XSS和字符集的那些事儿

2014-04-21   出处: WooYun知识库  作/译者:mramydnei


0x00 前言

在文章的开头,我想对上次发布了一个结论及其离谱但还算及时被删除了的 文章(关于跨域字符集继承的那篇)道个歉。也希望没有测试就去转载的那些人,可以把那个文章删除了。防止更多人对跨域字符集产生了错误的理解。不过作为谢罪,我也又重新整理了一篇文章,这也是一直以特别想写的一篇。但是觉得这个题目对我来说还是有点大,所以就一直没有下的去手。不过吹过的牛逼早晚都是要兑现的,早死早超生,所以就硬着头皮去写吧>.<。我也不扯 那些字符集是什么之类的了,让我们通过一个接一个的例子一起进入 XSS 和字符集所创造的世界吧。

0x01 基于 UTF-7 的 XSS


在开始之前,先对 UTF-7 做一个简单的介绍吧。UTF-7 是可以将所有的 unicode 通过 7bit 来表示的一种字符集。早期多数被利用在邮件环境当中,但现在已经从 Unicode 规格中移除。这个字符集为了通过 7bit 来表示所有的文字, 除去数字和一部分的符号,其它的部分将都以 base64 编码为基础的方式呈现。 比如:

1
我了个去!

用 UTF-7 表示,就是:

+ADw-div+AD4- +YhFOhk4qU7v/AQ- +Adw-/div+AD4-

同样的,

1

就会变成:

+ADw-script+AD4- alert(+ACI-xss+ACI-) +ADw-/script+AD4-

从上面的例子当中,不难看我们的代码中并没有出现我们期待的那种形式的” <”,”>”或双引号。但是我们要怎么将这种情况和 XSS 联系起来呢?大致的情 况可以分为 3 类:

(1)我们没有通过Response header或Meta标签来设置字符集

1
2
3
4
5
6
test page
+ADw-script+AD4-alert(1)+ADw-/script+AD4-

一种情况是,IE 的编码设置为自动检测,IE 就会跟据一些 BOM 字符,比如 +ADw-来判断当前页面的编码为 UTF-7(现在已经不适用了)。

另外一种情况就是虽然 IE 没有勾选自动检测字符集的设置,但是我们可以通过制作一个字符集为 UTF-7 的页面,并通过 Iframe 来包含我们的目标页面, 通过字符集继承漏洞来实现字符集的设定。

 

不过遗憾是在,在现在已经没有这种基于 iframe 的跨域字符集继承的漏洞 可利用了。MK 在不久前也指正了某人在 Slide 中这种的错误。

简短的翻译一下,就是说:『如果在你的 Slide 中所说的通过 iframe 来设定字符集是指,继承 top frame 的字符集,那么现在已经不存在这种问题了。因为这种继承的大前提是必须同域。』

(2)我们设置了一个无法识别的字符集

其实在一篇被删除的文章当中(笔者的测试方法有问题,得到结论都是错误的所以自觉提出删除),/fd 同学表示 utf8 也是标准。但它以前可不是标准。但是为什么 utf-8 和 utf8 都变成了标准呢?因为总会有粗心的人犯下这样的错误,比如:

把 UTF-8 写成 UTF8
把 EUC-JP 写成 EUC

 这种设置方法在以前是无法被浏览器所识别的。换句话来说就和没有设置字符集是一样的。具体利用方法可以参考第一种。

(3)输出点在

标签之前,且字符集是由 meta 标签所指定的

大概的场景可以像这样(输出点在 title 内,meta 之前):

1
2
3
4
5
输出

由于上述的 BOM 和基于 iframe 的字符集继承现在都已经不能利用了。所以在情况三下我们可以考虑先插入一个

1

0x02 基于 US-ASCII 的 XSS

其实基于 US-ASCII 的 XSS 和基于 UTF-7 的 XSS 有很多的类似之处。它也同样是通过 7bit 来表示数字和少数符号的字符集。可以用来表示从 0x00 到 0x7F 的 128 种文字。但如果你试图用 Internet Explorer 来打开一个内容是通过 US-ASCII 来记述的文档时,你会发现这个字符集不单是只会解析从 0x00 到 0x7F 的文字。即使是 0x80 到 0xFF 这个范围中无法通过 7bit 来表示的字符,也会通过忽略最上位的bit的方法生成一些和0x00~0x7F等价的字符。

也就是说在这个字符集当中:

双引号 0x22 等价于 0xA2
左尖括号 0x3C 等价于 0xBC
右尖括号 0x3E则等价于0xBE

比如,你把下面的这一段通过保存成 html,编码选 shift_jis(如果是记事本的可以用 ANSI)

1
2
3
4
5
6
7
シ script セ alert(document.charset)シ/script セ

注释:シ和セ在 shift_JIS 当中分别是 0xBC 和 0xBE

然后,再用 Internet Explorer 打开它,那么最终你会看到小窗口弹起来了。

0x03 利用字符集来绕过 htmlspecialchars()函数

在看完前面的两个字符集后,我们会发现这两个字符集的一个共同点,就是 都没有出现”<”,”>”或双引号。这不难让我们联想到 PHP 中 htmlspecialchars()的 绕过。虽然接下来会提到的 iframe 跨域字符集继承漏洞已经不能再利用了,但是在下文中我会提出可以复现这个漏洞的具体环境。

这是在 kotowicz 的博客当中 2010 年提到的一个 XSS hackme challenge 的解决方案。challenge 的主要目的就是绕过 htmlspecialchars()这个函数来实现 XSS。 而且重要的是这个页面并没有通过 response header 或 meta 来设置字符集。

笔者一开始提到可以做出这样的一个 POC:

1
2
3
4
5
6
7
8

大概意思就是在 IE6 那个年代,字符集继承问题横行,我们只需要一个 iframe 就能完成这个挑战(我没有在 playonlinux 里的 IE6 里复现成功,所以可能你需要足够古老的环境来重现这个问题)。笔者提到对于 IE8 来说,我们只能继承同域的字符集(iframe)。但是那个时候有一个小的 BUG 可以用来欺骗浏览器。

大致思路如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
// utf7exploit.html
// redirect.php

声明:本文为本站编辑转载,文章版权归原作者所有。文章内容为作者个人观点,本站只提供转载参考(依行业惯例严格标明出处和作译者),目的在于传递更多专业信息,普惠测试相关从业者,开源分享,推动行业交流和进步。 如涉及作品内容、版权和其它问题,请原作者及时与本站联系(QQ:1017718740),我们将第一时间进行处理。本站拥有对此声明的最终解释权!欢迎大家通过新浪微博(@测试窝)或微信公众号(测试窝)关注我们,与我们的编辑和其他窝友交流。
317° /3175 人阅读/0 条评论 发表评论

登录 后发表评论