๋ฐฐ๊ฒฝ
vllm ์๋ฒ ์ด์์ค 0.14.0 ๋ฏธ๋ง ๋ฒ์ ์์ RCE ์ทจ์ฝ์ ์ด ๋ฐ์ํ๋ค๊ณ ํด์ ๋ฒ์ ํจ์น๋ฅผ ํ์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ์ด์ ์ ๋์์๋ ์ทจ์ฝ์ ์ค ๋ชจ๋ธ ๋ก๋๋ฅผ ํตํด์ RCE ๊ฐ ๋ฐ์ํ ์ ์๋ค๋ ๊ธ์ ๋ณด
๊ณ ์ด๊ฒ ์ด๋ป๊ฒ ๊ฐ๋ฅํ๊ฑด์ง ์ฐพ์๋ณด๊ฒ ๋์๋๋ฐ์,
๋ฐฐํฌํฌ๋งท์ด๋ ์ผ๋ถ ํ๋ ์์ํฌ์์ ๋ชจ๋ธ๋ก๋์์ ๊ฐ์ค์น๋ง ๋ถ๋ฌ์ค๋๊ฒ์ด ์๋๋ผ
ํ์ด์ฌ ์ฝ๋ ๋ก์ง์ ํ ์ ์๋ค๋ ์ฌ์ค์ ์๊ฒ ๋์ด ์ ๋ฆฌํ ๊ฒธ ๊ธ์ ์์ฑํฉ๋๋ค.
CVE-2025-66448: vLLM Config Trust Bypass RCE | Miggo
The vulnerability lies in the __init__ method of the Nemotron_Nano_VL_Config class, located in the now-removed file vllm/transformers_utils/configs/nemotron_vl.py. The commit ffb08379d8870a1a81ba82b72797f196838d0c86 addresses the vulnerability by completel
www.miggo.io
๋ชจ๋ธ ๋ฐฐํฌ ํฌ๋งท
์ธ๊ณต์ง๋ฅ ๋ชจ๋ธ์ ๊ฐ๋ฐํ๋ค ๋ณด๋ฉด ํ์ต ์์ฒด๋ณด๋ค ๋ ๋ง์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ์ง์ ์ด ๋ฐ๋ก ๋ฐฐํฌ์ ๋๋ค. ํ์ต๋ ๋ชจ๋ธ์ ๋จ์ํ ์ฝ๋๊ฐ ์๋๋ผ ์๋ฐฑ MB์์ ์์ญ GB์ ์ด๋ฅด๋ ๊ฐ์ค์น ๋ฐ์ดํฐ์ ์คํ ๊ตฌ์กฐ๋ฅผ ํจ๊ป ๊ฐ๊ณ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ ๋ชจ๋ธ์ ์ด๋ค ํํ๋ก ์ ์ฅํ๊ณ ์ ๋ฌํ ๊ฒ์ธ๊ฐ์ ๋ํ ๋ฌธ์ ๊ฐ ๋ฐ๋ก ๋ชจ๋ธ ๋ฐฐํฌ ํฌ๋งท์ ์ถ๋ฐ์ ์ ๋๋ค.
์ด๊ธฐ์๋ ํ์ตํ ํ๋ ์์ํฌ ๋ด๋ถ์์๋ง ๋ชจ๋ธ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, ๋จ์ํ ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ฒด๋ฅผ ๊ทธ๋๋ก ์ง๋ ฌํํ๋ ๋ฐฉ์์ด ์ฌ์ฉ๋์์ต๋๋ค. ํ์ง๋ง ๋ชจ๋ธ์ด ์ปค์ง๊ณ , ํ์ ๊ณผ ์ธ๋ถ ๊ณต์ ๊ฐ ๋์ด๋๋ฉด์ ์์ฐ์ค๋ฌ์ด ์๊ตฌ์ฌํญ์ด ๋ฑ์ฅํ์ต๋๋ค. ๊ฐ์ฅ ํฐ ๊ฒ์ ๋ค๋ฅธ ํ๊ฒฝ์์๋ ๋์ผํ๊ฒ ๋ชจ๋ธ์ ๋ก๋ํ ์ ์์ด์ผ ํ๋ค๋ ๊ฒ์ธ๋ฐ์, ๋ชจ๋ธ์ ๋ง๋ค๊ณ ํ์ต์ํค๋ ๊ฒ์ ์ ์ฒด ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ์ง ์๋ ํ ๊ทธ๋ค์ง ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค๋ง, ์ถ๋ก ์ ํ ๋์๋ ์ด์์ฑ์ด ์ค์ํ๊ฒ ์ฌ๊ฒจ์ก์ต๋๋ค. ๊ทธ๋์ ๋ชจ๋ธ ํ์ผ๋ง export ํ๊ฒ ๋์๊ณ , ์ด๋ฐ ์๊ตฌ์ฌํญ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํด์ ์ฌ๋ฌ๊ฐ์ง ๋ชจ๋ธ ๋ฐฐํฌ ํฌ๋งท์ด ๋ฑ์ฅํ๊ฒ ๋์์ต๋๋ค.
Pytorch .pt .pth
Pytorch ์ ๋ชจ๋ธ ์ ์ฅ ๋ฐฉ์์ Python ๊ฐ์ฒด๋ฅผ ๊ทธ๋๋ก ๋ฐ์ดํฐ๋ก ๋ง๋๋ ๊ฒ์ธ๋ฐ ์ด๊ฒ์ ์ง๋ ฌํ๋ผ๊ณ ํฉ๋๋ค. ์ด ํฌ๋งท๋ ๋ค๋ฅธ ํฌ๋งท๋ค๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ชจ๋ธ ์ฌํ์ฑ์ ์๊ตฌ์ฌํญ์ ํด๊ฒฐํ๊ธฐ ๋๋ฌธ์ Research Level ์์๋ ํธํ๊ฒ ์ฌ์ฉ๋ ์ ์์ง๋ง, ๋ด๋ถ์ ์ผ๋ก pickle ์ ์ฌ์ฉํ๊ณ , ์ฝ๋๋ ๋ฐ์ดํฐ ์์ฒด๋ฅผ ๋ชจ๋ ์ง๋ ฌํ ํ๊ธฐ ๋๋ฌธ์ ํด๋น ๊ฐ์ฒด๋ฅผ ๋ก๋ํ๋ ๊ฒฝ์ฐ RCE๊ฐ ๊ฐ๋ฅํ๋ค๋ ์น๋ช ์ ์ธ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
python ๊ณต์๋ฌธ์์์ pickle ์ ์ง๋ ฌํ์ ์ญ์ง๋ ฌํ๋ฅผ ์ํ ๋ชจ๋์ด๋ผ๊ณ ๋์์์ต๋๋ค. ๋ค๋ฅธ ์์๋ก ์ฌ์ฉ๋๋ ๊ฒ๋ค๋ ๋์ค์ ํ๋ฒ ์ฐพ์๋ณผ๋ฒ ํ ๊ฒ ๊ฐ์ต๋๋ค.
pickle — Python object serialization
๊ทธ๋์ Pytorch ์ ๋ชจ๋ธ์ ๋ฐฐํฌํ๊ฒฝ์์๋ ์ฌ์ฉ์ ์ง์ํ๋ ๊ฒ์ด ์ข์ ๊ฒ ์ ๋๋ค.
pytorch ๋ ๋ชจ๋ธ์ ํํ๋ฅผ ์ ์ฅํ ๋ ์๋์ ๊ฐ์ด ์ ์ฅํ๋ฉด์ ์ง๋ ฌํ๋ฅผ ํ๋๋ฐ์, ํ๋ผ๋ฏธํฐ๋ง ์ ์ฅํ ์๋ ์์ต๋๋ค.
import torch
#model ๊ฐ์ฒด ๊ทธ๋๋ก ์ง๋ ฌํ
torch.save(model, 'model.pth')
torch.load('model.pth')
#model ํ๋ผ๋ฏธํฐ ์ง๋ ฌํ
torch.save(model.state_dict(), 'model.pth')
model.load_state_dict(torch.load('model.pth'))
๋ฐ์๊ฐ๋ฅํ ์ทจ์ฝ์
# Define model
class TheModelClass(nn.Module):
def __init__(self):
super(TheModelClass, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
# Initialize model
model = TheModelClass()
๋ง์ฝ ์์ ๊ฐ์ ๋ชจ๋ธ์ด ์๋ค๋ฉด torch.save ํ๋ ์์ ์์ TheModelClass ๊ฐ ์ง๋ ฌํ๋ฉ๋๋ค. ๊ทธ๋ผ class ์์ ์๋ ํจ์๋ค์ ๋ญ๊ฐ ๋ค๋ฅธ ๋ชฉ์ ์ ์ฝ๋๊ฐ ์๋ค๋ฉด torch.load() ํ๋ ์์ ์์ ๊ทธ๋๋ก ์คํ๋๊ฒ ์ง์. ์ด๊ฒ์ด pytorch ์ model.state_dict() ๋ฅผ ์ ์ฅํ์ง ์๊ณ save ํ์ ๋์ ๋ฌธ์ ์ ์
๋๋ค. ๊ทธ๋์ pytorch ๊ถ์ฅ์ฌํญ์ ํ๋ผ๋ฏธํฐ๋ง ์ ์ฅ๋๊ฒ ํ๋ torch.save(model.state_dict,’model.pth’) ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ฒ ํฉ๋๋ค.
Huggingface .safetensors
safetensors ๋ ๊ฐ์ค์น๋ฅผ ๋น ๋ฅด๊ฒ ์ ์ฅํ๊ณ ๋ถ๋ฌ์ค๊ธฐ ์ํ ํ์์ธ๋ฐ์, ๋ค๋ฅธ ๋ชจ๋ธ์์ ๋ฐ์ํ ์ ์๋ ์ทจ์ฝ์ ๋ฌธ์ ํนํ pickle ์ ์ฌ์ฉํ๋ฉด์ ๋ฐ์ํ๋ python ๊ฐ์ฒด์ ์ฅ์ด๋ ์คํ๊ฐ๋ฅํ ๊ตฌ์กฐ๋ฅผ ํฌํจํ๊ณ ์์ง ์์ต๋๋ค. safetensors ํ์ผ ๊ตฌ์กฐ๋ ํค๋์ ๋ธ๋ก์ผ๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค.
ํค๋๋ JSON ํ์์ผ๋ก ๋ ํ ์๋ค์ ๋ฉํ๋ฐ์ดํฐ์ด๊ณ , ๋ฐ์ดํฐ๋ธ๋ก์ weight๋ค์ด ์กด์ฌํ๋ ๋ฐ์ด๋๋ฆฌ ํํ์ ๋๋ค. ์ค์ ๋ก safetensors ๋ฅผ ์ด์ด์ ํ์ธํด๋ณผ ์ ์๋๋ฐ์
https://huggingface.co/Qwen/Qwen3-ASR-1.7B/tree/main
Qwen/Qwen3-ASR-1.7B at main
We’re on a journey to advance and democratize artificial intelligence through open source and open science.
huggingface.co
์ ๋๋ฒ์งธ safetensors ๊ฐ ๋ฐ๊ฒฌํ๊ฒ์ค ์ฉ๋์ด ์ข ์๋ค์, ์ด๊ฑฐ๋ก ํ ์คํธ ํด๋ณด์ ๋ ์ข์ ๋ฏ ํฉ๋๋ค.
from safetensors import safe_open
safetensors_file =
with safe_open(safetensors_file, framework="pt") as f:
tensor_name = f.keys()
print(f"tensor list {tensor_name}")
for key in tensor_name:
tensor = f.get_tensor(key)
print(f"tensor name {key} ์ ๋ฐ์ดํฐํ์
: {tensor.dtype}")
print(f"tensor name {key} ์ shape : {tensor.shape}")
tensor list ['thinker.model.layers.5.mlp.gate_proj.weight', 'thinker.model.layers.5.mlp.up_proj.weight', 'thinker.model.layers.5.post_attention_layernorm.weight', 'thinker.model.layers.5.self_attn.k_norm.weight', 'thinker.model.layers.5.self_attn.k_proj.weight', 'thinker.model.layers.5.self_attn.o_proj.weight', 'thinker.model.layers.5.self_attn.q_norm.weight', 'thinker.model.layers.5.self_attn.q_proj.weight', 'thinker.model.layers.5.self_attn.v_proj.weight', 'thinker.model.layers.6.input_layernorm.weight', 'thinker.model.layers.6.mlp.down_proj.weight', 'thinker.model.layers.6.mlp.gate_proj.weight', 'thinker.model.layers.6.mlp.up_proj.weight', 'thinker.model.layers.6.post_attention_layernorm.weight', 'thinker.model.layers.6.self_attn.k_norm.weight', 'thinker.model.layers.6.self_attn.k_proj.weight', 'thinker.model.layers.6.self_attn.o_proj.weight', 'thinker.model.layers.6.self_attn.q_norm.weight', 'thinker.model.layers.6.self_attn.q_proj.weight', 'thinker.model.layers.6.self_attn.v_proj.weight', 'thinker.model.layers.7.input_layernorm.weight', 'thinker.model.layers.7.mlp.down_proj.weight', 'thinker.model.layers.7.mlp.gate_proj.weight', 'thinker.model.layers.7.mlp.up_proj.weight', 'thinker.model.layers.7.post_attention_layernorm.weight', 'thinker.model.layers.7.self_attn.k_norm.weight', 'thinker.model.layers.7.self_attn.k_proj.weight', 'thinker.model.layers.7.self_attn.o_proj.weight', 'thinker.model.layers.7.self_attn.q_norm.weight', 'thinker.model.layers.7.self_attn.q_proj.weight', 'thinker.model.layers.7.self_attn.v_proj.weight', 'thinker.model.layers.8.input_layernorm.weight', 'thinker.model.layers.8.mlp.down_proj.weight', 'thinker.model.layers.8.mlp.gate_proj.weight', 'thinker.model.layers.8.mlp.up_proj.weight', 'thinker.model.layers.8.post_attention_layernorm.weight', 'thinker.model.layers.8.self_attn.k_norm.weight', 'thinker.model.layers.8.self_attn.k_proj.weight', 'thinker.model.layers.8.self_attn.o_proj.weight', 'thinker.model.layers.8.self_attn.q_norm.weight', 'thinker.model.layers.8.self_attn.q_proj.weight', 'thinker.model.layers.8.self_attn.v_proj.weight', 'thinker.model.layers.9.input_layernorm.weight', 'thinker.model.layers.9.mlp.down_proj.weight', 'thinker.model.layers.9.mlp.gate_proj.weight', 'thinker.model.layers.9.mlp.up_proj.weight', 'thinker.model.layers.9.post_attention_layernorm.weight', 'thinker.model.layers.9.self_attn.k_norm.weight', 'thinker.model.layers.9.self_attn.k_proj.weight', 'thinker.model.layers.9.self_attn.o_proj.weight', 'thinker.model.layers.9.self_attn.q_norm.weight', 'thinker.model.layers.9.self_attn.q_proj.weight', 'thinker.model.layers.9.self_attn.v_proj.weight', 'thinker.model.norm.weight']
tensor name thinker.model.layers.5.mlp.gate_proj.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.5.mlp.gate_proj.weight ์ shape : torch.Size([6144, 2048])
tensor name thinker.model.layers.5.mlp.up_proj.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.5.mlp.up_proj.weight ์ shape : torch.Size([6144, 2048])
tensor name thinker.model.layers.5.post_attention_layernorm.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.5.post_attention_layernorm.weight ์ shape : torch.Size([2048])
tensor name thinker.model.layers.5.self_attn.k_norm.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.5.self_attn.k_norm.weight ์ shape : torch.Size([128])
tensor name thinker.model.layers.5.self_attn.k_proj.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.5.self_attn.k_proj.weight ์ shape : torch.Size([1024, 2048])
tensor name thinker.model.layers.5.self_attn.o_proj.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.5.self_attn.o_proj.weight ์ shape : torch.Size([2048, 2048])
tensor name thinker.model.layers.5.self_attn.q_norm.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.5.self_attn.q_norm.weight ์ shape : torch.Size([128])
tensor name thinker.model.layers.5.self_attn.q_proj.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.5.self_attn.q_proj.weight ์ shape : torch.Size([2048, 2048])
tensor name thinker.model.layers.5.self_attn.v_proj.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.5.self_attn.v_proj.weight ์ shape : torch.Size([1024, 2048])
tensor name thinker.model.layers.6.input_layernorm.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.6.input_layernorm.weight ์ shape : torch.Size([2048])
tensor name thinker.model.layers.6.mlp.down_proj.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.6.mlp.down_proj.weight ์ shape : torch.Size([2048, 6144])
tensor name thinker.model.layers.6.mlp.gate_proj.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.6.mlp.gate_proj.weight ์ shape : torch.Size([6144, 2048])
tensor name thinker.model.layers.6.mlp.up_proj.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
tensor name thinker.model.layers.6.mlp.up_proj.weight ์ shape : torch.Size([6144, 2048])
tensor name thinker.model.layers.6.post_attention_layernorm.weight ์ ๋ฐ์ดํฐํ์
: torch.bfloat16
weight ์ ๋ํ ๋ฐ์ดํฐ๊ฐ ์๋๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. RCE ๋ฅผ ์์ฒ์ ์ผ๋ก ๋ง๊ธฐ ์ํด ์ค๊ณ ๋ ๋งํผ safetensors ๋ชจ๋ธ์์ฒด์ ๋ํด์๋ ๋ฐ๊ฒฌ๋ ์ทจ์ฝ์ ์ด ์์ต๋๋ค.
Microsoft ONNX(Open Neural Network Exchange)
ONNX ๋ ๋ง์ ๋จธ์ ๋ฌ๋ ํ๋ ์์ํฌ ๊ฐ์ ๋ชจ๋ธ์ ํตํฉํ ์ ์๋๋ก ์ค๊ณ๋ ์คํ์์ค ํฌ๋งท์ ๋๋ค. ONNX ๋ฅผ ํตํด์ ๊ฐ๋ฐ์๋ค์ Pytorch ๋ Tensorflow ๋ฑ ์์ดํ ๋จธ์ ๋ฌ๋ ํ๋ ์์ํฌ์์ ๊ฐ๋ฐํด๋ ONNX ๋ฅผ ํตํด์ ์๋ก๋ค๋ฅธ ํ๋ ์์ํฌ๋ก ์ฝ๊ฒ ์ ํํด์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด ์ญ์ ๋ฐฐํฌ๋ฅผ ์ํํ๊ฒ ํ์๋ ์ ์ ์์ ๊ฐ๋ฐ๋์์ต๋๋ค.
import torch
import torchvision.models as models
import onnx
# ์ฌ์ ํ๋ จ๋ PyTorch ๋ชจ๋ธ ๋ก๋
model = models.resnet18(pretrained=True)
model.eval()
# ๋๋ฏธ ์
๋ ฅ ๋ฐ์ดํฐ ์์ฑ
x = torch.randn(1, 3, 224, 224, requires_grad=True)
# ๋ชจ๋ธ์ ONNX ํฌ๋งท์ผ๋ก ๋ณํ
torch.onnx.export(model, # ์คํํ ๋ชจ๋ธ
x, # ๋ชจ๋ธ ์
๋ ฅ๊ฐ (ํํ ๋๋ ์ฌ๋ฌ ์
๋ ฅ๊ฐ์ ์ํ ํํ๋ ๊ฐ๋ฅ)
"resnet18.onnx", # ์ ์ฅ๋ ๋ชจ๋ธ์ ์ด๋ฆ
export_params=True, # ๋ชจ๋ธ ํ์ผ ๋ด ํ์ต๋ ๋ชจ๋ธ ๊ฐ์ค์น๋ฅผ ์ ์ฅํ ์ง์ ์ฌ๋ถ
opset_version=10, # ๋ชจ๋ธ์ ๋ณํํ ๋ ์ฌ์ฉํ ONNX ๋ฒ์
do_constant_folding=True, # ์ต์ ํ: ์์ ํด๋ฉ์ ์ํํ ์ง ์ฌ๋ถ
input_names = ['input'], # ๋ชจ๋ธ์ ์
๋ ฅ๊ฐ์ ๋ํ ์ด๋ฆ
output_names = ['output'], # ๋ชจ๋ธ์ ์ถ๋ ฅ๊ฐ์ ๋ํ ์ด๋ฆ
dynamic_axes={'input' : {0 : 'batch_size'}, # ๋ฐฐ์น ํฌ๊ธฐ์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๋ณํ๋ ์
๋ ฅ ์ฐจ์
'output' : {0 : 'batch_size'}}) # ๋ฐฐ์น ํฌ๊ธฐ์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๋ณํ๋ ์ถ๋ ฅ ์ฐจ์
ONNX ๋ฐ์ ๊ฐ๋ฅํ ์ทจ์ฝ์
์ต๊ทผ๊น์ง๋ ONNX ์ ๋ณด๊ณ ๋ ์ทจ์ฝ์ ๋ค์์ ONNX ์์ฒด์ ์ทจ์ฝ์ ์ ๊ฑฐ์ ์๋ค๊ณ ํด๋ ๋ ์ ๋๋ก ์์๊ณ , ๊ฒ๋ค๊ฐ RCE ๋ ์ ํ ๋ณผ์ ์์์ต๋๋ค. ์ด ๋ง์ ๋ C/C++ ์๋ฐํ ๋งํ๋ฉด ๋ฐํ์ ์ ํ์ ์ทจ์ฝ์ ์ด๋ผ๊ณ ํ ์ ์์๋ค๋๋ฐ์, ์ต๊ทผ ๋ฐํ ๋ Path Traveling ์ทจ์ฝ์ ๋ ONNX ํฌ๋งท์ ๋ฌธ์ ๋ผ๊ธฐ๋ณด๋ค๋, ONNX ๋ชจ๋ธ์ ์ฒ๋ฆฌํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ตฌํ์ ์ทจ์ฝ์ ์ด๋ผ๊ณ ํฉ๋๋ค.
ONNX Path Traversal Vulnerability Exploited | Matt T.๋์ด ํ ํฝ์ ๋ํด ์ฌ๋ฆผ | LinkedIn
CVE-2025-51480 Path Traversal vulnerability in onnx.external_data_helper.save_external_data in ONNX 1.17.0 allows attackers to overwrite arbitrary files by supplying crafted external_data.location paths containing traversal sequences, bypassing intended di
www.linkedin.com
GGUF / GGML
GGML (Georgi Gerganov Machine Learning Format)
GGML์ Georgi Gerganov๊ฐ ๊ฐ๋ฐํ ๊ฒฝ๋ ๋จธ์ ๋ฌ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, ๋๊ท๋ชจ ์ธ์ด ๋ชจ๋ธ์ ํฌํจํ ์ ๊ฒฝ๋ง ๋ชจ๋ธ์ CPU ํ๊ฒฝ์์ ํจ์จ์ ์ผ๋ก ์ถ๋ก ํ๊ธฐ ์ํด ์ค๊ณ๋ C/C++ ๊ธฐ๋ฐ ํ๋ก์ ํธ์ ๋๋ค. Hugging Face์ ์๊ฐ ๊ธ์์๋ ๊ฐ์กฐํ๋ฏ, GGML์ ๊ธฐ์กด ๋ฅ๋ฌ๋ ํ๋ ์์ํฌ๊ฐ ๊ฐ๋ ๋ณต์ก์ฑ๊ณผ ๋ฌด๊ฑฐ์ด ์์กด์ฑ์ ์ต์ํํ๋ ๊ฒ์ ๋ชฉํ๋ก ๋ง๋ค์ด์ก์ต๋๋ค.
์ผ๋ฐ์ ์ธ ๋จธ์ ๋ฌ๋ ํ๋ ์์ํฌ์ธ PyTorch๋ TensorFlow๋ ๋งค์ฐ ๊ฐ๋ ฅํ์ง๋ง, ๋๊ท๋ชจ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์กด์ฑ๊ณผ ๋ณต์กํ ๋น๋ ํ๊ฒฝ์ ์๊ตฌํฉ๋๋ค. ์ด๋ ์๋ฒ ํ๊ฒฝ์์๋ ๋ฌธ์ ๊ฐ ๋์ง ์์ ์ ์์ง๋ง, ๊ฐ์ธ PC๋ ๋ด๋ถ๋ง, ์คํ๋ผ์ธ ํ๊ฒฝ, ํน์ ๋ฆฌ์์ค๊ฐ ์ ํ๋ ์์คํ ์์๋ ๋ถ๋ด์ผ๋ก ์์ฉํฉ๋๋ค. GGML์ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ธ๋ถ ์์กด์ฑ์ ๊ฑฐ์ ๊ฐ์ง ์๋ ๊ตฌ์กฐ, ๊ทธ๋ฆฌ๊ณ ๋จ์ํ C ์ฝ๋ ๊ธฐ๋ฐ ๊ตฌํ์ ์ ํํ์ต๋๋ค.
GGML์ ํต์ฌ ์ฒ ํ์ “์๊ณ , ๋จ์ํ๋ฉฐ, ์์ธก ๊ฐ๋ฅํ ์คํ”์ ๋๋ค. ์ค์ ๋ก GGML์ ๋ช ๊ฐ์ ์์ค ํ์ผ๋ง์ผ๋ก ๊ตฌ์ฑ๋์ด ์์ผ๋ฉฐ, ์ปดํ์ผ๋ ๋ฐ์ด๋๋ฆฌ ํฌ๊ธฐ ์ญ์ ๋งค์ฐ ์์ต๋๋ค. ๋ณ๋์ Python ๋ฐํ์์ด๋ ๋ํ ํ๋ ์์ํฌ ์์ด๋ ๋ชจ๋ธ์ ์คํํ ์ ์๊ธฐ ๋๋ฌธ์, ํ๊ฒฝ ์ด์์ฑ์ด ๋งค์ฐ ๋ฐ์ด๋ฉ๋๋ค. Linux, macOS, Windows๋ ๋ฌผ๋ก ์ด๊ณ ARM ์ํคํ ์ฒ๋ Apple Silicon ํ๊ฒฝ์์๋ ๋น๊ต์ ์ฝ๊ฒ ๋น๋ํ๊ณ ์คํํ ์ ์์ต๋๋ค.
๋ ํ๋์ ์ค์ํ ํน์ง์ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ์ ๋๋ค. GGML์ ํ ์ ํํ๊ณผ ์ฐ์ฐ์์ ๋ถํ์ํ ์ค๋ฒํค๋๋ฅผ ์ ๊ฑฐํ๊ณ , CPU ์บ์ ์นํ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์์ ์ฌ์ฉํฉ๋๋ค. ํนํ GGML์ด ๋๋ฆฌ ์ฃผ๋ชฉ๋ฐ๊ฒ ๋ ์ด์ ์ค ํ๋๋ ๊ฐ๋ ฅํ ์์ํ(quantization) ์ง์์ ๋๋ค. float32 ๊ธฐ๋ฐ ๋ชจ๋ธ์ int8, int5, int4 ์์ค์ผ๋ก ์์ถํด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ํฌ๊ฒ ์ค์ด๋ฉด์๋, ์ถ๋ก ์ฑ๋ฅ์ ์ค์ฉ์ ์ธ ์์ค์ผ๋ก ์ ์งํ ์ ์๋๋ก ์ค๊ณ๋์์ต๋๋ค.
์ด๋ฌํ ํน์ฑ ๋๋ถ์ GGML์ ํ์ต๋ณด๋ค๋ ์ถ๋ก ์ค์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ฏธ ํ์ต๋ ๋ชจ๋ธ์ ๊ฐ๋ฅํ ํ ์ ์ ์์์ผ๋ก ๋น ๋ฅด๊ฒ ์คํํ๋ ๊ฒ์ด ๋ชฉ์ ์ด๋ฉฐ, ์ค์ ๋ก llama.cpp, whisper.cpp, GPT4All, LM Studio, Ollama์ ๊ฐ์ ์ฌ๋ฌ ํ๋ก์ ํธ๋ค์ด GGML์ ์ ์์ค ์ฐ์ฐ ์์ง์ผ๋ก ํ์ฉํ๊ณ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ GGML์ ๋จ์ํ ๋ชจ๋ธ ํฌ๋งท์ด๋ผ๊ธฐ๋ณด๋ค๋, ๋ชจ๋ธ ์คํ์ ๋ด๋นํ๋ ์ ์์ค ๋ฐํ์์ ๊ฐ๊น๋ค๊ณ ๋ณผ ์ ์์ต๋๋ค.
๊ตฌ์กฐ์ ์ผ๋ก ๋ณด๋ฉด GGML์ ๋ด๋ถ์ ํ ์์ ์ฐ์ฐ ๊ทธ๋ํ๋ฅผ ๊ด๋ฆฌํ๋ context๋ฅผ ๋๊ณ , ์ฐ์ฐ ๊ทธ๋ํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ณ์ฐ์ ์ํํฉ๋๋ค. ๋ํ CPU, CUDA, Metal ๋ฑ ๋ค์ํ ๋ฐฑ์๋๋ฅผ ์ง์ํ ์ ์๋๋ก ์ค๊ณ๋์ด ์์ผ๋ฉฐ, ๋ฐฑ์๋๋ณ๋ก ๋ฉ๋ชจ๋ฆฌ ํ ๋น๊ณผ ์ฐ์ฐ ์ค์ผ์ค๋ง์ ๋ถ๋ฆฌํด ๊ด๋ฆฌํฉ๋๋ค. ์ด๋ฌํ ๊ตฌ์กฐ ๋๋ถ์ ๊ฐ๋ณ์ง๋ง ๋จ์ํ ์์ค์ ๋๋ ์ ์ฐ์ฑ์ ํ๋ณดํ ์ ์์์ต๋๋ค.
๋ค๋ง GGML์ ์ด๋ฌํ ์ฅ์ ๊ณผ ํจ๊ป ํ๊ณ๋ ๊ฐ๊ณ ์์ต๋๋ค. C/C++ ๊ธฐ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํน์ฑ์ ์ฌ์ฉ ๋์ด๋๊ฐ ๋๊ณ , Python ๊ธฐ๋ฐ ํ๋ ์์ํฌ์ ์ต์ํ ์ฌ์ฉ์์๊ฒ๋ ์ง์ ์ฅ๋ฒฝ์ด ๋ ์ ์์ต๋๋ค. ๋ํ ๋ชจ๋ธ ๋ฉํ๋ฐ์ดํฐ ํํ์ด ์ ํ์ ์ด๊ณ , ํ ํฌ๋์ด์ ๋ specia1 token, rope ์ค์ ๊ณผ ๊ฐ์ ๋ถ๊ฐ ์ ๋ณด๋ฅผ ํจ๊ป ๊ด๋ฆฌํ๋ ๋ฐ์๋ ๋ถํธํจ์ด ์กด์ฌํ์ต๋๋ค. ์ด๋ฌํ ํ๊ณ๋ ๋ชจ๋ธ์ด ๋ณต์กํด์ง์๋ก ์ ์ ๋ ๋ฌธ์ ๊ฐ ๋์์ต๋๋ค.
์ด๋ฌํ ๋ฐฐ๊ฒฝ ์์์ GGML์ ์ ์ฐจ GGUF(GGML Unified Format)๋ก ๋ฐ์ ํ๊ฒ ๋ฉ๋๋ค. GGUF๋ GGML์ ์ฒ ํ์ ์ ์งํ๋ฉด์๋, ๋ชจ๋ธ ์คํ์ ํ์ํ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ค ๋ช ํํ๊ณ ํ์ฅ ๊ฐ๋ฅํ๊ฒ ๋ด๊ธฐ ์ํด ์ค๊ณ๋ ํฌ๋งท์ ๋๋ค. ํ์ฌ llama.cpp ์ํ๊ณ์์๋ GGML๋ณด๋ค๋ GGUF ์ฌ์ฉ์ด ๊ถ์ฅ๋๊ณ ์์ผ๋ฉฐ, GGML์ ์ ์ฐจ ๋ ๊ฑฐ์ ํฌ๋งท์ ์์น๋ก ์ด๋ํ๊ณ ์์ต๋๋ค.
์ ๋ฆฌํ์๋ฉด, GGML์ “๋ชจ๋ธ์ ์์ ํ๊ฒ ์ ์ฅํ๋ค”๋ ๋ฐฐํฌ ํฌ๋งท์ ๊ฐ๋ ๋ณด๋ค๋, “๋ชจ๋ธ์ ๊ฐ๋ณ๊ณ ํจ์จ์ ์ผ๋ก ์คํํ๋ค”๋ ๋ชฉ์ ์ ์ถฉ์คํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. Python ๊ฐ์ฒด ์ง๋ ฌํ๋ ์คํ ๊ฐ๋ฅํ ์ฝ๋ ๋ก๋ฉ๊ณผ๋ ๊ฑฐ๋ฆฌ๊ฐ ๋ฉ๊ธฐ ๋๋ฌธ์, ๊ตฌ์กฐ์ ์ผ๋ก RCE์ ๊ฐ์ ์ทจ์ฝ์ ๊ณผ๋ ๋ฌด๊ดํ ํธ์ ๋๋ค. ๋ค๋ง ๋ค๋ฅธ ๋ชจ๋ ์คํ ์์ง๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, ์ต์ข ์ ์ธ ์์ ์ฑ๊ณผ ๋ณด์์ฑ์ ๋ฐํ์ ๊ตฌํ๊ณผ ์ด์ ๋ฐฉ์์ ์ํด ๊ฒฐ์ ๋๋ค๋ ์ ์ ๋์ผํ๊ฒ ์ ์ฉ๋ฉ๋๋ค.
GGUF (GGML Unified Format)
GGUF๋ GGML์ ๊ธฐ๋ฐ์ผ๋ก ํ ๊ฐ์ ๋ ํฌ๋งท์ ๋๋ค. ์ด๋ฆ์์ ์ ์ ์๋ฏ 'ํตํฉ๋(Unified)' ํ์์ ์งํฅํ๋ฉฐ, ๋ ๋ง์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๊ณ ํ์ฅ์ฑ์ ๋์์ต๋๋ค. ์ด๋ฆ์ ๋ถ์ผ๋์๋
<BaseName><SizeLabel><FineTune><Version><Encoding><Type><Shard>.gguf ๋ผ๋ ๋ค์ด๋ฐ ๊ท์น์ ๋ง๋ค์์ต๋๋ค. ๋ ๋ง์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํฌํจํ ์ ์๊ฒ ํ์ผ๊ตฌ์กฐ๊ฐ ๊ฐ์ ๋์์ต๋๋ค.

GGUF ๋ ๋๋ฌด ๋ง์ ์ด์ผ๊ธฐ๋ค์ด ์๋๋ฐ ๋ฐ๋ก ๋ค๋ฃจ๋๋ก ํ๊ฒ ์ต๋๋ค. ๊ฒฐ๋ก ์ GGML ์ ํธ๋์คํฌ๋จธ ๋ชจ๋ธ ์๋น ํนํ ๋ฐฐํฌ ํฌ๋งท์ด๊ณ , GGUF ๋ ์ฌ๊ธฐ์ ๊ด๋ฆฌ์ ์ธ ์ธก๋ฉด์ ๊ณ ๋ํํ ํฌ๋งท์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
GGML /GGUF ์ ์ทจ์ฝ์ ๋ฐ์ ๊ฐ๋ฅ์ฑ
GGML ์ด๋ GGUF ๋๋ค Python ๊ฐ์ฒด๋ฅผ ํฌํจํ์ง ์๊ณ ๊ฐ์ ์๋ฏธ๋ก pickle ์ด๋ ์ด๋ค ์คํฌ๋ฆฝํธ๋ฅผ ํฌํจํ์ง ์์ต๋๋ค. ๊ทธ๋์ ๋ชจ๋ธ ์์ฒด๊ฐ ์ฝ๋๋ฅผ ์คํ์ํจ๋ค๋์ง์ ์ทจ์ฝ์ ์ ๋ฐ์ํ์ง ์์ต๋๋ค.
ํ๋ ์์ํฌ๋ฅผ ์์๋ณด๋ค ๋ณด๋ ์ ๋ง ๋๋ฌด ๋ง์ ํ๋ ์์ํฌ๋ค์ด ์๋๋ผ๊ตฌ์, ๊ทธ๋์ GPT ์๊ฒ ์ ๋ฆฌ๋ฅผ ์ข ํด๋ฌ๋ผ ํ๋๋ ์ด๋์ ์ฌ์ฉํ๊ณ ์๋์ง๋ ๋ชจ๋ฅด๋ ๋ ์๋ค๊น์ง ๊ฐ์ ธ๋ค ์ ๋ฆฌ๋ฅผ ํ๋ค์,
| ํฌ๋งท / ํํ | ์ฃผ ์ฌ์ฉ์ฒ | ํฌํจ ๋ด์ฉ | ์ฝ๋ ์คํ ๊ฐ๋ฅ์ฑ | ๋ณด์ ์ํ๋ | ์ฅ์ | ๋จ์ | ๊ถ์ฅ ์ฌ์ฉ ์ฌ๋ถ |
|---|---|---|---|---|---|---|---|
| safetensors | HF, ๋ด๋ถ๋ง, ๋ณด์ ํ๊ฒฝ | ์์ ํ ์ ๊ฐ์ค์น | โ ์์ | โญ ๋งค์ฐ ๋ฎ์ | pickle ๋ฏธ์ฌ์ฉ, fast mmap, ์์ | ๊ฐ์ค์น๋ง ์ ์ฅ | โ ๊ฐ๋ ฅ ๊ถ์ฅ |
PyTorch .pt / .pth |
์ฐ๊ตฌ/๊ฐ๋ฐ | Python ๊ฐ์ฒด + ๊ฐ์ค์น | ๐ฅ ๊ฐ๋ฅ | ๐ฅ๐ฅ๐ฅ | ์ ์ฅ ์ ์ฐ์ฑ | pickle ๊ธฐ๋ฐ RCE | โ ๋ฐฐํฌ ๊ธ์ง |
HF .bin (pytorch_model.bin) |
HF ๊ตฌ๋ฒ์ | pickle ๊ฐ์ค์น | ๐ฅ ๊ฐ๋ฅ | ๐ฅ๐ฅ๐ฅ | ํธํ์ฑ | ์ฌ์ค์ .pt |
โ |
ONNX .onnx |
์ถ๋ก /์๋น | ์ ์ ๊ทธ๋ํ + ๊ฐ์ค์น | โ | โญ ๋ฎ์ | ํ๋ ์์ํฌ ๋ ๋ฆฝ, ๋น ๋ฆ | ๋์ ๊ตฌ์กฐ ์ ํ | โ ์ถ๋ก ์ฉ |
TorchScript .ts / .pt |
PyTorch ์๋น | IR ๊ทธ๋ํ + ๊ฐ์ค์น | โ ๏ธ ์ ํ์ | โ ๏ธ ์ค๊ฐ | Python ์ ๊ฑฐ | ๋๋ฒ๊น ์ด๋ ค์ | โ ๏ธ ์ ํ์ |
| TensorFlow SavedModel | TF ์๋น | ๊ทธ๋ํ + ๊ฐ์ค์น | โ | โญ ๋ฎ์ | TF Serving ์ต์ | TF ์ข ์ | โ ๏ธ |
HDF5 .h5 |
Keras | ๊ฐ์ค์น + ๊ตฌ์กฐ | โ | โญ ๋ฎ์ | ๋จ์ | ๋๊ท๋ชจ ๋ชจ๋ธ ํ๊ณ | โ ๏ธ |
| GGUF / GGML | llama.cpp | ์์ํ ๊ฐ์ค์น | โ | โญ ๋ฎ์ | CPU ์นํ | ํ์ต ๋ถ๊ฐ | โ ๋ก์ปฌ |
| MLflow model | MLOps | ๋ชจ๋ธ + ๋ฉํ + ์ฝ๋ | ๐ฅ ๊ฐ๋ฅ | ๐ฅ๐ฅ | ๊ด๋ฆฌ ํธํจ | ์ฝ๋ ํฌํจ | โ ๏ธ ๊ฒ์ฆ ํ์ |
| Triton model repo | NVIDIA Triton | ๋ชจ๋ธ + config | โ | โญ ๋ฎ์ | ๊ณ ์ฑ๋ฅ ์๋น | ์ค์ ๋ณต์ก | โ |
| Docker image | ๋ฐฐํฌ | ๋ชจ๋ธ + ์ฝ๋ + OS | ๐ฅ๐ฅ๐ฅ | ๐ฅ๐ฅ๐ฅ | ์ฌํ์ฑ | ๊ณต๊ฒฉ๋ฉด ํผ | โ ๏ธ ๋ด๋ถ๊ฒ์ฆ |
| HF repo (์ ์ฒด) | ๊ณต์ | ๊ฐ์ค์น + Python | ๐ฅ๐ฅ๐ฅ | ๐ฅ๐ฅ๐ฅ | ํธ์์ฑ | trust_remote_code | โ ๋ฌด๊ฒ์ฆ |
| LoRA / Adapter | ํ์ธํ๋ | ๊ฐ์ค์น delta | โ | โญ ๋ฎ์ | ๊ฒฝ๋ | base ํ์ | โ |
๊ทธ๋์ ๊ฒฐ๋ก ์ ๋ชจ๋ธ์ ์ฌ๋ฌ ์๊ตฌ์ฌํญ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํด์ ํตํฉ๋ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๊ณ , ๊ทธ๊ณณ์์ ๋ฐ์ํ๋ ์ทจ์ฝ์ ์ ๋์ฒด๋ก pickle ์ ์ง๋ ฌํ๋ฅผ ์ฌ์ฉํด์ ๊ธฐ๋๋๋ ๋ฌธ์ ์ ๋ค์ด์์ต๋๋ค.
๊ทธ๋์ pickle ์ ์ง๋ ฌํ๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด, RCE ๊ฐ์ ์น๋ช ์ ์ธ ๋ฌธ์ ๋ค์ ๋ชจ๋ธ ์์ฒด์์ ์๊ธฐ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค. ๋ค๋ง ๋ชจ๋ธ ๋ฐํ์ ํ๋ ์์ํฌ์์ ๋ฐ์ํ๋ ์ทจ์ฝ์ ๋ค์ ์ ํ ๋ค๋ฅธ ์์ญ์ด๋ ์ฌ์ฉ์ ์ฐธ๊ณ ํด์ผํ ๊ฒ ๊ฐ์ต๋๋ค.
ํ๋ฆฐ ์ ๋ณด๊ฐ ์๋ค๋ฉด ์๋ ค์ฃผ์ธ์!
'Dev,AI > Machine Learning' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| Transformer ๊ตฌ์กฐ์์ Layer Norm ์ด Batch Norm์ด ๋ ์ ํฉํ ์ด์ (0) | 2026.01.15 |
|---|---|
| Seq2Seq (4) | 2024.01.28 |
