Bleeding Llama — Khi Một File GGUF Có Thể Hút Cạn Bộ Nhớ Máy Chủ Ollama Của Bạn
CVE-2026-7482 là lỗ hổng nghiêm trọng (CVSS 9.1) cho phép đọc vượt biên heap (heap out-of-bounds read) không cần xác thực trong bộ parse GGUF của Ollama. Kẻ tấn công tải lên một model được dàn dựng, gọi /api/create, và mang theo toàn bộ bộ nhớ tiến trình — API key, system prompt, hội thoại người dùng, mọi thứ. Khoảng 300.000 máy chủ Ollama phơi mình trên internet đang dễ bị tổn thương. Đây là cách lỗi hoạt động, cách kiểm tra xem bạn có bị ảnh hưởng, và cách xử lý.
Table of Contents
Chuyện Gì Đã Xảy Ra
Ngày 5 tháng 5 năm 2026, Cyera Research công bố công khai CVE-2026-7482 — biệt danh “Bleeding Llama” — một lỗ hổng nghiêm trọng trong Ollama, công cụ phổ biến nhất để chạy LLM trên máy cục bộ. Lỗi nằm trong bộ parse model GGUF của Ollama. Một kẻ tấn công không cần xác thực có thể tải lên một file model độc hại, gọi đúng một endpoint API, và nhận về toàn bộ bộ nhớ heap của máy chủ Ollama — biến môi trường, API key, system prompt, hội thoại đang diễn ra của người dùng.
Điểm CVSS là 9.1 (Nghiêm Trọng). Số lượng máy chủ Ollama có thể truy cập công khai vào khoảng 300.000. Mọi phiên bản Ollama trước 0.17.1 đều bị ảnh hưởng.
Bài viết này dựa trên phân tích chi tiết của Cyera Research về lỗ hổng.
Cách Cuộc Tấn Công Hoạt Động
Nguyên Nhân Gốc — Một Tensor Shape Không Ai Kiểm Tra
GGUF là định dạng nhị phân mà Ollama (và llama.cpp) dùng để lưu trọng số model. Mọi tensor trong file GGUF đều khai báo shape — kích thước của mảng nhiều chiều — trong phần header của file.
Đường dẫn quantization của Ollama đọc các giá trị shape này và đưa thẳng vào một vòng lặp chuyển đổi (ConvertToF32). Vòng lặp duyệt shape[0] * shape[1] * ... phần tử ra khỏi buffer. Buffer thì bị giới hạn bởi kích thước file. Còn giá trị shape thì không.
Nếu kẻ tấn công đặt một con số rất lớn vào trường shape, vòng lặp sẽ mù quáng đọc vượt ra ngoài cuối buffer — đó chính là heap read vượt biên.
Tệ hơn nữa, quá trình chuyển đổi dùng package unsafe của Go, vốn bỏ qua các đảm bảo an toàn bộ nhớ của runtime Go. Không hề có bước kiểm tra ranh giới giữa shape khai báo trong manifest và payload thực tế của file.
Chuỗi Khai Thác Bốn Bước
Cuộc tấn công không cần xác thực, không cần nạn nhân thao tác, và hoạt động trên bất kỳ máy chủ Ollama nào truy cập được trên mạng.
| Bước | Endpoint | Điều Gì Xảy Ra |
|---|---|---|
| 1 | POST /api/blobs/sha256:... | Kẻ tấn công tải lên file GGUF dàn dựng với giá trị shape tensor bị thổi phồng |
| 2 | POST /api/create | Kích hoạt quantization → ConvertToF32 đọc vượt xa buffer → dữ liệu heap tràn vào tensor đầu ra |
| 3 | (nội bộ) | Kẻ tấn công chọn chuyển đổi F16 → F32 — một phép biến đổi không mất mát, nên byte bị rò rỉ vẫn còn nguyên vẹn trong model artifact mới |
| 4 | POST /api/push | Đẩy “model” mới (giờ chứa bộ nhớ heap) lên một registry do kẻ tấn công kiểm soát thông qua tên model dạng URI |
Heap bị rò rỉ có thể chứa bất cứ thứ gì tiến trình Ollama đã chạm vào: biến môi trường, API key của vendor truyền vào cho chế độ proxy, system prompt, nội dung chat của người dùng khác, session token.
Lộ Trình Công Bố
Vụ này được báo cáo có trách nhiệm. Bản vá đã có mặt trước khi công bố công khai.
| Ngày | Sự Kiện |
|---|---|
| 2026-02-02 | Cyera Research báo cáo lỗ hổng cho Ollama |
| 2026-02-25 | Ollama xác nhận và đề xuất bản vá |
| 2026-03-02 | Gửi yêu cầu CVE cho MITRE |
| 2026-04-28 | Echo CNA gán CVE-2026-7482 |
| 2026-05-01 | CVE được công bố |
| 2026-05-05 | Cyera công bố bài phân tích kỹ thuật đầy đủ |
Vì Sao “300.000 Máy Chủ” Không Phải Phóng Đại
Mặc định Ollama bind vào 127.0.0.1, lẽ ra như vậy là ổn. Nhưng công thức triển khai production được khuyến nghị — bao gồm trong chính README của Ollama và hầu hết tutorial “tự host LLM” — là:
OLLAMA_HOST=0.0.0.0 ollama serve
OLLAMA_HOST=0.0.0.0 bind Ollama vào mọi network interface, không xác thực, trên cổng 11434. Truy vấn Shodan và Censys trả về ~300.000 instance có thể truy cập từ internet. Các endpoint /api/create, /api/blobs, và /api/push không có xác thực trong bản phân phối gốc.
Làm Sao Biết Tôi Có Bị Ảnh Hưởng
Kiểm Tra Phiên Bản Ollama
Phiên bản đã vá là 0.17.1. Mọi bản trước đó đều dính.
# Kiểm tra phiên bản đang cài
ollama --version
# Nếu chạy dưới dạng service
systemctl status ollama | grep -i version
Kiểm Tra Có Bị Phơi Ra Mạng Không
# Ollama có đang bind vào mọi interface?
ss -tlnp | grep 11434
# Dòng chứa 0.0.0.0:11434 hoặc [::]:11434 nghĩa là bạn
# đang phơi mình trên mọi interface. 127.0.0.1:11434 mới là trạng thái an toàn.
# Kiểm tra environment của tiến trình ollama đang chạy
ps -ef | grep ollama
cat /proc/$(pgrep ollama | head -1)/environ 2>/dev/null | tr '\0' '\n' | grep OLLAMA_HOST
Kiểm Tra Log Máy Chủ Có Lưu Lượng Khai Thác Không
Dấu vân tay của exploit là một POST /api/create ngay sau đó là POST /api/push từ cùng một IP nguồn với URI registry không quen thuộc.
# systemd journal (Linux)
journalctl -u ollama --since "30 days ago" | grep -E "api/(create|push|blobs)"
# Log container Docker
docker logs ollama 2>&1 | grep -E "api/(create|push|blobs)"
Bất kỳ POST /api/push đi đến đích không phải registry.ollama.ai đều đáng nghi mặc định.
# Liệt kê model đã push/create có tên không quen thuộc
ollama list
Cảnh báo quan trọng: Một vụ rò rỉ heap thành công không để lại artifact rõ ràng trên đĩa ngoài một entry model trỏ đến registry không quen thuộc. Nếu bạn thấy entry như vậy, hãy coi máy chủ đã bị xâm phạm và giả định mọi bí mật mà tiến trình Ollama tiếp cận được giờ đã công khai.
Các Bước Khắc Phục
1. Nâng Cấp Ngay
# Cài đặt native trên Linux / macOS
curl -fsSL https://ollama.com/install.sh | sh
# Xác minh
ollama --version # phải >= 0.17.1
# Docker
docker pull ollama/ollama:latest
docker stop ollama && docker rm ollama
docker run -d -p 127.0.0.1:11434:11434 -v ollama:/root/.ollama --name ollama ollama/ollama:latest
2. Dừng Bind Vào 0.0.0.0
Thay đổi có tác động lớn nhất bạn có thể làm. Nếu bạn chỉ tiêu thụ Ollama từ chính máy đó — đừng phơi nó ra.
# Bind mặc định an toàn
OLLAMA_HOST=127.0.0.1 ollama serve
# Nếu bắt buộc phải phơi ra, bind vào một interface nội bộ cụ thể, không phải 0.0.0.0
OLLAMA_HOST=10.0.0.5 ollama serve
Với người dùng systemd, sửa unit file (/etc/systemd/system/ollama.service):
[Service]
Environment="OLLAMA_HOST=127.0.0.1"
Sau đó systemctl daemon-reload && systemctl restart ollama.
3. Đặt Một Proxy Có Xác Thực Phía Trước
Nếu thực sự cần truy cập từ xa, đừng bao giờ phơi /api/create, /api/blobs, hoặc /api/push ra trực tiếp. Đặt Ollama sau một reverse proxy có nhiệm vụ:
- Yêu cầu API key hoặc mTLS cho mọi request
- Chặn
/api/create,/api/blobs,/api/pushhoàn toàn trừ khi caller nằm trong allowlist admin - Chỉ forward
/api/chat,/api/generate,/api/embeddings,/api/tags
location ~ ^/api/(create|blobs|push) {
# Chặn mọi caller trừ IP admin tin cậy
allow 10.0.0.0/24;
deny all;
}
location /api/ {
auth_request /auth; # xác thực API key
proxy_pass http://127.0.0.1:11434;
}
4. Nếu Đã Bị Phơi Ra — Xoay Vòng Mọi Thứ
Bộ nhớ heap có thể chứa bất cứ thứ gì tiến trình Ollama đã chạm vào. Nếu máy chủ của bạn truy cập được từ internet với phiên bản dính lỗi, hãy giả định đã bị rò rỉ:
- Xoay vòng mọi bí mật mà tiến trình Ollama có thể nhìn thấy:
- Biến môi trường (
OPENAI_API_KEY,ANTHROPIC_API_KEY, key proxy vendor, v.v.) - System prompt chứa hướng dẫn độc quyền hoặc credential nhúng
- Mọi token được mount vào container hoặc environment tiến trình
- Biến môi trường (
- Audit lại các hội thoại gần đây xem có nội dung nhạy cảm mà người dùng khác gửi không — nội dung đó nằm cùng heap
- Kiểm tra log mạng outbound xem có kết nối đến registry model không quen thuộc trong khoảng thời gian phơi nhiễm không
- Cài lại host nếu cùng máy đó chạy workload khác có credential trong bộ nhớ
5. Chặn Nguồn GGUF Không Tin Cậy Đi Tới
Vector tấn công là tạo model từ file GGUF do người dùng cung cấp. Nếu người dùng của bạn không cần tải model tùy ý:
# Chính sách front-end: chỉ cho phép `ollama pull` từ registry.ollama.ai
# Từ chối mọi lời gọi /api/create từ caller không xác thực (xem #3)
Với triển khai multi-tenant, hãy coi mọi file GGUF được tải lên là input không tin cậy — y như cách bạn đối xử với file ZIP hay executable do người dùng tải lên.
Bài Học Quan Trọng
-
unsafetrong Go bỏ qua an toàn bộ nhớ — và bộ parse GGUF dùng nó không kiểm tra ranh giới. Ngôn ngữ memory-safe không còn memory-safe khi bạn opt-out. Mọi đường code dùngunsafe,cgo, hay con trỏ tự chế đều xứng đáng được soi xét như một codebase C thuần. -
Các endpoint dính lỗ hổng (
/api/create,/api/blobs,/api/push) ship không xác thực và đầy quyền lực. Đây là phiên bản hạ tầng AI của việc để hởkubectl proxytrên internet công cộng. Endpoint local-admin mạnh không có lý do gì để mở mặc định. -
OLLAMA_HOST=0.0.0.0là0.0.0.0:6379mới (meme Redis-không-auth ngày xưa). Mọi tutorial “tự host LLM local” ship dòng copy-paste này đã đang dẫn người ta vào một bề mặt tấn công 300.000 máy chủ. -
F16 → F32 là kênh exfiltration ngoài ý muốn. Một phép chuyển đổi số không mất mát nghĩa là kẻ tấn công có thể đưa byte heap rò rỉ đi vòng qua chính pipeline quantization của Ollama mà không bị hỏng. Bất kỳ phép biến đổi dữ liệu “vô hại” nào bảo toàn bit pattern cũng là một primitive buôn lậu khả thi.
-
Quy trình disclosure đã hoạt động, và điều đó đáng được nói thẳng. Báo cáo 2/2, vá xong trước công bố công khai 5/5. Embargo 3 tháng đúng là cách nên làm — nhưng cũng có nghĩa bản vá mới công khai chưa đầy một tuần, và phần lớn instance Ollama tự host không tự động cập nhật.
Bàn Luận Tương Lai
File Model Giờ Là Mã Không Tin Cậy
Một file GGUF không còn là “chỉ có trọng số.” Nó là một binary có cấu trúc, đi qua một parser viết bằng Go unsafe, rồi qua pipeline quantization, rồi qua bộ serializer, rồi qua endpoint push mạng. Đó là một bề mặt tấn công hoàn chỉnh — đúng loại mà ngày xưa ta gán cho image decoder và thư viện ZIP. Khái niệm “file model” cần được đối xử với cùng sự hoài nghi mà ta áp dụng cho bất kỳ binary blob nào do người dùng tải lên.
Hạ Tầng AI Đang Lặp Lại Mọi Sai Lầm Của Web
Service mở-mặc-định, endpoint admin không xác thực, tutorial “cứ bind 0.0.0.0 đi”, parser unsafe — đây là kỷ nguyên bảo mật LAMP-stack 2005 đang diễn ra lại, mười lăm năm sau, trên máy chủ AI. Memcached, MongoDB, Elasticsearch, Redis, Kubernetes dashboard — mỗi cái đều có khoảnh khắc “300.000 instance phơi mình” của riêng nó. Giờ đến lượt Ollama.
Ngôn Ngữ Memory-Safe Không Còn Memory-Safe
Lỗ hổng này nằm trong code Go. Go có GC, có slice kiểm tra ranh giới, có runtime bắt phần lớn lỗi bộ nhớ. Không cái nào giúp được, vì parser dùng unsafe. Rust có lối thoát tương tự, Python có ctypes. Bài học không phải “dùng ngôn ngữ tốt hơn” — mà là mọi khối unsafe cần cường độ review như C thuần, và phần lớn project không làm vậy.
Triển Khai LLM Local Cần Default An Toàn Hơn
Ollama, llama.cpp, vLLM, LM Studio, Text Generation WebUI — phần lớn các công cụ này mặc định hoặc “chỉ 127.0.0.1, nhưng doc lập tức bảo bạn đổi sang 0.0.0.0” hoặc “0.0.0.0 không auth.” Một bước tiến có ý nghĩa sẽ là: bind vào localhost mặc định, yêu cầu flag tường minh --listen-all-interfaces-i-understand-the-risk, và ship sẵn cơ chế API key. Trừ khi điều đó trở thành chuẩn, mọi dự án LLM-server mới sẽ phát minh lại CVE này.
Tham Khảo
- Cyera Research: Bleeding Llama — Critical Unauthenticated Memory Leak in Ollama
- Mục CVE-2026-7482 trên cvefeed.io
- The Hacker News: Ollama Out-of-Bounds Read Vulnerability Allows Remote Process Memory Leak
- SecurityWeek: Critical Bug Could Expose 300,000 Ollama Deployments to Information Theft
- CSO Online: Ollama vulnerability highlights danger of AI frameworks with unrestricted access
- runZero: Ollama vulnerability CVE-2026-7482 — Find impacted assets
- lilting.ch: Ollama CVE-2026-7482 — crafted GGUF leaks heap memory
- Phiên bản đã vá: Ollama 0.17.1 (release notes)
Bai viet lien quan
- Khi Malware Gọi Lên Cloud Xin Chỉ Thị — Case Study Về Tấn Công Mạng Bằng AI
- Axios Bị Chiếm Quyền Trên npm — RAT Ẩn Trong Thư Viện HTTP Client Phổ Biến Nhất
- Giải Phẫu Cuộc Tấn Công Chuỗi Cung Ứng LiteLLM — Khi Công Cụ Bảo Mật Trở Thành Vũ Khí
- Claude Code vs OpenClaw vs NemoClaw — AI Agent Nào Phù Hợp Với Bạn?
- Chạy vLLM Trên Tesla V100 — Bắt Silicon Cũ Phục Vụ LLM Hiện Đại