Bài học theo mô-đun (4/4)
Viết các mẫu an toàn ReDoS
ReDoS (Từ chối dịch vụ theo biểu thức chính quy) là một loại tấn công trong đó đầu vào được chế tạo cẩn thận làm cho thời gian khớp của biểu thức chính quy trở nên bùng nổ. Công cụ JS sử dụng quay lại: nếu một mẫu "không rõ ràng", trên một đầu vào không may mắn, nó có thể thực hiện số lần thử theo cấp số nhân.
Mô hình thảm họa cổ điển
Pattern: ^(a+)+$
Input: "aaaaaaaaaaaaaaaaaaaaab"Để khớp, công cụ sẽ thử mọi phân vùng có thể có của "a" giữa
hai bộ định lượng +. Trên 20 "a" tức là 2^20 = ~1 triệu lần thử.
Trên 30 "a" s, một tỷ.
Các ví dụ nguy hiểm khác:
(a*)*b-- "các ngôi sao lồng nhau".(a|a)*-- các lựa chọn thay thế chồng chéo.(\w+)+@-- các nhóm tham lam có bộ định lượng bên ngoài.
Cách nhận biết mối nguy hiểm
Hãy tìm những cấu trúc này:
- Bộ định lượng bên trong bộ định lượng:
(...+)+,(...*)*,(...{n,})+. - Các lựa chọn thay thế chồng chéo theo bộ định lượng:
(a|ab)*,(\w|\d)+. - Nhìn trước/sau với các lựa chọn thay thế phức tạp được lặp lại.
Viết lại phòng thủ
Dangerous: ^(\w+\s+)+$
Safe: ^(?:\w+\s+)*\w+$Phiên bản an toàn tách trường hợp cơ bản khỏi trường hợp lặp lại, loại bỏ sự mơ hồ. Các kỹ thuật khác:
- Bộ định lượng sở hữu (
a++) -- không được hỗ trợ trong JS nhưng có sẵn trong các công cụ khác. - Mẫu nguyên tử (
(?>...)) -- không có trong JS. - Giới hạn độ dài của đầu vào trước khi khớp.
- Hết thời gian khi khớp (trình chỉnh sửa của khóa học này sử dụng một nhân viên có thời gian chờ là 500 mili giây).
Khuyến nghị về các mẫu an toàn ReDoS
- Đảm bảo rằng các tùy chọn luân phiên loại trừ lẫn nhau (ví dụ: không sử dụng
(a|a+)). - Tránh áp dụng các bộ định lượng lồng nhau cho các biểu thức chồng chéo (ví dụ:
(\\s*)*). - Luôn ưu tiên các lớp ký tự phủ định cụ thể (
[^\\n]*) hơn dấu chấm ký tự đại diện chung (.*).
Hãy thử nó
Xác định các mẫu chữ lặp lại -- nhưng theo cách an toàn với ReDoS. Sử dụng một lớp ký tự đơn, KHÔNG sử dụng các nhóm lồng nhau như (a+)+.
Hiển thị gợi ý
Thay thế (a+)+ nguy hiểm bằng a+ đơn giản. Kết quả là như nhau, nhưng an toàn.
Giải pháp khả dụng sau 3 lần thử
Xem lại bài tập
Nhận dạng chuỗi các từ được phân tách bằng dấu cách, theo cách an toàn ReDoS. Sử dụng cấu trúc `(?:word+spaces+)*word` thay vì `(word+space+)+`.
Hiển thị gợi ý
Thay thế nhóm chụp (\\w+\\s+)+ bằng phiên bản rời rạc (?:\\w+\\s+)*\\w+.
Giải pháp khả dụng sau 3 lần thử
Thử thách bổ sung
Make the vulnerable pattern `(\w+\s*)+:` which causes ReDoS safe, by removing the overlapping whitespace recursion.
Hiển thị gợi ý
Di chuyển khoảng trắng để nó không trùng với sự lặp lại của nhóm: (?:\\w+\\s+)*\\w+:
Giải pháp khả dụng sau 3 lần thử