Cuộc tấn công DDoS HTTP/2 'Rapid Reset' mới
(cloud.google.com)- DDoS Layer 7 dựa trên HTTP/2 nhắm vào các dịch vụ của Google và khách hàng Google Cloud đã đạt đỉnh vào tháng 8/2023, vượt quá 398 triệu yêu cầu mỗi giây
- Phần lớn cuộc tấn công đã bị chặn bởi hạ tầng cân bằng tải toàn cầu của Google nên không dẫn đến gián đoạn, và sau đó các biện pháp bảo vệ bổ sung đã được thêm vào để giảm thiểu các cuộc tấn công tương tự
- Rapid Reset hủy từng luồng ngay sau khi gửi yêu cầu bằng khung RST_STREAM nhưng vẫn giữ kết nối, lặp lại việc tạo yêu cầu trong khi né giới hạn số luồng đồng thời
- Ngay cả với yêu cầu đã bị hủy, máy chủ vẫn có thể phải thực hiện các tác vụ như giải nén header, ánh xạ URL, hay proxy tới backend, làm gia tăng bất đối xứng chi phí
- Nhà vận hành HTTP/2 cần kiểm tra mức độ phơi nhiễm và áp dụng bản vá; khi phát hiện lạm dụng, biện pháp giảm thiểu then chốt là đóng chính kết nối TCP thay vì chỉ từng yêu cầu riêng lẻ
Quy mô tấn công và phản ứng của Google
- Các dịch vụ của Google và khách hàng Cloud đã trở thành mục tiêu của cuộc tấn công DDoS Layer 7 dựa trên HTTP/2 đạt đỉnh vào tháng 8/2023
- Đợt tấn công lớn nhất vượt quá 398 triệu yêu cầu mỗi giây, lớn hơn rất nhiều so với các cuộc tấn công Layer 7 từng được báo cáo trước đó
- Hạ tầng cân bằng tải toàn cầu của Google đã chặn phần lớn cuộc tấn công tại biên mạng
- Không xảy ra gián đoạn
- Mức ảnh hưởng chỉ ở phạm vi hạn chế
- Google DDoS Response Team đã xem xét cuộc tấn công và áp dụng thêm các biện pháp bảo vệ để giảm các cuộc tấn công tương tự
- Google đã dẫn dắt quy trình công bố phối hợp cùng các đối tác trong ngành để xử lý vector tấn công HTTP/2 mới này
Vì sao HTTP/2 trở nên có lợi cho DDoS
- Kể từ cuối năm 2021, phần lớn các cuộc tấn công DDoS Layer 7 được quan sát trên các dịch vụ 1st-party của Google và các dự án Google Cloud được Cloud Armor bảo vệ đều dựa trên HTTP/2
- Nhiều cả về số lượng cuộc tấn công
- Cao cả về tốc độ yêu cầu tối đa
- Hiệu quả của HTTP/2 không chỉ tăng hiệu quả cho client hợp lệ mà còn có thể làm tăng hiệu quả của các cuộc tấn công DDoS
-
Ghép kênh luồng
- HTTP/2 truyền các frame giữa các endpoint bằng stream là một lớp trừu tượng hai chiều
- Nhờ ghép kênh luồng, nhiều yêu cầu có thể được xử lý đồng thời trên một kết nối TCP
- Ràng buộc chính của tấn công DoS Layer 7 là số lượng kết nối truyền đồng thời
- Mỗi kết nối tiêu tốn bộ nhớ hệ điều hành cho socket record và buffer
- Bắt tay TLS cần thời gian CPU
- Cần một bộ 4-tuple duy nhất gồm địa chỉ IP và cổng ở hai đầu
- HTTP/1.1 thường xử lý yêu cầu theo kiểu tuần tự, nên tốc độ yêu cầu trên một kết nối đơn lẻ gần mức 1 yêu cầu mỗi vòng RTT
- Với HTTP/2, có thể mở nhiều stream đồng thời trên một kết nối TCP, và mỗi stream tương ứng với một yêu cầu HTTP
- Trong thực tế, client có thể mở 100 stream cho mỗi yêu cầu và máy chủ có thể xử lý song song, khiến thông lượng hiệu dụng của một kết nối đơn đạt tới khoảng 100 yêu cầu mỗi RTT
- Kết quả là mức tận dụng kết nối có thể cao gần 100 lần so với HTTP/1.1
Cách Rapid Reset hoạt động
- HTTP/2 cho phép client gửi khung RST_STREAM để báo với máy chủ rằng một stream trước đó đã bị hủy
- Việc hủy không cần phối hợp riêng giữa client và server
- Client có thể hủy đơn phương
- Có thể giả định máy chủ nhận khung RST_STREAM sẽ áp dụng việc hủy trước các dữ liệu khác trên cùng kết nối TCP
- Rapid Reset dựa vào việc gửi khung RST_STREAM ngay sau khi gửi frame yêu cầu
- Khiến endpoint bên kia bắt đầu xử lý rồi nhanh chóng reset yêu cầu
- Yêu cầu bị hủy nhưng kết nối HTTP/2 vẫn được giữ mở
- Quy trình tấn công rất đơn giản
- Mở nhiều stream cùng lúc như một cuộc tấn công HTTP/2 tiêu chuẩn
- Không chờ phản hồi từ máy chủ hoặc proxy
- Lập tức hủy từng yêu cầu
- Nếu có thể reset ngay lập tức, mỗi kết nối về thực chất có thể đưa một lượng lớn yêu cầu vào trạng thái đang xử lý gần như vô thời hạn
- Kẻ tấn công không vượt quá giới hạn stream mở đồng thời một cách tường minh
- Số yêu cầu đang xử lý phụ thuộc vào băng thông mạng sẵn có nhiều hơn là thời gian khứ hồi (RTT)
- Triển khai máy chủ HTTP/2 thông thường vẫn có thể phải làm việc cho cả các yêu cầu đã bị hủy
- Cấp phát cấu trúc dữ liệu cho stream mới
- Phân tích truy vấn
- Giải nén header
- Ánh xạ URL tới tài nguyên
- Trong các triển khai reverse proxy, yêu cầu có thể đã được proxy tới máy chủ backend trước khi khung RST_STREAM được xử lý
- Vì client gần như không phải trả chi phí cho việc gửi yêu cầu, một bất đối xứng chi phí có thể bị khai thác xuất hiện giữa máy chủ và client
- Nếu yêu cầu bị hủy trước khi tạo phản hồi, máy chủ reverse proxy sẽ không gửi phản hồi, nhờ đó cũng làm giảm băng thông downlink từ máy chủ hoặc proxy theo hướng về phía kẻ tấn công
Các biến thể tấn công đã quan sát được
- Trong vài tuần sau đợt DDoS ban đầu, các biến thể Rapid Reset đã được quan sát
- Những biến thể này không hiệu quả bằng cách ban đầu, nhưng vẫn có thể hiệu quả hơn các cuộc tấn công DDoS HTTP/2 tiêu chuẩn
-
Biến thể hủy theo lô
- Biến thể đầu tiên không hủy stream ngay lập tức mà mở một nhóm stream, chờ một lúc rồi hủy hàng loạt
- Ngay sau khi hủy, nó lại mở một nhóm stream lớn mới để tiếp tục tấn công
- Cách này có thể vượt qua các biện pháp giảm thiểu chỉ dựa trên tỷ lệ khung RST_STREAM đi vào
- Ví dụ: chính sách chỉ cho phép tối đa 100 RST_STREAM mỗi giây trên mỗi kết nối và đóng khi vượt quá
- Do không tối đa hóa được mức tận dụng kết nối, lợi ích chính của kiểu tấn công hủy giảm đi
- Dù vậy, nó vẫn có thể hiệu quả hơn về mặt triển khai so với DDoS HTTP/2 tiêu chuẩn, nên chỉ giới hạn tỷ lệ hủy stream sẽ đòi hỏi ngưỡng khá nghiêm ngặt
-
Biến thể không hủy
- Biến thể thứ hai hoàn toàn không hủy stream
- Thay vào đó, nó cố gắng mở một cách lạc quan nhiều stream hơn số lượng stream đồng thời mà máy chủ quảng bá
- Điều này giúp giữ đầy pipeline yêu cầu liên tục, làm giảm nút thắt RTT giữa client và proxy
- Nếu nhắm vào các tài nguyên mà máy chủ HTTP/2 phản hồi ngay, nó còn có thể loại bỏ cả nút thắt RTT giữa proxy và server
- RFC 9113, RFC HTTP/2 hiện tại, khuyến nghị rằng khi cố mở quá nhiều stream thì chỉ các stream vượt giới hạn mới bị vô hiệu hóa, thay vì toàn bộ kết nối
- Trong cấu trúc của hầu hết máy chủ HTTP/2 không xử lý các stream vượt mức, biến thể không hủy trở nên khả thi vì stream mới có thể được chấp nhận và xử lý gần như ngay lập tức sau phản hồi của stream trước đó
Chiến lược giảm thiểu
- Họ tấn công này khó có biện pháp giảm thiểu khả thi nếu chỉ chặn từng yêu cầu riêng lẻ
- Khi phát hiện lạm dụng, cần đóng toàn bộ kết nối TCP
- HTTP/2 hỗ trợ đóng kết nối bằng loại frame GOAWAY
- RFC định nghĩa quy trình đóng dần dần: trước tiên gửi một GOAWAY mang tính thông báo không đặt giới hạn mở stream mới, rồi sau một vòng RTT gửi GOAWAY cấm mở thêm stream
- Nhưng quy trình GOAWAY dần dần này thường không đủ vững chắc với client độc hại
- Kết nối bị phơi nhiễm với tấn công Rapid Reset quá lâu
- Không chặn được các yêu cầu đi vào
- Với mục tiêu giảm thiểu, GOAWAY cần được cấu hình để giới hạn việc tạo stream ngay lập tức
-
Xác định kết nối lạm dụng
- Việc client hủy yêu cầu bản thân nó không phải lúc nào cũng là lạm dụng
- Chức năng hủy của HTTP/2 vốn nhằm quản lý xử lý yêu cầu tốt hơn
- Khi người dùng rời khỏi trang và trình duyệt không còn cần tài nguyên đã yêu cầu nữa
- Với các ứng dụng dùng long polling có timeout phía client
- Việc giảm thiểu tập trung vào theo dõi thống kê kết nối và dùng nhiều tín hiệu cùng logic nghiệp vụ để đánh giá tính hữu ích của từng kết nối
- Ví dụ, nếu một kết nối có hơn 100 yêu cầu và hơn 50% trong số đó bị hủy, nó có thể trở thành ứng viên để áp dụng giảm thiểu
- Mức độ và loại phản ứng phụ thuộc vào rủi ro của từng nền tảng
- Khung GOAWAY cưỡng bức
- Đóng kết nối TCP ngay lập tức
- Để giảm thiểu biến thể không hủy, khuyến nghị máy chủ HTTP/2 đóng các kết nối vượt quá giới hạn stream đồng thời
- Có thể đóng ngay lập tức
- Hoặc đóng sau một vài lần vi phạm lặp lại
Khả năng áp dụng với HTTP/3
- Google không cho rằng cách tấn công này áp dụng trực tiếp được với HTTP/3 (QUIC) do khác biệt giao thức
- Hiện tại Google chưa thấy HTTP/3 bị dùng làm vector DDoS quy mô lớn
- Tuy vậy, vẫn khuyến nghị các triển khai máy chủ HTTP/3 chủ động áp dụng cơ chế giới hạn khối lượng công việc mà một kết nối truyền tải đơn có thể gây ra
- Theo hướng tương tự các biện pháp giảm thiểu đã thảo luận cho HTTP/2
Phối hợp trong ngành và CVE
- Ngay từ giai đoạn đầu điều tra của Google DDoS Response Team, đã rõ rằng kiểu tấn công này có thể ảnh hưởng rộng đến mọi dịch vụ cung cấp HTTP/2
- Google đã tận dụng nhóm công bố lỗ hổng phối hợp sẵn có để dẫn dắt quy trình công bố lỗ hổng phối hợp
- Quy trình công bố tập trung vào việc thông báo cho các đơn vị triển khai HTTP/2 quy mô lớn
- Các công ty hạ tầng
- Nhà cung cấp phần mềm máy chủ
- Mục tiêu của việc thông báo trước là để phát triển biện pháp giảm thiểu và chuẩn bị theo lịch công bố phối hợp
- Trước đây, cách tiếp cận này từng dẫn tới việc các nhà cung cấp dịch vụ triển khai bảo vệ trên diện rộng hoặc phát hành cập nhật phần mềm cho nhiều gói và giải pháp
- Trong quá trình công bố phối hợp, CVE-2023-44487 đã được đặt trước để theo dõi việc sửa lỗi ở nhiều triển khai HTTP/2
Các nhà vận hành dịch vụ HTTP/2 cần làm gì
- Cuộc tấn công này có thể gây ảnh hưởng đáng kể đến dịch vụ ở mọi quy mô
- Mọi nhà cung cấp vận hành dịch vụ HTTP/2 cần đánh giá mức độ phơi nhiễm với vấn đề này
- Bản vá và cập nhật phần mềm cho các web server phổ biến và ngôn ngữ lập trình có thể đã hoặc sắp được cung cấp
- Khuyến nghị áp dụng các bản sửa lỗi được phát hành càng sớm càng tốt
- Với khách hàng Google Cloud, ngoài bản vá phần mềm còn được khuyến nghị sử dụng Application Load Balancer và Google Cloud Armor
- Google Cloud Armor đã bảo vệ Google và những người dùng hiện tại của Google Cloud Application Load Balancing
1 bình luận
Ý kiến trên Hacker News
Các luồng liên quan đang diễn ra:
Vụ tấn công DDoS lớn nhất tính đến nay, đạt đỉnh hơn 398 triệu yêu cầu mỗi giây - https://news.ycombinator.com/item?id=37831062
Lỗ hổng zero-day HTTP/2 gây ra vụ tấn công DDoS kỷ lục - https://news.ycombinator.com/item?id=37830998
Có vẻ nhóm HAProxy đã phát hiện và giảm thiểu loại vấn đề này trong HTTP/2 từ năm 2018, rất đáng mừng: https://www.mail-archive.com/haproxy@formilux.org/msg44134.h...
https://www.nginx.com/blog/http-2-rapid-reset-attack-impacti...
Trong một triển khai máy chủ HTTP/2 thông thường, ngay cả với các yêu cầu đã bị hủy, máy chủ vẫn phải làm khá nhiều việc như cấp phát cấu trúc dữ liệu stream mới, phân tích truy vấn, giải nén header, ánh xạ tài nguyên từ URL
Trong triển khai reverse proxy, yêu cầu thậm chí có thể đã được proxy sang máy chủ backend trước khi frame
RST_STREAMđược xử lý. Trong khi đó, client gần như không tốn chi phí gì để gửi yêu cầu, nên xuất hiện một bất đối xứng chi phí có thể bị khai thác giữa server và clientThật ngạc nhiên là điều này không được dự đoán khi thiết kế HTTP/2. Tấn công khuếch đại trong các giao thức khác vốn đã được biết đến rất rõ. Việc cuộc tấn công này lộ ra muộn như vậy cũng đáng ngạc nhiên tương tự, nhưng có lẽ cho đến gần đây HTTP/2 vẫn chưa được triển khai đủ rộng để trở thành mục tiêu đáng giá
RST_STREAMđã có trong các phiên bản SPDY đầu tiên, còn SPDY nhìn chung có vẻ được thiết kế khoảng năm 2009Các cuộc tấn công như Slowloris cũng xuất hiện gần như cùng thời điểm, nhưng khi đó chưa được biết đến rộng rãi. Trong khi đó SYN cookie đã được đưa vào từ năm 1996, nên rõ ràng có tiền lệ lịch sử cho kiểu tấn công mà nạn nhân phải trả Y còn kẻ tấn công trả X
Điểm khác biệt là lần này nó được thử nghiêm túc nhằm vào Google
Hóa ra chúng ta cần HTTP/2 để phân phối quảng cáo, tracker và các frontend framework cồng kềnh nhanh hơn. Giờ thì nó cũng phân phối các cuộc tấn công nhanh hơn
May là HTTP/1.1 vẫn hoạt động. Nếu không thích giao thức đó, bạn luôn có thể bật HTTP/1.1 trong cài đặt trình duyệt và trên web server
Đây là một lý do nữa để giữ giao thức nền tảng nhỏ gọn. HTTP/2, nếu tính cả SPDY, đã tồn tại hơn 10 năm, vậy mà đây là lần đầu kiểu tấn công này lộ diện
Không biết trong HTTP/3 và QUIC còn ẩn giấu bất ngờ nào
Có lẽ nên thêm “hủy” vào danh sách “các vấn đề khoa học máy tính khó”
Giống như những mục khác trong danh sách đó, chẳng hạn lỗi lệch 1 hay vô hiệu hóa cache, nó không thực sự khó đến mức khủng khiếp nhưng dễ bị đánh giá thấp và bỏ qua. Nếu chỉ cần dành một nửa thời gian dùng cho việc thiết kế tạo lập, constructor và khởi tạo cho việc hủy, dọn dẹp, tháo dỡ và hủy bỏ, chắc hẳn đặc biệt là các lỗi cạn kiệt tài nguyên đã ít hơn nhiều
awaitnào mà không cần từng lời gọi riêng lẻ phải hợp tác, đồng thời hủy luôn toàn bộ call stackTôi muốn nhắc mọi người rằng Google là công ty đã tạo ra HTTP/2
Giờ họ nói như thể đang anh hùng cứu chúng ta khỏi vấn đề do chính họ tạo ra, nhưng lại không nhắc đến phần họ là người tạo ra nó. Sự trơ trẽn của các công ty công nghệ này thật quá quen thuộc. Microsoft cũng đã làm kiểu này suốt nhiều thập kỷ
Ai có thể giải thích điểm mới của cuộc tấn công này so với một vụ flood yêu cầu thông thường là gì không?
Với HTTP/1.1, bạn có thể gửi một yêu cầu cho mỗi vòng khứ hồi[0]. Với multiplexing của HTTP/2, bạn có thể gửi 100 yêu cầu cho mỗi vòng khứ hồi. Trong cuộc tấn công này, về cơ bản bạn có thể gửi số lượng yêu cầu vô hạn cho mỗi vòng khứ hồi. Hy vọng biểu đồ trong bài viết cho thấy sự khác biệt, nhưng cũng có thể bạn đang nói đến một dạng tấn công khác với những gì tôi mô tả ở trên
[0] Nếu xét HTTP/1.1 pipelining thì có thể loại bỏ một yếu tố vòng khứ hồi, nhưng các client thực tế hầu như không dùng HTTP/1.1 pipelining, nên chỉ riêng việc dùng nó đã là một tín hiệu rất rõ ràng của lưu lượng độc hại
Khi gửi yêu cầu kèm reset stream trong cùng một kết nối, họ có thể gửi nhiều yêu cầu hơn trên mỗi kết nối/client so với trước đây, khiến chi phí tấn công rẻ hơn hoặc khó chặn hơn
Header blog cứ bật lên liên tục, làm tôi không đọc được trang