Một kỹ thuật tấn công mạng mới được phát hiện, được gọi là cache key injection, cho phép kẻ tấn công truy cập dữ liệu hạn chế, phá hoại website hoặc đưa nội dung độc hại vào các trang đã được lưu trữ trong bộ nhớ đệm (cache).
Kỹ thuật Cache Key Injection
Nghiên cứu của Alex Brumen chỉ ra rằng kẻ tấn công không nhất thiết phải khai thác các giá trị không được đưa vào khóa bộ nhớ đệm (unkeyed HTTP request values) như các cuộc tấn công thông thường. Thay vào đó, họ có thể lạm dụng các giá trị đã tồn tại trong khóa bộ nhớ đệm khi máy chủ web kết hợp chúng mà không có dấu phân cách rõ ràng.
Các bộ nhớ đệm web hoạt động bằng cách lưu trữ các phản hồi và phục vụ lại chúng khi các yêu cầu sau đó tạo ra cùng một khóa bộ nhớ đệm, giúp cải thiện hiệu suất. Trong Nginx, một khóa bộ nhớ đệm có thể được xây dựng từ nhiều phần của yêu cầu HTTP, bao gồm giao thức, tên máy chủ, URI, chuỗi truy vấn, cookie hoặc tiêu đề (headers).
Một cấu hình Nginx phổ biến có thể bao gồm:
proxy_cache_key "$scheme$host$request_uri$http_accept";
Vấn đề xảy ra khi các thành phần của yêu cầu bị nối trực tiếp với nhau mà không có dấu phân cách. Điều này có thể dẫn đến việc hai yêu cầu khác nhau tạo ra cùng một khóa bộ nhớ đệm cuối cùng.
Ví dụ, một yêu cầu hợp lệ tới /home với tiêu đề Accept: / có thể tạo ra cùng một khóa với yêu cầu của kẻ tấn công tới /h trong khi đặt phần còn lại của ome vào một tiêu đề được kiểm soát. Mặc dù đường dẫn được yêu cầu khác nhau, Nginx có thể coi cả hai yêu cầu là cùng một đối tượng bộ nhớ đệm sau khi nối các giá trị lại. Sự trùng lặp này cho phép kẻ tấn công lưu trữ một phản hồi dưới một khóa mà sau đó khớp với một yêu cầu hợp pháp khác.
Tác động của Cache Key Injection
Một tác động được minh họa là khả năng truy cập các điểm cuối được kiểm soát quyền truy cập như /admin. Trong bằng chứng khái niệm (Proof of Concept – PoC), Nginx cho phép truy cập bảng quản trị chỉ từ localhost. Tuy nhiên, bộ nhớ đệm của nó sử dụng một khóa tùy chỉnh bao gồm URI yêu cầu và tiêu đề Accept.
Một quản trị viên có thể lưu trữ trang /admin từ localhost. Sau đó, một kẻ tấn công bên ngoài, người không thể yêu cầu /admin trực tiếp, có thể yêu cầu một đường dẫn khác như /ad trong khi đặt phần còn lại là min vào một giá trị tiêu đề được kiểm soát. Nếu yêu cầu bị thao túng tạo ra cùng một khóa bộ nhớ đệm với /admin, máy chủ có thể trả về phản hồi quản trị đã được lưu trữ trước đó mà không đánh giá quy tắc truy cập ban đầu cho đường dẫn được bảo vệ. Điều này tạo ra một hình thức đánh lừa bộ nhớ đệm web mà không yêu cầu nạn nhân nhấp vào một liên kết được chế tạo.
Kỹ thuật này còn có thể gây ra tấn công từ chối dịch vụ bằng cách làm ngộ độc bộ nhớ đệm (Cache-Poisoned Denial of Service – CPDoS). Kẻ tấn công có thể yêu cầu một tài nguyên không tồn tại như /h trong khi thao túng một tiêu đề sao cho khóa bộ nhớ đệm của nó trùng với /home.
Do yêu cầu của kẻ tấn công trả về phản hồi 404 Not Found đã được lưu trữ, những người dùng sau đó yêu cầu trang /home thực sự có thể nhận được phản hồi lỗi bị ngộ độc cho đến khi bộ nhớ đệm hết hạn hoặc bị xóa.
Brumen cũng đã trình diễn một kịch bản nghiêm trọng hơn liên quan đến sự nhầm lẫn giao thức HTTP và HTTPS. Nếu một khóa Nginx bắt đầu bằng $scheme$host$request_uri, kẻ tấn công có thể dịch chuyển ký tự ‘s’ cuối cùng trong https vào một giá trị tiêu đề Host độc hại được gửi qua HTTP.
Ví dụ, một yêu cầu HTTP sử dụng máy chủ sdummywebsite.localhost có thể tạo ra cùng một khóa với một yêu cầu HTTPS thông thường tới dummywebsite.localhost. Nếu máy chủ backend phản ánh giá trị Host bên trong nguồn script, trang đã lưu trữ bị ngộ độc có thể tải JavaScript từ một tên miền do kẻ tấn công kiểm soát, dẫn đến tấn công Cross-Site Scripting (XSS) lưu trữ.
Xem xét với Cloudflare
Nghiên cứu cũng xem xét các môi trường sử dụng Cloudflare phía trước bộ nhớ đệm Nginx gốc. Kẻ tấn công có thể sử dụng tiêu đề Authorization để yêu cầu Cloudflare bỏ qua bộ nhớ đệm biên (edge cache) của nó và chuyển tiếp yêu cầu đến Nginx.
Nếu Nginx vẫn lưu trữ phản hồi đó, kẻ tấn công có thể nhắm mục tiêu trực tiếp vào bộ nhớ đệm gốc (origin cache). Một yêu cầu sau đó có thể truy xuất mục đã bị ngộ độc từ Nginx, đặc biệt là sau khi mục bộ nhớ đệm biên của Cloudflare hết hạn hoặc không tồn tại.
Các biện pháp phòng ngừa
Biện pháp giảm thiểu chính là tránh ghép nối các mảnh khóa bộ nhớ đệm thô mà không có ranh giới rõ ràng. Việc băm một khóa không rõ ràng sẽ không giải quyết được vấn đề vì hai sự kết hợp yêu cầu khác nhau vẫn có thể tạo ra cùng một chuỗi cơ bản.
Thay vì cấu hình:
proxy_cache_key "$scheme$host$request_uri$http_accept";
Quản trị viên nên sử dụng các dấu phân cách rõ ràng hoặc mã hóa có cấu trúc:
proxy_cache_key "$scheme|$host|$request_uri|$http_accept";
Các tổ chức cũng nên tránh lưu trữ các phản hồi được xác thực hoặc kiểm soát quyền truy cập trong bộ nhớ đệm chia sẻ, xác thực nghiêm ngặt các tiêu đề Host, chuyển hướng lưu lượng HTTP sang HTTPS và đảm bảo hành vi bộ nhớ đệm nhất quán giữa các lớp CDN và gốc.
Phát hiện này cho thấy các khóa bộ nhớ đệm không nên được coi là an toàn chỉ vì các giá trị yêu cầu được bao gồm trong đó. Nếu không có ranh giới rõ ràng, các giá trị do kẻ tấn công kiểm soát có thể xung đột với các yêu cầu hợp pháp và biến một tính năng hiệu suất thành rủi ro lộ dữ liệu, làm mất uy tín trang web hoặc gây ra từ chối dịch vụ. Các tổ chức nên xem xét các đề xuất từ các nguồn như Nginx security advisories để cập nhật cấu hình và bảo vệ hệ thống của mình.










