处理 /appsuite/api/oxodocumentfilter&action=addfile 时应用的 URL 验证逻辑存在三个缺陷,可被利用来执行检查时使用时(ToCToU)SSRF 攻击。该问题允许恶意行为者对内部网络服务执行 HTTP GET 请求,并可能导致受保护信息泄露。
URITools.getFinalURL 方法中的 URL 验证逻辑(实现见此处)存在 ToCToU 漏洞。
URL u = new URL(url);
if (validator.isPresent()) {
Optional<OXException> exception = validator.get().apply(u);
if (exception.isPresent()) {
throw exception.get();
}
}
URLConnection urlConnnection = u.openConnection();
在上述代码中,输入 URL 主机名的 DNS 解析在检查时(validator.get().apply(u))和使用时(u.openConnection())都会通过调用 InetAddress.getByName 方法进行。因此,如果攻击者能在检查之后、使用之前改变 DNS 解析结果,就可以绕过验证器。单独利用此缺陷极其困难,原因如下:
InetAddress.getByName 会缓存 DNS 解析结果 30 秒;如果 DNS 解析失败,则缓存 10 秒。validator.get().apply(u) 与 u.openConnection() 之间的时间间隔极小(对于正常 URL 小于 1 毫秒)。缺陷 #2 用于绕过此限制。URL 验证器 AddFileAction.validator(实现见此处)不验证输入 URL 的长度。通过提供大尺寸 URL,攻击者可以延长检查时和使用时调用 InetAddress.getByName 方法之间的时间间隔。更大的时间间隔使攻击者更容易利用缺陷 #1。
HostList.contains 方法(实现见此处)在输入 URL 主机名的 DNS 解析失败时返回 false。
// Need to resolve as last resort
try {
return contains(InetAddress.getByName(toCheck), false);
} catch (UnknownHostException e) {
// Cannot be resolved
return false;
}
AddFileAction.validator 调用 blackImageUrlHostlist.contains 方法检查输入 URL 主机名或其解析到的 IP 地址是否在黑名单中。如果攻击者使主机名的 DNS 解析失败,则会跳过 IP 地址检查并接受该 URL。
考虑一个主机名 randomid.dns.pointer.pw,其权威名称服务器由攻击者控制。攻击策略是使 randomid.dns.pointer.pw 的 DNS 解析在检查时(validator.get().apply(u);)失败,并在使用时(u.openConnection())成功。这使攻击者能够绕过 IP 地址黑名单过滤器,对任何被列入黑名单的 IP 地址执行 HTTP GET 请求。攻击者可按照以下步骤实施此攻击:
{"add_imageurl": "http://randomid.dns.pointer.pw"} 的 addfile 操作,触发服务器上的 InetAddress.getByName 缓存。此时,权威 DNS 服务器将被设置为通过返回 SERVFAIL 状态使 randomid.dns.pointer.pw 的 DNS 解析失败。InetAddress.getByName 将缓存此失败结果 10 秒。pointer.pw 域的权威名称服务器针对主机名 randomid.dns.pointer.pw 的 A 类型 DNS 请求返回 127.0.0.1。InetAddress.getByName 在检查时返回缓存的响应(SERVFAIL),并在使用时(url.openConnection())返回 127.0.0.1。add_imageurl 值设置为格式 http://u{25MB}:[email protected]/path/to/internal/resource.png。这里的 u{25MB} 表示用户名部分是长度为 25 x 1024 x 1024 个字符的字符串。从 https://golang.org/dl/ 安装 golang。
按照指南 https://oxpedia.org/wiki/index.php?title=AppSuite:Open-Xchange_Installation_Guide_for_Debian_9.0 和 https://oxpedia.org/wiki/index.php?title=AppSuite:Documents_Installation_Guide#Debian_GNU.2FLinux_9.0_.28valid_from_v7.10.29 在至少 4GB RAM 的虚拟机中安装 Open-Xchange 和 Documents。
下载并解压 poc.zip 文件。
打开终端 / 命令行,并将当前目录设置为解压后的 poc.zip 文件夹。
运行命令
go run . -serverRoot="http://172.16.66.130" -username="testuser" -password="secret" -targetPath="appsuite/v=7.10.3-9.20200409.083030/apps/themes/logo.png" -targetPort="80" -payloadSize=25 -startSleepDuration=6600
其中 172.16.66.130 是虚拟机的 IP 地址。