5

CVE-2022-1040 Sophos Firewall 服务架构与认证绕过漏洞分析之旅

 1 year ago
source link: https://paper.seebug.org/1925/
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.

作者:且听安全
原文链接:https://mp.weixin.qq.com/s/c0X8Ct2I2SP-H_pioMM12Q

漏洞信息

前端时间 Sophos Firewall 爆出了一个认证绕过漏洞 CVE-2022-1040 ,最近在深入分析 Sophos 服务架构的同时,完整复现了该漏洞。主要是在 User PortalWebadmin 两个接口存在认证绕过漏洞,漏洞巧妙利用了 Java 和 Perl 处理解析 JSON 数据的差异性,实现了变量覆盖,从而导致认证绕过及命令执行。漏洞适用范围为 Sophos Firewall v18.5 MR3 及以下版本。

环境搭建

首先从官网下载老版本虚拟机。本文研究下载版本为 VI-18.5.2_MR-2.VMW-380

图片

按照提示很容易完成安装。Sophos 的 Web 接口主要通过 Java 实现,由启动命令可以看出 Sophos 使用的是 openjdk 环境,如果在 Java 启动参数中直接添加调试参数,将会出现找不到 libjdwp.so 动态链接库的错误:

图片

图片

可以通过自行上传完整 JDK 来解决这个问题:

图片

重启 Java 服务即可看到监听的端口。

服务架构

Sophos 中的服务架构不是很复杂,主要使用了 Apache 、 Jetty 等 web 服务,第一层语言为 Java 通过网络通信的方式与后端 Perl 服务进行交互:

图片

0x01 Apache 配置

Apache 的启动命令如下:

apache -d /_conf/httpd -DFOREGROUND

进入 /_conf/httpd 目录,存放有 Apache 的配置文件,通过分析 httpd.conf,了解 Apache 引用了 /cfs/web/apache/httpd.conf 配置:

Define userportal_listen_port 65004
Define webconsole_https_port 65003
Define SSLCertificateFileWithPath "/conf/certificate/ApplianceCertificate.pem"
Define SSLCertificateKeyFileWithPath "/conf/certificate/private/ApplianceCertificate.key"
Define https_cert_valid true

从配置中可以看出 Apache 开放了两个主要的端口 userportal 65004webconsole 65003

图片

在 Apache 配置目录下搜索 ProxyPass,找到的代理转发配置如下:

./ssl.conf:53:    ProxyPass /webconsole/images !
./ssl.conf:54:    ProxyPass /webconsole/css !
./ssl.conf:55:    ProxyPass /webconsole/javascript !
./ssl.conf:56:    ProxyPass /webconsole http://localhost:8009/webconsole
./ssl.conf:57:    ProxyPassReverse /webconsole http://localhost:8009/webconsole
./userportal-static.conf:64:    ProxyPass /userportal/images !
./userportal-static.conf:65:    ProxyPass /userportal/CRSSL !
./userportal-static.conf:66:    ProxyPass /userportal http://localhost:8009/userportal
./userportal-static.conf:67:    ProxyPassReverse /userportal http://localhost:8009/userportal

代理转发策略将 webconsoleuserportal 端口分别代理到 8009 端口的不同 URL :

ProxyPass /webconsole http://localhost:8009/webconsole
ProxyPass /userportal http://localhost:8009/userportal

0x02 Jetty 配置

Jetty 配置文件为 /usr/share/jetty/start.ini,开启了本地服务的 8009 端口:

图片

Jetty 的启动参数在 /usr/bin/jetty 脚本中配置,如果要修改可直接修改该文件最后 Java 执行部分。

0x03 CSC 配置

CSC 是 Sophos 的主要服务之一,主要负责启动各个服务进程及提供 API 接口供其他程序服务调用。其启动命令为:

csc -L 3 -w -c /_conf/cscconf.bin

CSC 为标准的 ELF 32bit 可执行程序,可通过逆向分析其中功能。cscconf.bin 中在 CSC 程序中有调用解压,猜测是一个加密压缩包。

/usr/bin/csc 由 C 语言编写,负责启动加载其他的服务以及加载 Perl 代码,在虚拟机中 CSC 启动部分服务如下:

图片

程序中的 extract_conf 函数负责解密 cscconf.bin 并提取压缩包中的内容:

图片

decrypt_bin 函数主要是通过异或算法将 cscconf.bin 数据解密为 cscconf.tar.gz 压缩包格式:

图片

每次取 0x420 个字节通过 xor_decrypt 函数进行加密块解异或解密,将解密后数据中的 0x400 个字节写入 tar.gz 文件:

图片

xor_decrypt 核心代码如下,主要通过与 0x80DCB40 地址中实现存放的 64 字节逐一进行异或处理:

图片

通过逆向该算法,使用 Python 编写出加解密算法实现代码。解密得到 cscconf.tar.gz 压缩包,解开压缩包目录如下:

图片

在压缩包中的其中一个目录名为 service ,推测 CSC 通过该目录下的配置文件启动相关服务:

图片

补丁对比

配置 Sophos vmware 网卡连网后等待一段时间,将虚拟机上的文件与原来的文件进行对比,其中有两个修改的地方,一处为 web.xml,另一处添加了 RequestCheckFilter.class 文件:

图片

web.xml 增加了一段配置,主要给 Sophos Java 代码添加 RequestCheckFilter过滤器,过滤器主要检测 request 请求包中的 JSON 参数是否包含不可见字符:

图片

检测规则中,JSON 参数的每个字符都必须是 32~127 之间,如果超出范围则会跳转到登录界面:

图片

那么给我们的启发就是此次漏洞和 JSON 参数中的不可见字符有着直接的关系,应该是字符编码导致的认证绕过。

JSON 解析差异性分析

漏洞原理可简单理解为 Java 在使用 unicode \u0000 时,JSON 认为 key 是两个不同的 key 并没有 0 字节截断,当 Java 把含有 unicode 编码的 key 发送给后端的 Perl处理时 \u0000 产生了截断效果,使得带有 unicode 编码的 key 变为了 mode, Perl 可以处理重复 key 的 JSON,如果重复则后面覆盖前面的值:

图片

我们可以通过一个示例来对比不同语言处理 JSON 重复键的差异性。Java 处理带有 unicode 编码的 key 时可以正常解析:

import org.json.JSONObject;
import org.json.JSONException;
import java.io.*;
class test {
    public static void main(String[] args) {
        try{
          System.out.println(new JSONObject("{ \"name\": \"test\", \"name\\u0000ef\": \"test2\"}"));
        }catch (JSONException e){
          System.out.println(e);
        }
    }
}
图片

Perl 处理 Java 传递过来的零字节字符串就会产生截断效果,在处理相同 key 值的 JSON 时会取最后一个 key 对应的 value

#!/usr/bin/perl
use JSON;

my %rec_hash = ('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, 'a' => 6);
my $json = encode_json \%rec_hash;
print "$json\n";

其结果为 a 被覆盖为了最后一个 a 的值:

图片

不同语言对 JSON 解析的差异性是此次认证绕过漏洞的核心原理。Java 接收来自用户的以下数据(其中 \u0000 后面的 ef 是为了让 JSON中 key 的 hash 排序将 716 排到 151 的后面):

{"mode":151,"mode\u0000ef":716}

登录认证分析

通过登录 webadmin 获取登录数据包:

图片

根据 /webconsole/Controllermode=151 寻找 Java 代码中的处理逻辑,首先分析 web.xml 中路由对应的 Servlet :

图片
图片

主要由 CyberoamCommonServlet 进行处理,该类主要解析 mode 值,并通过 mode 进行分发:

图片

进入 _doPost 函数继续进行分发, EventBean 从数据库中获取 mode 对应的属性,其中就包括关键属性 Requesttype

图片

通过 Requesttype 将请求分为了三种:

图片
  • Requesttype1 ,使用 CyberoamAjaxHelper 处理;
  • Requesttype2 ,使用 CyberoamCustomHelper 处理;
  • Requesttype 为其他值时,使用 generateAndSendOpcode 处理。

进入 CyberoamCustomHelper 之后,通过匹配 mode 值进行分发,将会进入 WebAdminAuth 类中进行处理:

图片

process 函数对请求中的 JSON 字段进行解析,获取 jsonObject 之后将会给 cscClient 通过 localhost:299 发送给 CSC 进程进行处理:

图片

比较有意思的是 Sophos 通过 cscClient 返回的 Status code 判断是否登录成功,因此在 Java 代码中是看不到登录认证的完整过程的,如下图所示如果返回为 200 则会生成合法 sessionBean

图片

合法 sessionBean 生成过程如下,将 session 中填充 usernameuseridcsrftoken 等关键信息:

图片

因此我们只需要找到后台返回 200 的函数即可。

CSC Perl API 分析

因为 webadmin login mode 151 的 Requesttype2 ,在 _send 函数最后获取返回值的时候使用 getStatusFromResponse 进行解析:

图片

使用 eventBean 判断 Requesttype ,因为该 eventBean 在数据包刚开始处理的时候就根据 mode 值在数据库中进行搜索匹配,中间没有修改的可能性。在如下 else 分支中需要获取 JSON 结果的 status 字段:

图片

因此在寻找可返回 200mode 值时需要考虑的是要能够同时返回 status 字段,通过搜索数据库找到所有 Requesttype2OPCODE ,其中有 716 符合条件。注意 Perl 代码获取了 request 中的 accessaction 字段,并且需要该字段为 1 才能返回 200

漏洞复现

通过前面的分析,我们很容易构造特殊的 JSON 数据包实现认证绕过。如果数据包中返回 status 的为 200 ,并且 redirectionURL 路由为 index.jsp 即为认证成功,直接取 Set-Cookie 中的 JSESSIONID 进行使用:

图片

在未登录条件下在浏览器中添加上述认证后返回的 session,操作如下:

图片

替换浏览器中的 JSESSIONID ,并在 url 处输入 index.jsp 回车进行跳转:

图片

小结

通过漏洞还能够获取 admin 操作权限,因此可以向固件中添加恶意代码,然后通过上传固件的方式实现命令执行,或者通过修改配置等方式进入底层,方法有很多种不再详细分析。

通过分析复现 CVE-2022-1040 认证绕过漏洞,学习了一种新的认证绕过思路,通过不同语言对 JSON 或者其他格式的数据处理上的差异实现变量覆盖,完成漏洞利用。


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1925/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK