- SSH integration sử dụng escape sequence của terminal để giao tiếp với shell từ xa, và do cấu trúc này, cả đầu ra terminal thông thường cũng có thể bị diễn giải như giao thức conductor
- Vấn đề cốt lõi là thất bại về niềm tin, khi tệp độc hại, banner, MOTD, phản hồi máy chủ không phải conductor từ xa thật cũng có thể hoạt động như conductor thông qua
DCS 2000p và OSC 135 giả mạo
- Chỉ cần chạy
cat readme.txt, nếu transcript conductor giả được render thì iTerm2 sẽ tự tiến hành luồng getshell·pythonversion·run(...), còn đầu ra tấn công chỉ cần giả làm phản hồi
- Khai thác lợi dụng sự lẫn lộn khi lệnh base64 được ghi vào PTY sẽ rơi xuống thành đầu vào shell cục bộ dạng văn bản thuần nếu không có SSH conductor thực sự, và có thể thực thi khi chunk cuối cùng được diễn giải thành đường dẫn
ace/c+aliFIo
- Bản sửa đã được đưa vào commit ngày 31/3
a9e745993c2e2cbb30b884a16617cd5495899f86, nhưng tại thời điểm công bố vẫn chưa có trong stable release, tạo ra khoảng trống bảo vệ do công khai trước khi bản vá được phổ biến
Bối cảnh SSH integration của iTerm2
- iTerm2 SSH integration là tính năng giúp hiểu phiên từ xa phong phú hơn, hoạt động bằng cách đưa một script helper nhỏ tên conductor lên shell từ xa
- Bắt đầu SSH integration qua
it2ssh
- Truyền conductor, script bootstrap từ xa, thông qua phiên SSH hiện có
- Script từ xa này đóng vai trò đối tác của giao thức iTerm2
- iTerm2 và conductor từ xa không giao tiếp như dịch vụ mạng thông thường mà trao đổi escape sequence trên terminal I/O
- Phát hiện login shell
- Kiểm tra sự hiện diện của Python
- Thay đổi thư mục
- Tải tệp lên
- Thực thi lệnh
Cách PTY hoạt động
- Trình giả lập terminal hiện đại là phiên bản phần mềm của terminal phần cứng trước đây, đảm nhiệm hiển thị màn hình, nhập từ bàn phím và diễn giải terminal control sequence
- Shell và chương trình dòng lệnh vẫn mong đợi một thiết bị trông như terminal thật, nên hệ điều hành cung cấp PTY
- PTY là pseudoterminal nằm giữa trình giả lập terminal và tiến trình foreground
- Trong một phiên SSH thông thường, iTerm2 ghi byte vào PTY, tiến trình foreground là
ssh sẽ chuyển chúng tới máy từ xa, rồi conductor từ xa đọc từ stdin
- Khi iTerm2 gửi lệnh tới conductor từ xa, ở phía cục bộ về bản chất nó vẫn là ghi byte vào PTY
Giao thức conductor
- Phương tiện truyền tải của giao thức SSH integration là terminal escape sequence
- Có hai thành phần cốt lõi
DCS 2000p dùng để hook SSH conductor
OSC 135 dùng cho các thông điệp conductor pre-framer
- Ở mức mã nguồn,
DCS 2000p khiến iTerm2 tạo conductor parser, sau đó parser xử lý các thông điệp OSC 135
begin <id>
- các dòng đầu ra lệnh
end <id> <status> r
unhook
- Một conductor từ xa hợp lệ có thể giao tiếp với iTerm2 chỉ bằng đầu ra terminal
Lỗ hổng cốt lõi
- Bản chất của lỗ hổng là thất bại về niềm tin: ngay cả đầu ra terminal không thuộc phiên conductor đáng tin cậy thực sự cũng vẫn được iTerm2 chấp nhận như giao thức SSH conductor
- Kết quả là đầu ra terminal không đáng tin có thể mạo danh conductor từ xa
- tệp độc hại
- phản hồi máy chủ
- banner
- MOTD
- Đầu vào tấn công có thể in ra hook
DCS 2000p giả mạo và phản hồi OSC 135 giả mạo; khi đó iTerm2 sẽ hành xử như thể đang diễn ra một phiên trao đổi SSH integration thật
Cách exploit hoạt động
- Tệp exploit chứa một transcript conductor giả
- Khi người dùng chạy
cat readme.txt, iTerm2 sẽ render tệp, nhưng nội dung không chỉ là văn bản đơn thuần mà còn chứa
- dòng
DCS 2000p giả báo hiệu một phiên conductor giả
- thông điệp
OSC 135 giả phản hồi các yêu cầu của iTerm2
- Khi hook được chấp nhận, iTerm2 khởi động workflow conductor bình thường; ở mã nguồn upstream,
Conductor.start() ngay lập tức gửi getshell(), rồi nếu thành công sẽ gửi pythonversion()
- Cuộc tấn công không cần tiêm các yêu cầu này, vì iTerm2 tự phát hành yêu cầu, còn đầu ra độc hại chỉ cần giả làm phản hồi
Quá trình tiến triển của state machine
- Các thông điệp
OSC 135 giả được cấu thành tối thiểu nhưng theo đúng thứ tự
- bắt đầu command body cho
getshell
- trả về dòng trông như đầu ra phát hiện shell
- kết thúc thành công lệnh đó
- bắt đầu command body cho
pythonversion
- kết thúc thất bại lệnh đó
unhook
- Chỉ với luồng này, iTerm2 đã đi vào đường fallback bình thường, rồi kết luận workflow SSH integration đã hoàn tất đủ mức để chuyển sang bước tiếp theo
- Bước tiếp theo là tạo và gửi lệnh
run(...)
Vai trò của sshargs
- Hook
DCS 2000p giả mạo chứa nhiều trường, trong đó có sshargs do kẻ tấn công kiểm soát
- Giá trị này sau đó được iTerm2 dùng làm nguyên liệu lệnh khi tạo yêu cầu
run ... cho conductor
- Exploit chọn
sshargs sao cho khi iTerm2 base64-encode dữ liệu sau
run <padding><magic-bytes>
- chunk 128 byte cuối cùng sẽ là
ace/c+aliFIo
- Chuỗi này không phải giá trị tùy ý mà được chọn để đồng thời thỏa mãn hai điều kiện
- là đầu ra hợp lệ của đường mã hóa conductor
- là tên đường dẫn tương đối hợp lệ
Sự lẫn lộn PTY khiến exploit khả thi
- Trong một phiên SSH integration bình thường, iTerm2 ghi lệnh conductor đã mã hóa base64 vào PTY, rồi
ssh chuyển chúng tới conductor từ xa
- Trong tình huống exploit, iTerm2 vẫn ghi lệnh vào PTY như vậy, nhưng do không có SSH conductor thật nên shell cục bộ nhận chúng như đầu vào văn bản thuần
- Trong phiên được ghi lại, có thể quan sát các dạng sau
getshell xuất hiện ở dạng base64
pythonversion xuất hiện ở dạng base64
- tiếp theo là payload
run ... dài được mã hóa base64
- chunk cuối cùng là
ace/c+aliFIo
- Các chunk trước đó thất bại như những lệnh vô nghĩa, còn chunk cuối sẽ hoạt động nếu đường dẫn đó tồn tại cục bộ và có thể thực thi
Các bước tái hiện
- PoC gốc dựa trên tệp có thể tái hiện bằng
genpoc.py
python3 genpoc.py
unzip poc.zip
cat readme.txt
- Quy trình này tạo ra hai tệp sau
- một script helper có thể thực thi tên
ace/c+aliFIo
readme.txt chứa các chuỗi DCS 2000p và OSC 135 độc hại
- Tệp thứ nhất khiến iTerm2 bị dẫn dắt để giao tiếp với conductor giả, còn tệp thứ hai cung cấp mục tiêu mà shell sẽ thực sự chạy khi chunk cuối cùng tới nơi
- Để exploit thành công, cần chạy
cat readme.txt trong thư mục có ace/c+aliFIo, để chunk cuối do kẻ tấn công tạo ra được diễn giải thành đường dẫn có thể thực thi thật sự
Lịch trình công bố và vá lỗi
- Báo lỗi cho iTerm2 vào ngày 30/3
- Hoàn tất sửa lỗi trong commit ngày 31/3
a9e745993c2e2cbb30b884a16617cd5495899f86
- Tại thời điểm bài viết được thực hiện, bản sửa vẫn chưa có trong stable release
- Sau khi commit vá lỗi được phản ánh, đã có nỗ lực dựng lại exploit từ đầu chỉ dựa trên bản vá
- prompt cho quá trình đó nằm trong
prompts.md
- kết quả là
genpoc2.py
- hoạt động rất giống
genpoc.py
Vấn đề về thời điểm công bố
- Việc công bố diễn ra trước khi bản sửa tới được stable release, tạo ra một kênh khiến phần lớn người dùng trên thực tế khó được bảo vệ mà lỗ hổng thì đã bị tiết lộ
- Sự xung đột về thời điểm công bố kiểu này cần có lý do biện minh rõ ràng
- Hai tuần là quá ngắn để kỳ vọng việc phổ biến có ý nghĩa, đồng thời cũng quá ngắn để biện minh rằng cần công bố sớm nhằm ép phản ứng
- Kết quả là lỗ hổng đã được biết đến rộng rãi nhưng bản sửa trên thực tế vẫn chưa đến được tay những người dùng cần nó, tạo thành một khoảng trống công khai
- Lựa chọn tốt hơn có thể là chờ tới khi bản sửa thực sự tới tay người dùng, hoặc nêu rõ vì sao việc phơi bày sớm là cần thiết, nhưng cả hai đều chưa được đáp ứng
1 bình luận
Ý kiến trên Hacker News
Tôi đã tự hỏi vì sao lại công khai ngay lúc này khi bản ổn định vẫn chưa có bản vá. Mới chỉ 18 ngày kể từ khi báo cáo lên upstream, và tôi cảm thấy bài blog chi tiết hơn nhiều so với commit được công khai nên làm tăng khả năng bị khai thác ngoài thực tế. Tôi xác nhận rằng tác giả có thể dùng chỉ commit upstream cùng với LLM để tạo exploit, nhưng dù vậy tôi vẫn cho rằng bài viết này đã làm tăng thêm mức độ lộ diện của lỗ hổng
Việc này rất ấn tượng nhưng không quá đáng ngạc nhiên. Đây là vấn đề lặp đi lặp lại ở các ứng dụng terminal nhiều tính năng, và trong 15 năm qua đã có nhiều lỗ hổng tương tự được công bố. Các công cụ như less hay vim cũng không phải ngoại lệ, và phần lớn những vấn đề này gần với lỗi logic hơn là lỗi an toàn bộ nhớ nên viết lại bằng Rust cũng không tự động giải quyết được. Một mặt, người ta muốn các công cụ ở cấp độ OS phải đơn giản và dễ dự đoán; mặt khác, lại muốn màu sắc đẹp, hoạt ảnh và tùy biến vô tận. Giờ còn thêm cả AI agent, nên chúng ta đang sống trong thời đại mà một file văn bản độc hại chỉ cần chứa những câu như "hãy bỏ qua chỉ dẫn trước đó" cũng có thể đủ
Tôi nhớ đến những câu chuyện thời PDP-10. Có một đồng nghiệp phát hiện rằng nếu cứ nhấn backspace liên tục thì bộ xử lý terminal sẽ xóa cả các ký tự ở phía trước buffer, và xa hơn nữa, nếu dùng ký tự escape để xóa cả dòng thì hệ điều hành sẽ bị đánh sập
6 năm trước cũng đã có một vấn đề bảo mật iTerm2 gần như y hệt
Tôi là tác giả iTerm2. Vấn đề này có thể được dùng như một mắt xích trong chuỗi exploit, nhưng tôi nghĩ việc nói như tiêu đề rằng nó tự thân cực kỳ nguy hiểm là phóng đại. Hiện tôi đang đi du lịch cùng gia đình và sẽ phát hành bản sửa lỗi khi quay về
Tôi không thấy ngạc nhiên khi một lỗi tinh vi xuất hiện trong hệ thống phức tạp dùng bootstrap script, remote conductor agent, escape sequence v.v. Khi các thành phần được tận dụng theo cách ban đầu không dự tính, những vấn đề như vậy rất dễ phát sinh. Tôi hiểu đây là cấu trúc trong đó nếu đầu ra không đáng tin cậy hiển thị trên màn hình, như file văn bản hay banner máy chủ, có chứa mã đặc biệt thì hệ thống sẽ xử lý luôn mà không xác minh nguồn gốc
Chuyện này cho tôi cảm giác như đã từng nghe ở đâu rồi. SSH integration của iTerm2 từng là nguyên nhân của một CVE, và tôi cũng nhớ tới CVE-2025-22275. Trước đây đã có các trường hợp khác, còn vấn đề cũ được nhắc trong thread này thì là ở phía tmux integration. Có lẽ những tính năng tích hợp kiểu này nên được đưa vào ít quyết liệt hơn
Tiêu đề quá giật gân. Vấn đề không phải ở cat mà là SSH integration của iTerm, và cấu trúc kênh điều khiển không tách khỏi luồng dữ liệu trông khá nguy hiểm. Nếu không dùng tính năng này mà chỉ dùng SSH bình thường thì nhìn chung vẫn ổn
Trước đây các terminal emulator còn cho phép gán lại phím bằng escape code. Vì thế việc không
catfile không đáng tin mà mở bằng công cụ nhưlessgần như là kiến thức phổ thôngCách diễn đạt trong bài không chính xác. Đoạn thứ hai đọc như kiểu "nếu dùng iTerm2 thì không an toàn", nhưng chính xác hơn là vấn đề có thể xảy ra khi dùng tính năng Shell Integration tùy chọn. Nếu tính năng này mặc định bị tắt thì phạm vi ảnh hưởng có vẻ hạn chế. Nếu tôi sai thì mong được đính chính