概述#
WatchGuard是一家历史悠久的安全厂商,其产品为全球超过25万家中小型企业提供安全保护,并根据其官网信息,保护超过1000万个终端。WatchGuard设备运行的是Fireware OS操作系统,该系统集成了入侵防御、防病毒、网页过滤、VPN等多种安全功能,可以让设备通过网络间的加密隧道传输机密信息。Fireware OS中的”iked”进程负责处理IKEv2协议的VPN协商流程,是企业网络安全架构中的关键组件,广泛应用于分支机构VPN连接和移动用户VPN接入场景。
下载Firewall OS#
下载链接:https://software.watchguard.com/SoftwareDownloads?familyId=a2R2A000001YGvTUAW ↗
选择Fireware 12.11.3 OVF Template for new installations ↗
导入虚拟机#
双击ova文件,导入虚拟机,关闭虚拟机

磁盘挂载至其他Linux虚拟机#
添加SCSI设备#
添加硬盘,选择SCSI,选择已有虚拟磁盘,选择firewall的vmdk路径,保持现有格式不转换,加载




挂载#
一般来说有8个img,选择第2个,即/dev/**2 挂载
#创建挂载路径
sudo mkdir /mnt/firewall
#查看磁盘
sudo fdisk -l
#挂载
sudo mount /dev/sdb2 /mnt/firewallshell
获取root和shell#
firewall默认禁止root,且不具备shell
#修改passwd
cd /mnt/firewall/etc
#创建个密文
openssl passwd -6 密码
#修改passwd中root的密码,注意!也要删去,否则无法使用root
sudo vim passwd
#保存并退出出
:wq
#看到root使用的ash,但实际系统中并没有任何shell,所以要回到bin目录,创建软连接
cd /mnt/firewall/bin
#查看busybox架构
file busybox-rel
#下载对应架构完整的busybox
sudo wget https://busybox.net/downloads/binaries/1.21.1/busybox-x86_64
#修改权限
sudo chmod 777 busybox-x86_64
#创建软链
sudo ln -s busybox-x86_64 ash
#验证一下软链
sudo ls -al ashshell


破解license#
修改序列号#
#创建目录
sudo mkdir /mnt/firebox
#挂载
sudo mount /dev/sdb5 /mnt/firebox
#修改序列号
sudo vim /mnt/firebox/serial
#添加内容
FVE117F24D585
#保存并退出出
:wqshell生成license#
#进入crack路径
cd ~/crack_firewall
#生成私钥
openssl ecparam -name sect163k1 -genkey -noout -out private_key.pem
#生成公钥
openssl ec -in private_key.pem -pubout -out public_key.pem
#修改pre-license中的version, wg name, licenses , expiration dates
vim aftermarket_lic.txt
#生成license文件
python3 sign_feature_key.py aftermarket_lic.txt private_key.pem
#验证license文件
python3 verify_feature_key.py aftermarket_lic.txt public_key.pem
#替换公钥
sudo cp public_key.pem /mnt/firewall/etc/lickey.pem
#修改info.txt中的product=utm为product=base
sudo sed -i -e "s/Product = utm/Product = base/" /mnt/firewall/info.txtshell


卸载磁盘#
至此全部文件的修改已经完成,保存好licnese,可以退出挂载
#取消挂载
sudo umount /mnt/firewall
#卸载磁盘
sudo umount /mnt/firebox
#删除目录
sudo rm -rf /mnt/firewall
sudo rm -rf /mnt/fireboxshell移除虚拟机SCSI设备#
点击移除
查看IP#
虚拟机启动后登录root查看ip
ifconfigplaintext进入网页配置#
访问https://ip:8080 进入网页配置
#默认账户密码
账户admin
密码readwriteplaintext选择 Locally-Managed 选择 Configure the external interface settings
IP 选择 Static
DNS选择 119.29.29.29和8.8.8.8
剩下的配置自己根据网络情况修改


配置VPN#
进入web ui后,侧边选择vpn->Mobile vpn->IKEv2,按照向导正常配置,配置完成后,再次回到首页,下载证书相关。
PS:证书和配置时的IP息息相关。

调试#
参考获取shell,塞入gdbserver。
firewall调试命令#
#查看ASLR
0x7ffd710e5780
#关闭ASLR
busybox echo 0 > /proc/sys/kernel/randomize_va_space
#查看进程
busybox netstat -aunp | busybox grep 500
#查看内存布局
busybox cat /proc/{pid}/maps
#开启gdbserver
gdbserver :1234 --attach {pid}plaintext主机调试命令#
#创建文件
mkdir iked_debug
cd iked_debug
#拷贝文件
scp -p 4118 -r root@192.168.96.107:/lib ./lib
scp -p 4118 -r root@192.168.96.107:/usr/lib ./lib/lib
scp -p 4118 root@192.168.96.107:/bin/iked .
#调试
gdb iked
gef➤ set sysroot /home/root/ike_debug
gef➤ set solib-search-path /home/root/ike_debug/lib64:/home/root/ike_debug/lib:/home/you/ike_debug:/home/root/ike_debug/lib/lib
gef➤ target remote 192.168.96.107:1234
gef➤ b *0x4225abplaintextIKEv2介绍#
IKEv2 是一种通常在 UDP 端口 500 上运行的协议,主要负责建立虚拟专用网络 (VPN) 隧道。
从宏观层面来说,它负责处理两个对等方之间加密参数、身份验证和密钥交换的安全协商。
协议中未经认证的部分包括两个初始数据包交换:

攻击的Identification代码部分是在IKE_SA_AUTH处理过程中进行的。所以,必须向 WatchGuard IKE 服务发送两个数据包才能到达攻击的代码路径:
- 一个
IKE_SA_INIT数据包 - 一
IKE_SA_AUTH数据包
IKE_SA_INIT#
第一个数据包启动了Diffie-Hellman密钥交换。在这个过程中,客户端会提出它支持的加密变换,发送其公钥,并额外添加一个随机数(nonce)。相当于TLS协议中的握手环节,双方就如何安全通信达成一致。不过,此时并未进行身份验证;客户端和服务器只是交换一些数学运算来建立一个共享密钥。
Internet Security Association and Key Management Protocol
Initiator SPI: aae76f3726073034
Responder SPI: 0000000000000000
Next payload: Security Association (33)
Version: 2.0
Exchange type: IKE_SA_INIT (34)
Flags: 0x08 (Initiator, No higher version, Request)
Message ID: 0x00000000
Length: 548
Payload: Security Association (33)
Payload: Proposal (2) # 1
Payload: Transform (3)
Transform Type: Encryption Algorithm (ENCR) (1)
Transform ID (ENCR): ENCR_AES_CBC (12)
Transform Attribute (t=14,l=2): Key Length: 256
Payload: Transform (3)
Transform Type: Pseudo-random Function (PRF) (2)
Transform ID (PRF): PRF_HMAC_SHA2_256 (5)
Payload: Transform (3)
Transform Type: Integrity Algorithm (INTEG) (3)
Transform ID (INTEG): AUTH_HMAC_SHA2_256_128 (12)
Payload: Transform (3)
Transform Type: Diffie-Hellman Group (D-H) (4)
Transform ID (D-H): 2048 bit MODP group (14)
Payload: Key Exchange (34)
Payload: Nonce (40)
Payload: Notify (41) - NAT_DETECTION_DESTINATION_IP
Payload: Notify (41) - NAT_DETECTION_SOURCE_IP
Payload: Vendor ID (43) : Unknown Vendor ID
Payload: Vendor ID (43) : Unknown Vendor ID
Payload: Vendor ID (43) : Cisco Fragmentation
Payload: Vendor ID (43) : Cisco Fragmentation
Payload: Notify (41) - IKEV2_FRAGMENTATION_SUPPORTED
Payload: Notify (41) - REDIRECT_SUPPORTED
Payload: Notify (41) - SIGNATURE_HASH_ALGORITHMSshell如果服务器接受所提议的变换,它将回复自己的公钥、随机数和选定的变换集,换句话说,双方就加密通信规则达成一致。
IKE_SA_AUTH#
第二个数据包携带加密的有效载荷,该有效载荷使用在“握手”过程中协商的变换进行保护IKE_SA_INIT。该有效载荷使用从 Diffie-Hellman 密钥交换中导出的共享密钥进行加密。
值得注意的是:它可以同时包含身份验证 - 发起程序有效载荷和证书有效载荷,而这正是受攻击的函数被调用的地方。
服务器会尝试进行证书验证,但该验证是在存在漏洞的代码运行之后进行的,这使得存在漏洞的代码路径在身份验证之前即可访问:
Internet Security Association and Key Management Protocol
Initiator SPI: aae76f3726073034
Responder SPI: f1b3cf883e18a45c
Next payload: Encrypted and Authenticated (46)
Version: 2.0
Exchange type: IKE_AUTH (35)
Flags: 0x08 (Initiator, No higher version, Request)
Message ID: 0x00000001
Length: 1616
Payload: Encrypted and Authenticated (46)
Initialization Vector: 57401bf413505f5550173a07d778d68f (16 bytes)
Encrypted Data (1552 bytes) <AES-CBC-256 [RFC3602]>
Decrypted Data (1552 bytes)
Contained Data (1538 bytes)
Payload: Identification - Initiator (35) <---
Payload length: 521
ID type: FQDN (2)
[…] Identification Data:(A*513) <---
Payload: Certificate (37) <---
Payload: Notify (41) - INITIAL_CONTACT
Payload: Notify (41) - HTTP_CERT_LOOKUP_SUPPORTED
Payload: Certificate Request (38)
Payload: Configuration (47)
Payload: Security Association (33)
Payload: Traffic Selector - Initiator (44) # 1
Payload: Traffic Selector - Responder (45) # 1
Payload: Vendor ID (43) : RFC 3706 DPD (Dead Peer Detection)
Payload: Notify (41) - MOBIKE_SUPPORTED
Payload: Notify (41) - MULTIPLE_AUTH_SUPPORTED
Padding (13 bytes)
Pad Length: 13
Integrity Checksum Data: 3e2683f32beaaddeb8f3f0d43f7b0b2b (16 bytes) <HMAC_SHA2_256_128 [RFC4868]>[correct]shell指纹识别#
在深入研究 IKEv2 协议,观察客户端和 WatchGuard VPN 服务之间数据包的传输时,服务器响应中有一个 base64 字符串。
00000000: bfc2 2e98 56ba 9936 11c1 1e48 a6d2 0807 ....V..6...H....
00000010: a95b edb3 9302 6a49 e60f ac32 7bb9 601b .[....jI...2{.`.
00000020: 566b 3439 4d54 4975 4d54 4575 4d79 4243 Vk49MTIuMTEuMyBC
00000030: 546a 3033 4d54 6b34 4f54 513d Tj03MTk4OTQ=shell~ # echo 'Vk49MTIuMTEuMyBCTj03MTk4OTQ=' | base64 -d
VN=12.11.3 BN=719894shell漏洞原理#

// src/ike/iked/v2/ike2_payload_cert.c
int ike2_ProcessPayload_CERT(uint8_t *pIkeSA, p_id_t *pIDPld)
{
char identification [520];
memset(identification, 0, sizeof(identification));
...
// Vulnerability: Stack-based buffer overflow
// * pIDPld.identification is an attacker-controlled buffer
// * identification is a fixed size stack buffer of 520 bytes
memcpy(identification, pIDPld.identification.buffer, pIDPld.identification.length);
...
int status = CMgrValidateCert_GetPubKey(...);
if (status != 0)
wglog_trace_r("failed to validate received peer certificate");
wglog_trace_r("successfully validated received peer certificate");
}c首先将客户端“标识”复制到本地堆栈缓冲区,然后验证提供的客户端 SSL 证书。
查看已打补丁的12.11.4固件版本中的相同功能,可以看到缓冲区中引入了额外的长度检查(在注释下方突出显示// CVE-2025-9242 length check patch):
// src/ike/iked/v2/ike2_payload_cert.c
int ike2_ProcessPayload_CERT(uint8_t *pIkeSA, p_id_t *pIDPld)
{
char identification [512];
memset(identification, 0, sizeof(identification));
...
// CVE-2025-9242 length check patch
if (pIDPld.identification.length > 0x200)
{
wglog_trace_r("received ID data legth(%d) is larger than expected length",
gProgram, pIDPld.identification.length);
return -1;
}
memcpy(identification, pIDPld.identification.buffer, pIDPld.identification.length);
...
int status = CMgrValidateCert_GetPubKey(...);
if (status != 0)
wglog_trace_r("failed to validate received peer certificate");
wglog_trace_r("successfully validated received peer certificate");
}c利用#





内核 ASLR(地址空间随机化)开关的值通常是:
| 值 | 含义 |
|---|---|
| 0 | 关闭 ASLR |
| 1 | 保守随机化(stack / mmap 随机) |
| 2 | 完全随机化(包含 heap, stack, mmap, VDSO,最高) |
查看:
cat /proc/sys/kernel/randomize_va_spacebash会看到其中一个数(一般 Linux 默认是 2)。
2plaintext修改方式#
echo 0 > /proc/sys/kernel/randomize_va_spacebash
页对齐#
mprotect#
先了解一下mprotect(addr,length,prot),该函数的作用就是修改指定内存页的权限。第一个参数addr为所要修改的内存页的起始地址,一般低12位必须为0;第二个参数length为所要修改的长度,通常为0x1000;第三个参数为所要修改的权限r,w,x(可读,可写,可执行),代表的数字分别为1,2,4。
- 硬件内存管理单元 (MMU) 的工作方式
- MMU 以页为单位管理内存权限
- 典型的页大小是 4KB (0x1000)
- 内存权限只能按整个页设置,不能设置部分页
- 页表结构
虚拟地址: 0x7ffd020d80d0
分解为:
- 页表索引: 0x7ffd020d8
- 页内偏移: 0x0d0plaintextMMU 只能控制整个页(0x7ffd020d8000 - 0x7ffd020d8fff)的权限,不能单独控制偏移 0xd0 处的权限。
- 系统调用约束
mprotect 系统调用直接操作页表,所以地址必须是页边界。
缝缝补补#
寻找gadget:有32位、8位清零操作,无直接操作
在 x86-64 中:
- 32位操作(如
mov eax, 0x190)会自动将高32位清零 - 16位操作(如
mov ax, 0x190)只影响低16位,保持高48位不变 - 8位操作(如
mov al, 0x90)只影响低8位,保持高56位不变
组合使用:纯体力活,需要修改栈布局