[GH-ISSUE #965] [BUG] No restrictions on sending "Forgot Password" emails, which may pose a security risk #352

Closed
opened 2026-02-27 08:16:48 +03:00 by kerem · 4 comments
Owner

Originally created by @Insulinocytus on GitHub (Sep 1, 2024).
Original GitHub issue: https://github.com/lldap/lldap/issues/965

Describe the bug

I tested sending multiple password reset emails to myself, and there were no warnings or limitations triggered, even after sending over a dozen emails.

Since my SMTP service charges per email, a hacker could easily guess my username (e.g., "admin") and send unlimited emails, potentially leading to significant costs for me.

Are there any plans to add CAPTCHA support to prevent such abuse?

I am not a web engineer myself, so any guidance or suggestions on how to address this issue would be greatly appreciated.

To Reproduce
Just send password reset email.

Expected behavior
You could consider setting a fixed interval, such as 1 minute, between sending emails to the same ID. Alternatively, requiring CAPTCHA verification before each email is sent could be another effective solution.

Logs
null

Additional context
null

Originally created by @Insulinocytus on GitHub (Sep 1, 2024). Original GitHub issue: https://github.com/lldap/lldap/issues/965 **Describe the bug** I tested sending multiple password reset emails to myself, and there were no warnings or limitations triggered, even after sending over a dozen emails. Since my SMTP service charges per email, a hacker could easily guess my username (e.g., "admin") and send unlimited emails, potentially leading to significant costs for me. Are there any plans to add CAPTCHA support to prevent such abuse? I am not a web engineer myself, so any guidance or suggestions on how to address this issue would be greatly appreciated. **To Reproduce** Just send password reset email. **Expected behavior** You could consider setting a fixed interval, such as 1 minute, between sending emails to the same ID. Alternatively, requiring CAPTCHA verification before each email is sent could be another effective solution. **Logs** null **Additional context** null
kerem 2026-02-27 08:16:48 +03:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@nitnelave commented on GitHub (Sep 1, 2024):

This is such a common problem with services that I feel that it would be a shame if everyone implemented it independently, and badly.

I feel like it would be better achieved through a local SMTP proxy with rate limiting.

<!-- gh-comment-id:2323303961 --> @nitnelave commented on GitHub (Sep 1, 2024): This is such a common problem with services that I feel that it would be a shame if everyone implemented it independently, and badly. I feel like it would be better achieved through a local SMTP proxy with rate limiting.
Author
Owner

@Insulinocytus commented on GitHub (Sep 1, 2024):

This is such a common problem with services that I feel that it would be a shame if everyone implemented it independently, and badly.

Agree.

I feel like it would be better achieved through a local SMTP proxy with rate limiting.

Perhaps I can solve this by modifying my reverse proxy settings.

Anyway, thanks for your reply.

<!-- gh-comment-id:2323370453 --> @Insulinocytus commented on GitHub (Sep 1, 2024): > This is such a common problem with services that I feel that it would be a shame if everyone implemented it independently, and badly. Agree. > I feel like it would be better achieved through a local SMTP proxy with rate limiting. Perhaps I can solve this by modifying my reverse proxy settings. Anyway, thanks for your reply.
Author
Owner

@nitnelave commented on GitHub (Sep 1, 2024):

Yeah, you can either do that by applying limits to the incoming HTTP queries (which is always good if you're afraid of DDoS), or by applying limits on the outgoing SMTP by using an SMTP proxy before forwarding to your actual provider.

<!-- gh-comment-id:2323371664 --> @nitnelave commented on GitHub (Sep 1, 2024): Yeah, you can either do that by applying limits to the incoming HTTP queries (which is always good if you're afraid of DDoS), or by applying limits on the outgoing SMTP by using an SMTP proxy before forwarding to your actual provider.
Author
Owner

@Insulinocytus commented on GitHub (Sep 2, 2024):

I'm using Traefik as a reverse proxy. Here's my solution.
In this way, each source can only reset the password once every 30 seconds.

# dynamic.yml

http:
  middlewares:
    lldapForgetPasswordMailRateLimit:
      ratelimit:
        average: 1
        period: 30s
        sourceCriterion:
          ipstrategy:
            excludedIPs:
              - 10.0.0.0/8
              - 172.16.0.0/12
              - 192.168.0.0/16
  routers:
    lldap:
      rule: Host(`lldap.your.site`)
      entryPoints: websecure
      service: lldap
      priority: 1
    lldap-forget-password-mail-request:
      rule: Host(`lldap.your.site`) && PathRegexp(`^/auth/reset/step1/.+$`)
      entryPoints: websecure
      service: lldap
      middlewares: lldapForgetPasswordMailRateLimit
      priority: 2
    lldap-forget-password-mail-request-exclude:
      rule: Host(`lldap.your.site`) && Path(`/auth/reset/step1/lldap_unlikely_very_long_user_name`)
      entryPoints: websecure
      service: lldap
      priority: 3

image

github.com/lldap/lldap@6cf0f6df06/app/src/infra/api.rs (L180-L214)

<!-- gh-comment-id:2323761468 --> @Insulinocytus commented on GitHub (Sep 2, 2024): I'm using Traefik as a reverse proxy. Here's my solution. In this way, each source can only reset the password once every 30 seconds. ```yaml # dynamic.yml http: middlewares: lldapForgetPasswordMailRateLimit: ratelimit: average: 1 period: 30s sourceCriterion: ipstrategy: excludedIPs: - 10.0.0.0/8 - 172.16.0.0/12 - 192.168.0.0/16 routers: lldap: rule: Host(`lldap.your.site`) entryPoints: websecure service: lldap priority: 1 lldap-forget-password-mail-request: rule: Host(`lldap.your.site`) && PathRegexp(`^/auth/reset/step1/.+$`) entryPoints: websecure service: lldap middlewares: lldapForgetPasswordMailRateLimit priority: 2 lldap-forget-password-mail-request-exclude: rule: Host(`lldap.your.site`) && Path(`/auth/reset/step1/lldap_unlikely_very_long_user_name`) entryPoints: websecure service: lldap priority: 3 ``` ![image](https://github.com/user-attachments/assets/8c6fd9c9-605b-4142-9ece-766e7639a006) https://github.com/lldap/lldap/blob/6cf0f6df0639425f792af243b4345acc9b737fa8/app/src/infra/api.rs#L180-L214
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/lldap-lldap#352
No description provided.