从Web安全的角度攻击桌面应用
在群里惊叹 hackerhack 太强了之余,他给了一个腾讯玄武的 pdf :《ATTACKING DESKTOP APPS FROM WEB SECURITY’S PERSPECTIVE》
这里阅读一下,并且学点东西。总体是学习笔记
作者是腾讯实验室的:Md5salt、HearMen1、T0m4to
想到攻击桌面应用往往是 Pwn 高手、或者利用攻击浏览器
- 了解 web 安全
- 懂一点逆向
- 完全不懂 Pwn
可以像 Pwn2Own 一样弹出一个计算机窗口吗?
| 传统应用 | 混合应用 |
|---|---|
| C++ | node.js nw.js electron |
让 Web 安全持续伟大!
攻击面概览
- 开放的端口
- URI 方案(就是 url 冒号前面的东西)
- App 特性
开放的端口
应用为什么要开放端口?
- Web 服务
- 本地动态站点
- API 调用
- 调试
- 其他
如何访问这些端口?
- 绑定 0.0.0.0 导致任意 IP 访问
- 绑定 localhost
如果这些端口可以接受 http 协议,或者容忍非法命令,那我们就可以利用浏览器去攻击。
基础知识
- 同源策略
- 两个页面拥有相同的协议、主机、端口
同源 与 不同源的区别
| 同源 | 不同源 | |
|---|---|---|
| 发送简单请求 | ✓ | ✓ |
| 发送自定义头请求 | ✓ | ✕ |
| 获得返回 | ✓ | ✕ |
这是浏览器的限制
如何绕过呢?
DNS 重绑定
flowchart LR
title["DNS Rebinding"]
A["Pull Payload<br/>rebind.com<br/>x.x.x.x"]
B["bypass SOP<br/>rebind.com<br/>127.0.0.1"]
C["Attack<br/>rebind.com<br/>127.0.0.1"]
A -->|"DNS Changed"| B
B --> C
style title fill:none,stroke:none,font-size:28px,color:white
style A fill:#807aa7,stroke:none,color:white,rx:15,ry:15
style B fill:#807aa7,stroke:none,color:white,rx:15,ry:15
style C fill:#807aa7,stroke:none,color:white,rx:15,ry:15
这块我推荐包队:https://baozongwi.xyz/p/dns-rebinding-attack/
DNS 重绑定攻击前提:
- 拥有一个域名
- 需要受害者等待 DNS 改变,因为浏览器有缓存
另一种攻击叫做 CSRF
| DNS 重绑定 | CSRF | |
|---|---|---|
| 绕过同源 | ✓ | ✕ |
| 通过 hostname 检测 | ✕ | ✓ |
| 立即生效 | ✕ | ✓ |
DNS 重绑定能绕过同源但是不能过检测和立即生效,CSRF 恰恰相反。那么是不是可以结合一下呢?
例子:一个受欢迎的第三方微信插件
- WeChatPlugin-MacOS
- 防撤回
- 自动回复
- ……
- 13000+ stars / 2000+ forks
- 已停止维护
它会在本地主机上绑定一个固定端口,并且暴露了一些 API,通过这些 API 可以获得所有用户的好友列表。所有聊天记录,向任意好友发送任意消息。
我们可以用 DNS 重绑定攻击这个插件。
- 绑定在 127.0.0.1:52700
- /wechat-plugin/user
- /wechat-plugin/chatlog
- /wechat-plugin/send-message
它们向开发者提交了这个漏洞,增加了主机名检测。
真的修复了吗?https://github.com/TKkk-iOSer/WeChatPlugin-MacOS/commit/3bf0a352ddbd85250eb00c3f4ed21bb7810b77f4
1
2
3
4
5
6
NSString *hostname = request.headers[@"Host"];
NSString *url1 = [NSString stringWithFormat:@"127.0.0.1:%d", port];
NSString *url2 = [NSString stringWithFormat:@"localhost:%d", port];
if(!([hostname isEqualToString:url1] | [hostname isEqualToString:url2])){
return [GCDWebServerResponse responseWithStatusCode:404];
}
仍然会被 CSRF 攻击,可以向已知用户发送消息。
所以仅检查主机名是不行的,检查主机名仅能防范 DNS 重绑定攻击。要防范这类攻击首先务必检查主机名,然后使用不可预测的路径和数据。不要安装第三方插件。
Xdebug 攻击
Xdebug 是 php 调试的扩展
它的工作方式:
- 请求时携带:XDEBUG_SESSION_START 参数,比如
http://127.0.0.1/index.php?XDEBUG_SESSION_START - Xdebug 连接到一个服务器
- 此服务器可以通过 DBGP 命令与 Xdebug 交互
那么 Xdebug 连接哪个服务器呢?Xdebug 会按照回退顺序检查以下内容。
- 第一个是 Xdebug 配置文件中的:xdebug.remote_host
- 还有http 请求里的 X-Forward-For
- 如果没有,Xdebug 会连接 Remote-Addr
如何进行Xdebug 远程攻击?
在 Xdebug 里面配置这三个参数:
- Xdebug.remote_connect_back = 1
- xdebug.remote_enable = 1
- Xdebug.remote_host is None
这种配置在 PHP 开发这种普遍存在。
攻击路径:
- 设置一个恶意服务器等待 Xdebug 连接
- 利用 DNS重绑定攻击发送自定义的 XFF 头,指向恶意服务器
- 恶意服务器发送 payload 到 Xdebug
- 获得反连 shell
所以,你作为 PHP 开发者,并且使用 Xdebug,当你停留在恶意页面几十秒,你就有可能被攻击
Xdebug 如何看待这个漏洞?他们认为是谣言!
对于 Nodejs,java 调试端口或者 JavaRMI 端口,也可能受到影响。
- NodeJS Debugging Port
- http://bluec0re.blogspot.com/2018/03/cve-2018-7160-pwning-nodejs-developers.html
- Java RMI(于 2018 年 4 月修复)
- RMI 支持 http
- java 反序列化攻击
- https://mbechler.github.io/2018/05/21/Java-CVE-2018-2800/
他们都会受到 DNS 重绑定攻击或类似技术
所以,你发现了某个应用开放了端口,可以检查她是绑定在所有接口还是仅本地主机上。通过 DNS 重绑定,回连来攻击它。
flowchart LR
A["open port"]
--> B["bind on<br/>0.0.0.0"]
--> C["attack<br/>remotely"]
A
--> D["bind on<br/>127.0.0.1"]
D
--> E["DNS<br/>Rebinding"]
D
--> F["CSRF"]
%% 样式调整(保持与原图相近的青绿色)
classDef node fill:#807aa7,stroke:#0f766e,color:white,rx:15,ry:15
class A,B,C,D,E,F node
style A fill:#807aa7,stroke:#0f766e,color:white,rx:15,ry:15
URI Schemes
人们可以通过协议来启动应用,比如浏览器输入:vscode://aaa
浏览器会出现弹窗,问你是否打开 VSCode
在 windows 上,它被注册在注册表中
在HKEY_CLASSED_ROOT\vscode项,有个默认项,数据是URL:vscode
Windows 会使用这个 API 调用命令
"C:\Program Files\Microsoft VS Code\Code.exe" --open-url -- "%1"
ShellExecuteW(NULL, L"open",L"code.exe" --open-url -- %1", NULL, NULL, SW_SHOW);Avoid spaces, quotes, or backslashes in your URI"%1"
但这个 API 有个已知漏洞。可以闭合前面的引号,来添加额外命令。
于是就出现了 Electron 那个著名漏洞:CVE-2018-1000006
Chromium 参数注入
- –renderer-cmd-prefix
- –gpu-launcher
- –utility-cmd-prefix
- –ppapi-pligin-launcher
- ……
ShellExecuteW(NULL, L"open", L"chromium.exe --nacl-gdb=cmd.exe", NULL, NULL, SW_SHOW);
所有用 Chromium 的框架都有这个漏洞
比如 NW.js 框架,放了一个演示视频,弹出了计算器,现场都是掌声。
已经修复了。WINNOTE-19941
之后微软发布了一个补丁,KB4497935,URI Scheme 被 url 编码了,无法注入参数
那 URI 方案死了吗?如果挖漏洞,关注一下 app 与框架。
APP 特性
通常有三个途径
- XSS
- 特权 API
- 不当的协议处理
XSS
XSS 的故事从 Markdown 编辑器开始~
许多的 Markdown 编辑器会在预览窗口中渲染 JavaScript 代码。比如 Mou,Macdown,VSCode
如何攻击?
预览页面在文件domain 上渲染
- 可以利用文件 domain 上的 js 漏洞从磁盘上窃取文件
- 窃取凭证,甚至克隆账户在另一台机器登录
如果使用了特权 API,或者浏览器版本过旧,就可以 RCE
例子:MacDown 本地文件读取,他有几千 stars,上千 forks
作者说 16 年提交的,到了 19 年还没修复。
但是攻击难度增加了
许多编辑器增加了 CSP,也就是内容安全策略。来限制 JS 的执行
有些编辑器使用沙盒机制,在隔离环境中运行 js,而且不提供 node.js 模块的访问权限。
现在开始考虑 Markdown 编辑器所使用的库
第一个是经常用于制作图表的 Mermaid
几乎所有Markdown 编辑器都有这个,typora,印象笔记,hackmd ,gitlab 等等,不过已经修复了。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
需要渲染
graph TD
B --> C{<iframe src=javascript:alert`1`>}
graph LR;
A-->B;
click B callback "<iframe src=javascript:alert`1`>"
需要点击
graph LR;
xss-->B;
click xss alert "callback"
click B "javascript:alert`1` "link"
Katex / Mathjax
这两个库用于数学公式排版,在旧版本中均存在点击劫持漏洞。
flowchart.js
是一个做流程图的。也有点击劫持 XSS 漏洞。
后面使用HackMD 作为例子,因为它用了 mermaid
用上面的代码发现不能攻击,因为被 CSP 拦截了。检查站点,发现了一个有趣的引用,HackMD 的 CSP 里面有个 google-analysis.com,这里可以通过谷歌来攻击。就是通过 Google Tag Manager 编辑一个代码,再引入。
hackmd 桌面应用,使用 renderer.js 渲染,并且他处于特权上下文。
如何把网页的 XSS 转换为桌面应用的 RCE 呢
后续补一下这里的 renderer.js 代码吧,反正他会从 web 视图里获取标题,并将它设置为特权上下文插入页面。
1
2
3
4
webview.addEventListener('dom-ready', function () {// set webview title
document.querySelector('#navbar-container .title').innerHTML = webview.getTitle()
document.querySelector('title').innerHTML =webview.getTitle()
})
所以控制标题就能在特权上下文中执行任意 js 代码。
先 location 定位到某个恶意页面,这个页面的<head>标签里嵌入一些 XSS 代码,调用 node 模块 process 和 child_process 执行命令。
有的时候无法执行 js 代码,只能执行 HTML 代码,可以用来钓鱼或者发广告。
特权 APIs
特权 API 的来源一般是 node 模块。一种是自定义应用,代码通常通过 JSBridge 和 wrapper 结合提供客户端应用。这些接口通常有公开文档
例子:一个受欢迎的聊天 app,看样子是钉钉
它内置了浏览器,并提供了自定义 API,如果把页面渲染到 iframe 中,就可以调用这些 API,因为不存在域名限制。而且这些 API 都有完善的开发文档。
在嵌入式浏览器中打开 URL 有两种方式,一种是卡片消息。就是钉钉发url,会被解析。此外还可以使用内部的 URI schemes 来通过特定协议打开嵌入式浏览器。
突然想到小黑盒里有个叫数学爱好者的就挖到了steam 客户端的漏洞,拿到了 6000美金,不会就是这种浏览器的吧。
有两个值得关注 API:
- app.downloadFile
- 用户选择一个位置保存文件
- app.openLocalFile
- 无需确认直接打开文件
所以通过下载 URL 来执行文件。但是失败了,因为下载后没有执行权限。所以想用 Bash /Python 脚本,但是通常被文本编辑器打开。
那咋办?
Jar 包可以执行!
可以让他下载一个 Jar 包,然后用那个 API,直接打开 Jar 包,它会执行 Java 代码。
所以如果你有 Java,你点击了一个黑客发送的卡片消息,一个弹窗问你是否保存文件。保存一个文件通常无害,所以你点击了保存,你被黑了!
果然是钉钉,新版已经修复了,现在是打开文件夹,而不是直接打开文件。
不当的协议处理
在开发桌面应用时需要注意这三种协议。
- http
- 在不可信上下文打开页面
- 浏览器 1day
- JavaScript
- js 让你处于文件域,可以窃取文件
- file / SMB
- 可以启动程序或或者文件协议获取凭证
例子:duilib
广泛用于中国应用,大量 stars
他支持类似 HTML 的文本格式,比如 showhtml=true,a 标签用于超链接,i 是图片,c 是文本颜色
这个例图居然是微信,微信认为这种标签是安全的,它会渲染这些标签,比如<c #FF0000>Red</c>会被微信渲染红色。
可以利用<i> tag 进行NTLM中继攻击。
当标签被渲染时,它会自动发送Windows凭据。代码后补。因为这些tag通常是群组名称,个人名称,所以可以在无需用户交互的情况下完成。
攻击者可以获取凭据,离线暴力破解。将凭据关联到其他服务器,比如Exchange服务器。
例子:Ghidra,卧槽,这玩意也能攻击。
它是Java写的。使用XML描述项目。
所以在项目描述文件中存在访问控制漏洞,也就是XXE
XXE可以窃取文件,发送http请求。但是怎么把XXE变成RCE。
Ghidra从XXE到RCE
Java在遇到基于ntlm的401http响应时候,会发送凭据,不是基础认证。这是NTLM的挑战响应机制,用于http响应。
攻击者可以假设恶意http服务器来响应请求。随后Java会把凭据发送给攻击者。攻击者只需要将凭据反射回同一个机器即可。所以你只要打开了一个恶意项目。并且开启了无障碍服务。你就有可能被黑。
放了一个视频,Ghidra打开一个恶意项目就被黑了。
flowchart LR
A["feature"]
A --> B["XSS"]
A --> C["Privileged<br/>API"]
A --> D["Protocol<br/>Handler"]
D --> E
D --> F
D --> G
%% 节点样式
classDef node fill:#807aa7,stroke:#0f766e,color:white,rx:12,ry:12,padding:10px
class A,B,C,D,E,F,G node
总结。
不得不说学到了很多,跃跃欲试。
