Chuyển đến nội dung chính
Mô-đun 8 · Bài học 4 trong tổng số 432/32 trong khóa học~14 min
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

Code
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:

  1. Bộ định lượng bên trong bộ định lượng: (...+)+, (...*)*, (...{n,})+.
  2. Các lựa chọn thay thế chồng chéo theo bộ định lượng: (a|ab)*, (\w|\d)+.
  3. 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ủ

Code
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

  1. Đả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+)).
  2. 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*)*).
  3. 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ó

tập thể dục#regex.m8.l4.e1
Nỗ lực: 0Đang tải…

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+)+.

Đang tải trình chỉnh sử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

tập thể dục#regex.m8.l4.e2
Nỗ lực: 0Đang tải…

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+)+`.

Đang tải trình chỉnh sửa…
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

tập thể dục#regex.m8.l4.e3
Nỗ lực: 0Đang tải…

Make the vulnerable pattern `(\w+\s*)+:` which causes ReDoS safe, by removing the overlapping whitespace recursion.

Đang tải trình chỉnh sửa…
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ử