Skip to content

[SECURITY] Missing Rate Limiting on Registration Endpoint #36

Description

@1234-ad

🔒 Security Issue: Missing Rate Limiting on Registration Endpoint

Severity: HIGH

Description

The /register endpoint in backend/main.go has no rate limiting, making it vulnerable to abuse and DoS attacks. An attacker could:

  • Spam registration requests to exhaust resources
  • Trigger excessive email sends (Gmail API quota abuse)
  • Cause database performance degradation
  • Exhaust ntfy server resources

Affected Code

backend/main.go - Line 265:

mux.HandleFunc("GET /register", register)

Current Behavior

  • ❌ No rate limiting
  • ❌ No request throttling
  • ❌ No IP-based restrictions
  • ❌ No CAPTCHA or bot protection

Attack Scenarios

1. Registration Spam

# Attacker can spam registrations
for i in {1..1000}; do
  curl "https://naarad-api.metakgp.org/register" \
    --cookie "heimdall=valid_token" &
done

2. Email Quota Exhaustion

  • Gmail API has daily sending limits
  • Attacker could exhaust quota, preventing legitimate users from receiving credentials
  • Could trigger Gmail account suspension

3. Database Performance

  • Excessive INSERT operations
  • SQLite write lock contention
  • Potential database corruption under heavy load

Recommended Solution

Option 1: Implement Rate Limiting Middleware (Recommended)

Install rate limiting package:

go get golang.org/x/time/rate

Add rate limiter:

package main

import (
    "golang.org/x/time/rate"
    "sync"
)

var (
    // Global rate limiter: 5 requests per minute per IP
    limiters = make(map[string]*rate.Limiter)
    mu       sync.Mutex
)

func getLimiter(ip string) *rate.Limiter {
    mu.Lock()
    defer mu.Unlock()

    limiter, exists := limiters[ip]
    if !exists {
        limiter = rate.NewLimiter(rate.Every(time.Minute/5), 5) // 5 req/min
        limiters[ip] = limiter
    }

    return limiter
}

func RateLimitMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ip := r.Header.Get("X-Real-IP")
        if ip == "" {
            ip = r.RemoteAddr
        }

        limiter := getLimiter(ip)
        if !limiter.Allow() {
            http.Error(w, "Rate limit exceeded. Please try again later.", http.StatusTooManyRequests)
            return
        }

        next.ServeHTTP(w, r)
    })
}

Apply to registration endpoint:

mux.Handle("GET /register", RateLimitMiddleware(http.HandlerFunc(register)))

Option 2: Use Existing Rate Limiting Library

go get github.com/didip/tollbooth/v7
import (
    "github.com/didip/tollbooth/v7"
    "github.com/didip/tollbooth/v7/limiter"
)

func main() {
    // ... existing code ...

    // Create rate limiter: 5 requests per minute
    lmt := tollbooth.NewLimiter(5, &limiter.ExpirableOptions{
        DefaultExpirationTTL: time.Minute,
    })

    mux.Handle("GET /register", tollbooth.LimitFuncHandler(lmt, register))
}

Option 3: Nginx Rate Limiting (Infrastructure Level)

Add to nginx configuration:

limit_req_zone $binary_remote_addr zone=register_limit:10m rate=5r/m;

location /register {
    limit_req zone=register_limit burst=2 nodelay;
    proxy_pass http://naarad-api:5173;
}

Recommended Rate Limits

Endpoint Rate Limit Burst Reasoning
/register 5 req/min 2 User registration is infrequent
/health 60 req/min 10 Health checks need higher limit

Additional Security Measures

  1. CAPTCHA Integration

    • Add reCAPTCHA or hCaptcha to frontend
    • Verify CAPTCHA token in backend before registration
  2. Email Verification

    • Send verification link instead of credentials
    • Require email confirmation before account activation
  3. Monitoring & Alerting

    • Log registration attempts
    • Alert on suspicious patterns (many requests from same IP)
    • Track Gmail API quota usage
  4. IP Blacklisting

    • Automatically blacklist IPs that exceed rate limits
    • Implement temporary bans (e.g., 1 hour)

Testing Rate Limiting

# Test rate limit
for i in {1..10}; do
  echo "Request $i:"
  curl -w "\nHTTP Status: %{http_code}\n" \
    "https://naarad-api.metakgp.org/register" \
    --cookie "heimdall=valid_token"
  sleep 1
done

# Expected: First 5 succeed, rest return 429 (Too Many Requests)

Impact Assessment

Without Rate Limiting With Rate Limiting
❌ Vulnerable to spam ✅ Protected
❌ Resource exhaustion ✅ Resource protected
❌ Email quota abuse ✅ Quota protected
❌ No cost control ✅ Cost controlled

References

Priority

HIGH - Should be implemented before the service scales to prevent abuse.


Related: This complements the security improvements in PR #35

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions