Không còn những ‘Ngày thứ Sáu xanh’ nữa
(brendangregg.com)- Sự cố Windows toàn cầu ngày 19/7/2024 là một trường hợp trong đó bản cập nhật trình điều khiển kernel của một sản phẩm bảo mật dẫn đến đọc bộ nhớ sai và gây ra màn hình xanh cùng vòng lặp khởi động
- eBPF chạy trong kernel, nhưng dùng trình xác minh và sandbox để từ chối mã nguy hiểm, nên được thiết kế để một chương trình không thể làm sập toàn bộ hệ thống
- Linux đã có sẵn eBPF, và khi eBPF for Windows của Microsoft đạt trạng thái sẵn sàng cho production, phần mềm bảo mật trên Windows cũng có thể được chuyển sang theo cùng cách đó
- Các công ty công nghệ lớn như Google, Meta, Cisco và các startup bảo mật dựa trên eBPF đang mở rộng sản phẩm bảo mật và hệ thống phát hiện nhờ tận dụng tốc độ, khả năng quan sát sâu và các đảm bảo an toàn
- Doanh nghiệp mua phần mềm thương mại có chứa trình điều khiển kernel hoặc mô-đun kernel có thể biến hỗ trợ eBPF thành yêu cầu đối với nhà cung cấp: trên Linux là ngay bây giờ, và trên Windows là trong thời gian tới
Rủi ro của mã kernel mà sự cố Windows ngày 19/7 đã phơi bày
- Sự cố ngày 19/7/2024 là một ví dụ chưa từng có cho thấy những rủi ro cố hữu của lập trình kernel
- Các máy tính Windows trên toàn thế giới đã gặp màn hình xanh (blue screen of death) và vòng lặp khởi động, gây gián đoạn cho bệnh viện, hãng hàng không, ngân hàng, cửa hàng tạp hóa, đài phát thanh và nhiều nơi khác
- Nguyên nhân là một bản cập nhật cấu hình (config update) của một sản phẩm bảo mật được dùng rộng rãi; sản phẩm này có kèm trình điều khiển kernel cho hệ thống Windows
- Sau bản cập nhật, trình điều khiển kernel đã cố đọc nhầm vùng nhớ, và kiểu lỗi này có thể làm kernel bị crash
Những crash mà eBPF có thể ngăn chặn
- eBPF không còn chỉ là một chữ viết tắt nữa, mà là một môi trường thực thi kernel an toàn tương tự runtime JavaScript an toàn được tích hợp trong trình duyệt web
- Người dùng Linux nhiều khả năng đã có sẵn eBPF trong hệ thống, vì eBPF đã được tích hợp vào Linux kernel từ vài năm trước
- Chương trình eBPF bị giới hạn để không thể làm sập toàn bộ hệ thống
- Trình xác minh (verifier) của phần mềm sẽ kiểm tra độ an toàn
- Chương trình về thực chất chạy trong sandbox
- Nếu trình xác minh phát hiện mã không an toàn, chương trình sẽ bị từ chối và không được thực thi
- Trình xác minh trong triển khai Linux gồm hơn 20.000 dòng mã, với đóng góp từ phía công nghiệp như Meta, Isovalent, Google và giới học thuật như Rutgers University, University of Washington
- Bảo mật tăng cường, mức sử dụng tài nguyên thấp và khả năng ngăn crash là những ưu điểm cốt lõi của eBPF
Khả năng áp dụng trên Linux và Windows
- Công ty bảo mật gây ra sự cố lần này đã ở trong quá trình áp dụng eBPF trên các hệ thống Linux
- Khi eBPF support for Windows của Microsoft đạt mức sẵn sàng cho production, phần mềm bảo mật Windows cũng có thể được port sang eBPF
- Tác nhân bảo mật Windows sau khi chuyển sang eBPF sẽ ở dạng không thể gây crash kernel Windows
Việc áp dụng của ngành bảo mật và các công ty công nghệ lớn
- Các startup bảo mật dựa trên eBPF như Oligo và Uptycs đã nhân sự cố gần đây để nhấn mạnh lợi ích của việc chuyển sang eBPF
- Các công ty công nghệ lớn cũng đang áp dụng eBPF cho mục đích bảo mật
- Cisco đã mua lại startup eBPF Isovalent và công bố Cisco Hypershield, một fabric dành cho thực thi và giám sát bảo mật
- Google và Meta đang phát hiện và chặn hành vi độc hại ở quy mô lớn dựa trên tốc độ, khả năng quan sát sâu và các đảm bảo an toàn của eBPF
- Ngoài bảo mật, eBPF còn được dùng cho networking và observability
Giới hạn của eBPF và các biện pháp bổ sung trong vận hành
- Điều tệ nhất mà một chương trình eBPF có thể làm là tiêu tốn tài nguyên ở mức không mong muốn như chu kỳ CPU hoặc bộ nhớ
- Dù không ngăn được cả những đoạn mã lãng phí, nó vẫn chặn được các vấn đề nghiêm trọng dẫn đến crash hệ thống
- eBPF cũng là công nghệ mới nên trong mã quản lý từng có lỗi; đã từng có trường hợp Linux kernel panic được phát hiện bởi chính công ty bảo mật từng xuất hiện trong tin tức gần đây
- Khi các lỗi như vậy được sửa trong eBPF, bản sửa có thể áp dụng cho mọi nhà cung cấp eBPF, từ đó cải thiện bảo mật tổng thể nhanh hơn
- Rủi ro khi triển khai không chỉ dừng lại ở eBPF; vẫn còn các kỹ thuật vận hành có thể dùng kèm
- Canary test
- Rollout theo từng giai đoạn
- Các thực hành kỹ thuật khả năng phục hồi nói chung
Những thay đổi mà bên mua có thể yêu cầu
- Điểm quan trọng của cách tiếp cận eBPF là đây là giải pháp phần mềm sẽ được cung cấp sẵn ở cả Linux kernel và Windows kernel, đồng thời đã được áp dụng cho chính trường hợp sử dụng này
- Nếu doanh nghiệp đang trả tiền cho phần mềm thương mại có chứa trình điều khiển kernel hoặc mô-đun kernel, họ có thể biến eBPF thành một yêu cầu bắt buộc
- Trên Linux điều đó đã làm được ngay hôm nay, còn trên Windows sẽ sớm khả thi
- Một số nhà cung cấp đã chủ động áp dụng eBPF, nhưng với những nhà cung cấp khác có thể vẫn cần áp lực yêu cầu từ phía khách hàng trả tiền
1 bình luận
Ý kiến trên Hacker News
Nhìn vào danh sách “hook” mà eBPF cho Windows cung cấp thì có vẻ khá xa rời thực tế. Hiện tại chỉ ở mức gói tin đến và thao tác socket, tức là Microsoft dường như kỳ vọng Berkeley Packet Filter được dùng đúng theo nghĩa đen là lọc gói tin
Điều này khác với lọc I/O, tạo/sử dụng đối tượng, và vô số điểm mà các driver như CrowdStrike gắn vào kernel NT
Ngoài ra, để giám sát những thứ rác rưởi bên thứ ba khác chạy trong không gian kernel, anti-malware cũng phải nằm trong kernel. ELAM (early-launch anti-malware) tải driver anti-malware trước để nó giám sát hành vi của các driver khác, nhưng rất đáng nghi liệu eBPF có thể làm được việc như vậy hay không
Microsoft còn một chặng đường rất dài nếu muốn thay thế driver anti-malware trong không gian kernel bằng eBPF
https://microsoft.github.io/ebpf-for-windows/ebpf__structs_8...
Ví von thì giống như mọi người dùng website JavaScript trên Google Chrome để giao dịch ngân hàng, còn trên Microsoft Edge lại hiện “chúng tôi không hỗ trợ JavaScript, hãy tải file .EXE này về và chạy”. Câu hỏi gần với “khi nào” Microsoft sẽ hỗ trợ JavaScript hay eBPF hơn là “liệu” họ có hỗ trợ hay không
Tôi không muốn tranh luận với những người như Brendan Gregg, nhưng mong các vendor trong lĩnh vực này điều tra toàn bộ chuỗi sự cố một cách tổng hợp hơn. Khi một đề xuất xuất hiện 3 ngày sau sự cố, nói rằng “x sẽ giải quyết vấn đề đã xảy ra vào ngày y”, tôi sẽ thận trọng
Có thể đúng, nhưng nếu không phân tích thì vẫn có thể còn điểm mù, và cũng có thể có nhiều phương án thay thế cần được xem xét rồi loại bỏ một cách phù hợp
Đặc biệt, tôi khó đồng ý với phần “kết quả tiêu cực tệ nhất chỉ là lãng phí CPU”. Với một số nhóm lỗi nhất định thì có thể vậy, nhưng có đủ nhiều chế độ lỗi trong đó một bộ quy tắc sai có thể khiến hệ thống bị brick nghiêm trọng và khó khôi phục
Điều đó không có nghĩa mô-đun bảo mật dựa trên eBPF không thể là lựa chọn đúng cho nhiều vendor; ý tôi là cần hiểu nó tránh được rủi ro nào, không tránh được rủi ro nào, và xử lý phần nào trong chuỗi sự cố
https://opensource.microsoft.com/blog/2021/05/10/making-ebpf...
https://lwn.net/Articles/857215/
Nếu thật sự có lo ngại, cũng có các kênh thảo luận để góp ý, và chúng được tổng hợp trên GitHub
https://github.com/microsoft/ebpf-for-windows
Có thể đã có câu trả lời rồi, còn nếu chưa thì có thể xử lý ở đó
Điều này không đúng. Nếu cấu trúc là hệ thống chỉ chạy khi có một đoạn mã nào đó, thì khi đoạn mã đó hỏng, hệ thống phải hoàn toàn không chạy. Việc bỏ qua lỗi là kỳ lạ
Ví dụ, nếu mã driver của một thiết bị y tế nào đó bảo đảm khóa an toàn để không làm cháy người, thì tôi sẽ chọn để toàn bộ hệ thống dừng lại hơn là để nó hoạt động như không có gì xảy ra trong khi cơ chế an toàn bị tắt
Cuối cùng, dù đi xuống các lớp bên dưới thì vẫn là cùng một vấn đề
Tôi không biết Linux thực tế làm thế nào, nhưng ta cũng có thể hình dung một thế giới nơi hành vi với đầu vào sai có thể cấu hình được
Ngoài ra, câu đó không phải lúc nào cũng đúng. Trong trường hợp chung thì tôi đồng ý, nhưng trong một số ngữ cảnh hệ thống vẫn phải tiếp tục chạy. Ví dụ hiện ra ngay là máy tính dẫn đường của tàu đổ bộ sao Hỏa tự động. Độ trễ khứ hồi với Trái Đất quá lớn nên không thể đẩy trách nhiệm đi nơi khác
Nếu tắt thì sẽ rơi, nhưng nếu cố hết sức trong trạng thái bị hỏng thì có lẽ cũng chỉ rơi thôi, nên phương án đó có thể tốt hơn
Nếu cả hệ điều hành bị biến thành cục gạch thì kỹ thuật viên IT phải trực tiếp sửa, nên đó là vấn đề lớn hơn nhiều. Nếu không thì chỉ cần cập nhật driver lỗi là xong
Xe hơi cũng đâu có không nổ máy chỉ vì hết nước rửa kính
Phần lớn tổ chức bị ảnh hưởng vào thứ Sáu hẳn sẽ thích việc rủi ro bị tấn công mã độc hoặc sử dụng trái phép tăng lên một chút trong 24 giờ hơn là sự sụp đổ IT toàn diện mà họ thực sự trải qua
Hơn nữa, bug đó cũng không nhất thiết phải gây màn hình xanh. Hệ thống có thể đã tiếp tục chạy trong trạng thái không xác định với hậu quả không giới hạn
Với eBPF, ít nhất có thể phát hiện một phần các lỗi khả dĩ và đưa ra quyết định quản lý rủi ro dựa trên kết quả đó
Để cập nhật, bên gọi phải gọi một hàm khác, vì vậy trách nhiệm nằm ở bên gọi chứ không phải ở người có thể chọc ngang vào kernel
Nếu không có hàm tương ứng với hash được hiển thị thì không thể gọi; còn nếu có thì cũng không thể gọi theo cách nào khác ngoài cách đã định, nhờ đó đạt được tính chất “hoặc hoạt động hoàn hảo, hoặc hoàn toàn không hoạt động” như mong muốn
Ngoài ra, phản ứng trước trạng thái sai không nhất thiết phải là “bỏ qua”. Có thể vô hiệu hóa đăng nhập người dùng bị giới hạn hoặc tắt màn hình
Nếu lo rằng mã độc có thể khai thác điều này, thì trong tình huống mã độc đã có thể sửa các tập tin trên đĩa của phần mềm diệt virus, tôi nghi ngờ liệu có phải ý hay khi tin rằng chính hệ thống có thể xử lý việc đó
Có thể an toàn hơn nếu báo cáo lên cơ chế bảo mật cấp cao hơn và để hệ thống bên ngoài vô hiệu hóa hoặc hạn chế truy cập mạng. Xa hơn nữa, các biện pháp như vậy chỉ cần quyền quan sát chứ không cần quyền can thiệp vào hệ thống, nên cũng giảm khả năng bản thân hệ thống diệt virus trở thành đường đi của mã độc hoặc nguyên nhân của những bug kiểu này
eBPF rất tuyệt và có thể được dùng cho nhiều mục đích để cải thiện nhiều thứ, nhưng nói rằng “máy tính sẽ không crash vì một bản cập nhật phần mềm tệ” thì có vẻ phóng đại
Ngay cả khi giả định bản thân BPF không có bug, phạm vi các kernel hook khá rộng, các hook đó gọi mã eBPF, và mã đó lại có thể gọi vào kernel
https://www.man7.org/linux/man-pages/man7/bpf-helpers.7.html
Đặc biệt bpf_probe_read_kernel() được dùng rất nhiều nhưng không an toàn. Nó nỗ lực khá nhiều để tránh OOPS hoặc crash, nhưng tuyệt đối không hoàn hảo
Trong phần còn lại của danh sách cũng có nhiều thứ có thể dễ dàng làm hỏng hệ thống, dù thực tế không gây oops hay panic
Và nếu đó là công cụ phát hiện rồi chặn “hành vi độc hại” ở user space, nó cũng có thể bắt đầu coi mọi thứ là độc hại và khiến máy tính không dùng được
Mặt khác, eBPF không có mô hình bảo mật thực sự ở phía user space. Việc gắn chương trình eBPF thực tế được thực hiện thông qua lệnh gọi hệ thống bpf(), chứ không phải một thao tác quyền hợp lý trên đối tượng kernel được gắn vào; cũng hoàn toàn không có cơ chế nào nhốt eBPF mà container dùng bên trong chính container đó. bpf_probe_read_kernel() về bản chất có thể đọc toàn bộ bộ nhớ kernel
Vì vậy điểm eBPF tốt hơn mã C kernel thông thường nằm ở chỗ nó giống như viết mã bằng một ngôn ngữ an toàn với bề mặt API unsafe bị giới hạn. Với loại công việc này thì đó là cải thiện lớn, nhưng tuyệt đối không hoàn hảo
Cũng có người nói verifier rất nghiêm ngặt và phần triển khai Linux dài hơn 20 nghìn dòng, nhưng verifier phức tạp đến mức vô lý. Tôi muốn thấy nền tảng dựa trên phương pháp hình thức hơn là 20 nghìn dòng logic viết tay
Tôi nghi ngờ câu nói rằng “chương trình eBPF được bộ kiểm chứng phần mềm kiểm tra an toàn và về cơ bản chạy trong sandbox, nên không thể làm sập toàn bộ hệ thống”
Chẳng phải một trong những mục đích của hệ điều hành là giám sát phần mềm sao? Tôi biết đây là vấn đề liên quan đến chính hệ điều hành, nhưng nếu thêm một tầng để giám sát người giám sát, rốt cuộc chẳng phải tầng đó cũng lại cần được giám sát sao?
Thay vì ngây thơ tin rằng độ phức tạp mới về lâu dài sẽ tốt hơn, không thể chọn giảm độ phức tạp sao?
Cách cũ là nạp kernel driver, hook vào vô số system call, rồi cầu mong không làm hỏng gì. Làm sai có thể gây panic, nhưng Linux khá vững chắc
Cách eBPF gần với việc yêu cầu thông tin mong muốn bằng lệnh dành riêng cho eBPF hơn
Tổng quan cách hoạt động có ở đây: https://ebpf.io/what-is-ebpf/
Nghe như một công nghệ tuyệt vời, nhưng vấn đề thực sự nghiêm trọng lại nằm ở phần “cũng có thể dùng các biện pháp giảm thiểu rủi ro khi triển khai phần mềm như canary test, rollout theo giai đoạn, engineering về khả năng phục hồi”
Không cần công nghệ mới để triển khai quản lý chất lượng cơ bản theo tiêu chuẩn ngành
Có lẽ nhân sự kiện này có thể bắt đầu cho nghỉ thứ Sáu. Nếu mọi người bớt bị thúc ép làm việc, và có thêm thời gian dừng lại suy nghĩ xem tình hình đang diễn tiến ra sao và mình có thể tác động thế nào đến dòng chảy đó, có khả năng thiệt hại đã ít hơn
Việc giải thích rằng bộ kiểm chứng trong triển khai Linux dài hơn 20 nghìn dòng và có đóng góp từ cả ngành công nghiệp lẫn giới học thuật lại không khiến tôi yên tâm. Bề mặt tấn công bổ sung đã là vấn đề, nhưng ai có thể bảo chứng cho một codebase lớn như vậy?
Tôi có ấn tượng rằng bộ kiểm chứng WebAssembly đơn giản hơn nhiều
Nếu bộ lọc được nạp khi khởi động và hook vào mọi thứ, chỉ một bug cũng có thể khóa hệ thống đến mức không thể thao tác hay vá được. Ví dụ như khi nạp một danh sách cho phép rỗng; rốt cuộc có thể biến boot loop thành một dạng từ chối dịch vụ khác
Nếu Microsoft đưa các yếu tố cốt lõi cần thiết cho việc khôi phục vào một danh sách cho phép hard-code, bug trong những công cụ kiểu này có thể dễ sửa hơn, nhưng cho đến khi bản sửa được triển khai, hệ thống dù bật lên vẫn không dùng được, tạo ra downtime thực tế
Bài blog viết rằng “eBPF miễn nhiễm với những crash kiểu này”
Tôi đã tìm kiếm nhưng không thấy thông tin chắc chắn, và vẫn có vẻ như nó có thể làm hỏng thứ gì đó. Mong có chuyên gia eBPF giải thích về tuyên bố này. Tài liệu tốt nhất tôi tìm được là cái này: https://stackoverflow.com/questions/70403212/why-is-ebpf-sai...