Lỗ hổng Telnet 32 năm tuổi: Khi GNU inetutils Telnetd phơi bày lỗi tồn tại từ năm 1994
Một lỗ hổng tràn bộ đệm trong GNU inetutils Telnetd (CVE-2026-32746) đã tồn tại suốt 32 năm, ảnh hưởng đến hàng loạt hệ điều hành và thiết bị nhúng. Dù khó khai thác để đạt RCE hoàn chỉnh, lỗ hổng vẫn mở ra các nguyên thủy tấn công nguy hiểm như arbitrary free và rò rỉ con trỏ heap.

Lỗ hổng Telnet 32 năm tuổi: Khi GNU inetutils Telnetd phơi bày lỗi tồn tại từ năm 1994
Một lỗ hổng tràn bộ đệm trong GNU inetutils Telnetd vừa được công bố với mã CVE-2026-32746, nhưng điều đáng chú ý là nó đã tồn tại từ năm 1994 — tức là đã 32 năm. Lỗi nằm trong trình xử lý thương lượng LINEMODE SLC, ảnh hưởng đến hầu hết các bản phân phối Linux lớn và nhiều hệ điều hành khác. Dù chưa có khai thác RCE hoàn chỉnh, lỗ hổng vẫn tạo ra những nguyên thủy tấn công đáng lo ngại.
Chuyện gì đang xảy ra với Telnet?
Nếu bạn chưa quen với Telnet, đây là một giao thức mạng cung cấp giao diện dòng lệnh để giao tiếp với máy chủ từ xa qua TCP/IP. Nói cách khác, nó giống như "dịch vụ thực thi mã từ xa" vậy.
Điểm đáng lo ngại là Telnet hoạt động trên văn bản thuần (plaintext), nghĩa là tên đăng nhập và mật khẩu của bạn được truyền qua mạng mà không hề được mã hóa. Ngày nay, SSH đã thay thế Telnet trong hầu hết các trường hợp, nhưng Telnet vẫn tồn tại dai dẳng trên nhiều hệ thống sản xuất.
Sơ đồ minh họa giao thức Telnet
CVE-2026-32746 nguy hiểm đến mức nào?
Được phát hiện bởi DREAM Security Research Team, CVE-2026-32746 là một lỗi tràn bộ đệm dựa trên BSS, cho phép kẻ tấn công ghi đè khoảng 400 byte các biến liền kề.
Lỗ hổng nằm trong trình xử lý thương lượng LINEMODE SLC (Set Linemode Characters). Ban đầu tưởng chừng chỉ ảnh hưởng đến GNU inetutils, nhưng thực tế phần lớn các nhà cung cấp đều dựa trên cùng đoạn mã này, khiến phạm vi ảnh hưởng cực kỳ rộng và khó ước lượng chính xác.
Danh sách các hệ thống bị ảnh hưởng bao gồm:
- inetutils-telnetd gốc
- Ubuntu
- Debian
- FreeBSD 13 / FreeBSD 15 Port
- NetBSD 10.1
- Citrix NetScaler
- Apple Mac Tahoe
- Haiku
- TrueNAS Core
- uCLinux
- libmtev
- DragonFlyBSD
Tại sao năm 2026 mà vẫn còn dùng Telnet?
Đây là câu hỏi mà nhiều người đặt ra. Câu trả lời khá đơn giản: Telnet vẫn hiện diện trên hệ thống sản xuất vì nhiều lý do khác nhau.
Có thể đó là giao thức duy nhất mà nhà cung cấp hỗ trợ — chẳng hạn một máy CNC có chi phí ngừng hoạt động lên tới hàng nghìn đô mỗi phút, và nó chạy trên vi điều khiển 8-bit. Bạn không thể nhét một SSH client vào đó.
Hoặc có thể có lý do kỹ thuật sâu xa khiến việc chuyển đổi là bất khả thi. Dù sao đi nữa, Telnet vẫn hiện diện trong kho của mọi bản phân phối lớn — minh chứng cho sức sống bền bỉ của nó.
Lỗ hổng nằm ở đâu trong giao thức Telnet?
Nhiều người lầm tưởng Telnet chỉ đơn thuần là một luồng TCP kết nối tới shell. Thực tế không phải vậy — Telnet hỗ trợ nhiều tính năng phức tạp như điều khiển terminal, thương lượng kích thước cửa sổ client, xác thực, thậm chí cả mã hóa.
Lỗ hổng này nằm trong tính năng LINEMODE của giao thức, được định nghĩa trong RFC 1184:
Khi ở chế độ Linemode với tính năng chỉnh sửa được bật ở phía cục bộ, lưu lượng mạng giảm xuống chỉ còn vài gói mỗi dòng lệnh, thay vì vài gói mỗi ký tự gõ vào. Điều này rất hữu ích cho các mạng có độ trễ cao.
Đúng vậy, lỗ hổng này cũ đến mức nó có từ thời mà các mạng còn tính phí theo từng gói tin.
Trình thương lượng SLC và lỗi thiếu kiểm tra biên
Trong quá trình thương lượng kết nối, máy chủ Telnet sẽ gửi một loạt bộ ba byte (triplet), mỗi bộ chỉ định một ký tự đặc biệt cần thay thế, mức hỗ trợ, và giá trị ký tự thực tế. Client có thể phản hồi bằng danh sách triplet mới.
Đây chính là điểm mấu chốt:
if ((*slcptr++ = (unsigned char) func) == 0xff)
*slcptr++ = 0xff;
if ((*slcptr++ = (unsigned char) flag) == 0xff)
*slcptr++ = 0xff;
if ((*slcptr++ = (unsigned char) val) == 0xff)
*slcptr++ = 0xff;
Máy chủ lưu tất cả các giá trị này vào một mảng toàn cục có kích thước cố định mà không hề kiểm tra biên. Đó chính là lỗ hổng — tồn tại âm thầm suốt từ năm 1994.
Minh họa tràn bộ đệm trong Telnetd
Lịch sử "lặp lại có vần điệu"
Điều thú vị là vào năm 2005, lỗ hổng CVE-2005-0469 đã xuất hiện với bản chất hoàn toàn giống hệt — nhưng ở phía client thay vì server, trong hàm slc_add_reply thiếu kiểm tra biên. Bản vá cho lỗi năm 2005 giống hệt bản vá cho lỗ hổng hiện tại.
Phải mất hai mươi năm sau, ai đó mới nghĩ đến việc kiểm tra phía server xem có lỗ hổng tương tự hay không.
Khai thác: Con đường đầy chông gai
Dù có thể tràn biến toàn cục với dữ liệu do mình kiểm soát, việc khai thác thực tế lại vô cùng phức tạp. Dữ liệu gửi đến phải tuân theo nhiều ràng buộc nghiêm ngặt:
- Byte
funclớn hơn hằng số NSLC (0x1e) sẽ bị loại bỏ - Nếu
funcbằng 0, triplet cũng không vào được buffer - Hàm
change_slctiếp tục biến đổi giá trị đầu vào - Mỗi byte 0xff bị nhân đôi thành 0xff 0xff, khiến không thể chèn số lượng byte 0xff lẻ liên tiếp
Trên hệ thống x86 64-bit, các con trỏ thường có nhiều byte NULL liên tiếp (ví dụ 0x0000000802215180). Để ghi đè hoàn toàn một con trỏ, ta cần viết 3 byte NULL liên tiếp — điều gần như không thể. Vì thế, cách duy nhất là ghi đè một phần (partial overwrite) khi nhắm vào kiến trúc little-endian.
Kết quả phân tích dịch ngược mã Telnetd
Bước ngoặt trên Debian 32-bit
Nhóm nghiên cứu chuyển sang thử nghiệm trên Debian bookworm 32-bit — phiên bản cũ nhưng mới nhất còn hỗ trợ môi trường 32-bit x86, vì Debian đã ngừng hỗ trợ kiến trúc này từ lâu.
Tại đây, họ phát hiện biến def_slcbuf — một con trỏ được cấp phát qua malloc khi quá trình khởi tạo terminal chưa hoàn tất. Khi terminit chưa được thiết lập, các triplet SLC nhận được sẽ không được xử lý ngay, mà được sao chép vào def_slcbuf. Sau đó, khi terminal khởi tạo xong, hàm deferslc mới thực sự xử lý chúng và giải phóng def_slcbuf bằng free.
Vì ta kiểm soát được def_slcbuf thông qua các triplet SLC ghi đè, ta có thể khiến free được gọi trên bất kỳ vị trí bộ nhớ nào — một nguyên thủy cực kỳ mạnh mẽ, thường được gọi là arbitrary free.
Trên các hệ thống nhúng nhẹ, điều này có thể nhanh chóng dẫn đến RCE thông qua ghi tùy ý (arbitrary write). Trên Debian, heap có nhiều kiểm tra hơn nên việc khai thác khó khăn hơn — nhưng vẫn là một bước tiến đáng kể.
Phát hiện lỗ hổng như thế nào?
Vì bản vá xử lý tràn bộ đệm theo cách tối giản — âm thầm bỏ qua dữ liệu vượt quá kích thước slcbuf mà không phản hồi lỗi — việc phát hiện không hề đơn giản.
Tuy nhiên, máy chủ Telnet sẽ gửi lại danh sách SLC của mình cho client sau khi nhận dữ liệu SLC. Kẻ tấn công có thể gửi dữ liệu rác để lấp đầy buffer, sau đó gửi một giá trị bất thường:
- Máy chủ có lỗ hổng sẽ lưu giá trị bất thường đó, dù buffer đã tràn
- Máy chủ đã vá sẽ âm thầm loại bỏ nó
Nếu ta thấy giá trị bất thường xuất hiện trong phản hồi, mục tiêu đang bị ảnh hưởng.
Nhóm watchTowr Labs đã phát hành Detection Artifact Generator cho phép kiểm tra lỗ hổng này, bao gồm cả chế độ probe mode chỉ kết nối và kiểm tra xem tính năng LINEMODE có được quảng bá hay không, mà không gửi bất cứ nỗ lực tràn bộ đệm nào.
Patch ngay, nhưng vá bằng cách nào?
Đây là vấn đề nhức nhối: dự án inetutils vẫn chưa phát hành phiên bản đã vá chính thức. Phiên bản mới nhất có thể tải về — 2.7 — vẫn còn lỗ hổng. Người dùng phải tự clone commit đã sửa từ git và build từ source.
Hầu hết các bản phân phối Linux vẫn chưa phát hành gói cập nhật. Tại thời điểm công bố, chỉ có nhánh sid/forky của Debian chứa bản vá — mọi bản phát hành Debian khác vẫn bị ảnh hưởng.
Góc nhìn cho người dùng Việt Nam
Với các doanh nghiệp Việt Nam đang vận hành hệ thống SCADA, máy CNC, thiết bị công nghiệp hoặc thiết bị mạng cũ có sử dụng Telnet, đây là lời cảnh báo đáng lưu tâm. Nhiều thiết bị nhúng trong các nhà máy, hệ thống giám sát công nghiệp tại Việt Nam vẫn sử dụng Telnet do yêu cầu tương thích với nhà cung cấp.
Khuyến nghị cụ thể:
- Kiểm tra ngay xem hệ thống có dịch vụ Telnet đang mở không
- Hạn chế truy cập Telnet từ Internet, chỉ cho phép từ mạng nội bộ tin cậy
- Theo dõi thông báo từ nhà cung cấp và các bản phân phối Linux
- Xem xét chuyển đổi sang SSH nếu thiết bị hỗ trợ
- Sử dụng Detection Artifact Generator của watchTowr Labs để đánh giá mức độ phơi nhiễm
Đây là ví dụ điển hình cho thấy một lựa chọn tưởng như vô hại của trình biên dịch từ nhiều năm trước có thể biến một lỗ hổng từ "khó khai thác" thành "arbitrary free" — đẩy nó tiến gần hơn đến khả năng RCE hoàn chỉnh.
Kết luận của nhóm nghiên cứu: dù chưa đạt được RCE trọn vẹn, họ đã khám phá ra nhiều hành vi bất thường nguy hiểm. Điều đáng chú ý nhất là phạm vi ảnh hưởng khổng lồ của lỗ hổng này — nó đã len lỏi vào mọi ngóc ngách của các hệ thống mạng trong suốt hơn ba thập kỷ. Các chuyên gia dự đoán những trường hợp nhiễm lỗ hổng này sẽ còn xuất hiện trong nhiều năm tới.


