Lỗ hổng Nginx làm lộ kho mật khẩu của Bitwarden
(labs.hakaioffsec.com)- Nginx, máy chủ web đa năng chiếm thị phần áp đảo từ năm 2004
- Cấu hình sai trong Nginx có thể dẫn đến lỗ hổng bảo mật và rò rỉ dữ liệu
- Giới thiệu NavGix, công cụ tự động để phát hiện lỗ hổng của Nginx
- Lỗ hổng này có thể cho phép truy cập vào các tệp và thư mục ngoài phạm vi dự kiến
- Các nghiên cứu tình huống về Bitwarden và HPC Toolkit của Google cho thấy mức độ nghiêm trọng của lỗ hổng này
1 bình luận
Ý kiến trên Hacker News
Tham khảo thêm, gixy (trình kiểm tra cấu hình nginx) phát hiện được vấn đề này: https://github.com/yandex/gixy/blob/master/docs/en/plugins/a...
Và NixOS tự động chạy gixy trên các cấu hình được tạo thông qua nó, rồi từ chối build hệ thống nếu có vấn đề
$uritrong 301 redirectNhưng mình tò mò không biết có trình tìm kiếm tùy chọn nào tốt hơn không. Kiểu tìm trên toàn bộ hàng nghìn tùy chọn không hợp lắm; mình muốn chỉ xem các package như
sshvà những tùy chọn tương ứng với chúng, nhưng kết quả không liên quan lẫn vào quá nhiềuCó thể đây là câu hỏi ngớ ngẩn, nhưng có lý do chính đáng nào để nginx cho phép đi lên thư mục cha bằng
..trong đường dẫn URL không? Trông nó như hành vi đang chờ gây rắc rối vậySửa: mình hơi rối về chuyện chính xác lỗ hổng gốc xảy ra thế nào. Có vẻ như http://localhost/foo../secretfile.txt được diễn giải thành kiểu
/var/www/foo/../secretfile.txt; vậy thì trên một server không có lỗ hổng, tại sao http://localhost/foo/../secretfile.txt lại không được diễn giải y hệt? Mình không hiểu vì sao..trong đường dẫn chỉ hoạt động trong một số trường hợpTrong trường hợp này, một phần của URL được nginx diễn giải thành thư mục (http://localhost/foo) do cách nó được ánh xạ từ cấu hình sang filesystem cục bộ. Vì nó có vẻ trỏ đến thư mục, nên khi nginx tạo đường dẫn đầy đủ cho tài nguyên được yêu cầu, nó trở thành
"${mapped_path}/../secretfile.txt"; điều này vô nghĩa theo góc nhìn URL nhưng lại hợp lệ trên filesystem cục bộ. URL chỉ là chuỗi chứ không phải thành phần đường dẫn thực sự, nên vị trí của dấu gạch chéo về bản chất không quá quan trọngĐây là vấn đề rất thường gặp trên web server nói chung kể từ khi web xuất hiện. Việc ánh xạ URL trực tiếp sang đường dẫn file phổ biến vì ban đầu nó bắt nguồn từ các file server đơn giản có chỉ mục, nhưng rồi nhanh chóng chuyển sang môi trường hỗn hợp nơi URL không còn là đường dẫn mà là định danh ứng dụng. Kiểu chỉ định app bằng một phần của đường dẫn rồi coi phần còn lại là tham số hay đối số
Và nói chung, việc tôn trọng
.hay..trong URL đối với các đối tượng filesystem thường là vô nghĩa. Các app của mình sẽ chuẩn hóa request path để đảm bảo ánh xạ đúng. Trình duyệt coi URL như đường dẫn khi tạo liên kết tương đối, nên cũng phải cẩn thận với việc dùng dấu/ở cuối khi nào và như thế nào. Nó có thể trỏ tới tài nguyên có ý nghĩa phía server hoàn toàn khácallow_parent_traversal on;tronglocationvà biến nó thành hành vi chỉ bật khi khai báo rõ ràng"/foo/bar/.."để chặn hoặc chuẩn hóa thành"/foo/". Nhưng"/foo/bar.."là tên file hoàn toàn hợp lệ, nên có vẻ nó lọt qua kiểu kiểm tra này và không bị bắt..hoạt động khi nào trong đường dẫn hoàn toàn phụ thuộc vào quyền truy cập fileTrong trường hợp này, giả sử bạn có quyền đọc file từ thư mục chỉ mục web (
../index.html) cho đến thư mục gốc (/), thì vì bạn có quyền đi ngược lên đến root, giờ bạn cũng có thể xem mọi file world-readable có thể truy cập từ root, ví dụ/etc/passwdHãy hình dung một cái dĩa ăn có ba nhánh, trong đó web server nằm ở nhánh ngoài cùng bên phải. Nếu phần tay cầm nơi các nhánh gặp nhau là filesystem, thì khi web server có quyền truy cập các file và thư mục nối từ nhánh bên phải đến tay cầm, một khi đã chạm được đến tay cầm, nó có thể tiếp tục truy cập file ở các nhánh khác
Mình không hiểu sao chuyện này lại không được xem là lỗ hổng của nginx. Hành vi này hoàn toàn vô lý, chẳng có vẻ phục vụ mục đích có ích nào, và có thể bị khai thác ngay lập tức
Cũng nên nhớ nginx trở nên nổi tiếng nhờ các benchmark cho thấy nó “web scale” hơn Apache2
Tôi thấy có thể thử thế này: thêm một tùy chọn kiểu Linux capability để loại bỏ
..khỏi trình phân tích tên tệp của nhân LinuxTrong ứng dụng web, từ thời còn dùng modem quay số đã liên tục xuất hiện đủ kiểu lách để chèn hai dấu chấm bằng cách này hay cách khác. Cũng như nhân Linux từng xử lý nhiều loại lỗi không gian người dùng khác, có lẽ đã đến lúc tìm cách chặn hẳn vấn đề này một lần
RESOLVE_BENEATHtrong https://man7.org/linux/man-pages/man2/openat2.2.htmlFreeBSD cũng có tính năng này trong
openat(2)thông thường dưới dạngO_RESOLVE_BENEATHChỉ cần chạy nginx dưới một người dùng riêng với quyền cực kỳ hạn chế hoặc chạy trong Docker. Kèm thêm cập nhật định kỳ thì thường giải quyết được 90% vấn đề bảo mật
/some/../pathgần như nên bị cấm 100%. Ngoài việc “ai đó đã viết mã xấu xí” ra thì không có ca sử dụng hợp lý nào cả../some/pathít nhất thỉnh thoảng vẫn có ý nghĩaTuy vậy có lẽ nó cũng không hữu ích như tưởng tượng. Nhiều ứng dụng tự diễn giải
..trước khi chuyển cho hệ điều hànhNếu bạn phục vụ tệp từ một thư mục lên web, framework web phải đảm bảo không thoát ra ngoài thư mục gốc công khai mà nó phụ trách. Nếu tự làm thì phải tính đến mọi tình huống, bao gồm cả chuyện này
“Google VRP Team thưởng 500 đô la cho việc phát hiện lỗ hổng này. Họ cho rằng tác động tới ứng dụng không đủ nghiêm trọng để nhận mức thưởng cao hơn” — vậy mà lộ email tài khoản GCP và khóa riêng tư bí mật chỉ đáng 500 đô thôi sao? Rốt cuộc là kiểu gì vậy. Đúng là Google
May là những thứ bị lộ vẫn còn được mã hóa. Ngay cả công ty chuyên về lĩnh vực này cũng không tránh khỏi rò rỉ, nên thành thật mà nói thì đây gần như là kịch bản tốt nhất có thể rồi
Tiêu đề đã bị biên tập khá nhiều. Tiêu đề gốc là Hunting for Nginx Alias Traversals in the wild
Tiêu đề gửi lên HN nhấn mạnh lỗ hổng của Bitwarden, nhưng trong bài cũng nói cả về trường hợp của Google
Nếu chỉ cần phục vụ tệp tĩnh an toàn một cách ổn định, với mức dùng tài nguyên tối thiểu, thì hiện nay lựa chọn tốt nhất là gì? Trước đây tôi sẽ chọn Nginx, nhưng xét về bảo mật thì tôi tự hỏi liệu một công cụ chuyên biệt hơn, ít khả năng cấu hình sai hơn có tốt hơn không
Nó đa nền tảng, viết bằng Rust, cấu hình đơn giản và có mặc định an toàn. Cũng có image container được harden và mô-đun NixOS được harden
Tôi không khuyến nghị Caddy. Image Docker chính thức mặc định chạy bằng root [1], và cũng không cung cấp file unit systemd được sandbox đúng cách [2]
[1]: https://github.com/caddyserver/caddy-docker/issues/104
[2]: https://github.com/caddyserver/dist/blob/master/init/caddy.s...
Sửa: trau chuốt lại cách diễn đạt
file_serverrất chắc chắnCó thể là câu hỏi ngớ ngẩn, nhưng tại sao Bitwarden lại cho phép yêu cầu không xác thực tới
/attachmentsngay từ đầu? Ngay cả khi có lỗi Nginx, nếu URL đó yêu cầu xác thực thì chẳng phải yêu cầu sẽ thất bại sao?Dù vậy, vì đã triển khai cấu hình rủi ro qua Docker nên đây đúng là trách nhiệm của Bitwarden. Có vẻ Bitwarden cũng thừa nhận điều đó và đã sửa sau đó
Xin thứ lỗi cho câu hỏi ngớ ngẩn này. Nếu có quyền sở hữu thư mục và tệp phù hợp thì kiểu truy cập vòng qua như thế này chẳng phải sẽ bị chặn sao?
Nếu nginx không chạy bằng root, thì làm sao nó có thể đọc được các tệp khác ngoài những tệp được gán rõ ràng cho người dùng nginx?
go-rwxcho toàn bộ tệp của ứng dụng, rồi đặt nhóm của các tệp “static” thànhwww-datavà chỉ cấpg+r, thì web server sẽ không thể truy cập các tệp của ứng dụngĐây đúng nghĩa là nhập môn hosting ứng dụng 101, và người ta đã làm như vậy từ 20 năm trước rồi
/homeCó thể sẽ phải chỉnh thêm một chút về group membership, nhưng hoàn toàn đáng công
Có khi tôi đang làm hỏng mọi thứ một cách nghiêm trọng thật. Oái
www-data. Nếu ứng dụng tạo ra dữ liệu nhạy cảm thì đương nhiên nên dùng 077 umaskĐáng tiếc là nginx và các web server khác trong các ứng dụng web thông thường thường cần chạy bằng root. Vì chúng phải lắng nghe trên cổng 80 hoặc 443. Các cổng nhỏ hơn 1024 thì chỉ root mới có thể mở
Giải thích chi tiết hơn ở đây: https://unix.stackexchange.com/questions/134301/why-does-ngi...