← All posts

Biểu mẫu đặt lại mật khẩu của bạn là một khẩu đại bác email miễn phí

Authagonal·July 9, 2026
securityrate-limitingemail

Biểu mẫu đặt lại mật khẩu có lẽ là endpoint kém thú vị nhất mà bạn sở hữu. Nó cũng là endpoint duy nhất mà kẻ tấn công có thể chĩa vào bất kỳ ai. Endpoint của chúng tôi đã không có rate limit theo từng email trong một thời gian, và lý do điều đó quan trọng không phải lý do bạn nghĩ.

Phản xạ tự nhiên, khi nghe "endpoint không cần xác thực, không có rate limit," là nghĩ đến brute force. Nhưng chẳng có gì để brute force trên một yêu cầu đặt lại cả. Bạn không đoán mật khẩu. Bạn gửi một địa chỉ email và hệ thống gửi đi một liên kết. Dội bom nó không đưa bạn vào được tài khoản nào. Vậy ai là người chịu thiệt?

Nạn nhân là một bên thứ ba. Gõ địa chỉ của người khác, [email protected], nhấn gửi, lặp lại. Mỗi yêu cầu gửi một email thật đến một hộp thư thật mà bạn không kiểm soát. Bạn đã trưng dụng biểu mẫu đặt lại của chúng tôi thành một quả bom thư nhắm vào một người chưa từng đăng ký bất cứ thứ gì. Và vì email đến từ chúng tôi, thiệt hại giáng xuống cả hai nơi cùng lúc. Hộp thư của nạn nhân đầy ứ. Và uy tín người gửi của chúng tôi hứng đòn, bởi một cơn lũ email không mong muốn từ tên miền của chúng tôi chính xác là thứ mà các nhà cung cấp hộp thư để mắt tới. Đủ nhiều thì email hợp lệ của chúng tôi, liên kết xác minh, các yêu cầu đặt lại mật khẩu thật sự, bắt đầu rơi vào thư mục spam của mọi khách hàng thật mà chúng tôi có. Một endpoint không cần xác thực, không có thông tin đăng nhập và không tốn kém gì cho kẻ tấn công, làm suy giảm một tài nguyên mà tất cả người dùng của chúng tôi cùng chia sẻ.

Vậy nên bạn rate-limit nó. Theo từng địa chỉ email, để một mục tiêu không thể bị dội bom. Dễ thôi. Ngoại trừ việc cách triển khai hiển nhiên lại lặng lẽ mở ra một lỗ hổng khác.

Nếu bạn chỉ áp dụng giới hạn, hoặc chỉ thực hiện xử lý, khi địa chỉ thật sự có một tài khoản, thì endpoint sẽ hành xử khác nhau đối với tài khoản thật so với tài khoản bịa. Một kẻ tấn công nhìn thấy được sự khác biệt đó, trong phản hồi, trong mã trạng thái, hay chỉ trong thời gian phản hồi, giờ đây có một oracle cho biết email nào đã đăng ký với bạn. Biểu mẫu đặt lại là một chỗ rò rỉ liệt kê tài khoản kinh điển chính vì lý do này: cách khắc phục ngây thơ cho quả bom thư lại tạo ra lỗi liệt kê.

Cách khắc phục thật sự phải làm cả hai việc cùng một lúc, và hai nửa đó tách biệt nhau. Thứ nhất, rate-limit theo địa chỉ email đã chuẩn hóa bất kể có tài khoản hay không. Khóa giới hạn chính là bản thân địa chỉ đó, viết chữ thường và cắt khoảng trắng để Victim@victim@ dùng chung một bucket, và bộ đếm được áp dụng trước khi bạn tra cứu bất cứ thứ gì. Bộ đếm đó phải nằm trong một kho lưu trữ dùng chung và bền vững, không phải bộ nhớ của một tiến trình, nếu không nó bốc hơi khi khởi động lại và chẳng làm được gì trên nhiều instance. Thứ hai, phản hồi giống hệt trong mọi trường hợp: cùng một trạng thái, cùng một thông báo "nếu địa chỉ đó có tài khoản, chúng tôi đã gửi một liên kết," cùng một dáng thời gian, dù địa chỉ đó có phải của bạn hay không. Bạn vẫn chỉ thật sự gửi email khi có một tài khoản đằng sau nó. Nhưng không có gì mà người ngoài quan sát được thay đổi dựa trên bí mật đó. Rate limit bảo vệ bên thứ ba; phản hồi thời gian không đổi bảo vệ sự thật về việc ai có tài khoản.

Bài học chung này vươn xa hơn cả chuyện đặt lại mật khẩu. Bất kỳ endpoint không cần xác thực nào gây ra một hệ quả trong thế giới thực, gửi một email, gửi một SMS, gọi một webhook, không chỉ đơn thuần là một phần trong bề mặt tấn công của bạn. Nó là một vũ khí nhắm vào bất kỳ ai ở đầu bên kia, và hóa đơn cho việc khai hỏa nó giáng xuống uy tín của bạn, chứ không phải của kẻ tấn công. Rate-limit theo đối tượng bị tác động, tức là người nhận, chứ không phải người gọi. Và làm điều đó mà không để sự hiện diện hay vắng mặt của trạng thái bí mật thay đổi những gì người quan sát nhìn thấy.

Biểu mẫu đặt lại mật khẩu trông có vẻ như đường ống. Nó là đúng cái mảnh đường ống sẽ vui vẻ phun vào bất kỳ ai trên thế giới theo lệnh. Hãy đo đếm nó cho tương xứng.

Đo đếm một endpoint gây hệ quả không cần xác thực mà không làm lộ ai có tài khoản khó nhằn hơn vẻ ngoài của nó. Authagonal cung cấp sẵn luồng đặt lại đã được rate-limit và an toàn trước liệt kê tài khoản, để uy tín người gửi của bạn không bao giờ chỉ cách sự sụp đổ đúng một vòng lặp curl.