HIGH dictionary attackfibercockroachdb

Dictionary Attack in Fiber with Cockroachdb

Dictionary Attack in Fiber with Cockroachdb — how this specific combination creates or exposes the vulnerability

A dictionary attack in a Fiber application that uses CockroachDB typically arises from weak authentication endpoints and predictable user identifiers. When login or password-reset endpoints rely on sequential or easily guessable identifiers (e.g., numeric user IDs or usernames), an attacker can systematically submit common credentials or iterate through likely usernames to discover valid accounts. Because CockroachDB is often used in distributed, horizontally scaled environments, developers may assume network-level protections are sufficient and inadvertently expose authentication logic without adequate rate limiting or account enumeration defenses.

In this combination, the risk is not CockroachDB itself being vulnerable to dictionary attacks, but rather how the application exposes authentication surfaces that an attacker can probe. For example, if the login route uses a username or email query parameter without proper throttling, an attacker can attempt many passwords for a given user or enumerate existing users by observing timing differences or response messages. Because Fiber is a fast, low-friction framework, it is easy to inadvertently build endpoints that do not uniformly enforce authentication checks, allowing attackers to leverage automation to test credentials against user accounts stored in CockroachDB.

Consider an endpoint that queries CockroachDB by a user-supplied identifier without ensuring constant-time behavior or masking whether the identifier exists. An attacker can send many requests with guessed usernames or emails and infer valid accounts based on subtle differences in response messages or timing. If rate limiting is not applied globally or is bypassed for certain paths, the attacker can make a high volume of attempts. The presence of CockroachDB does not inherently mitigate or exacerbate this; the exposure depends on how authentication routes are designed, what validation and rate limiting are applied, and whether error handling leaks information about account existence.

Another vector involves password reset or token verification endpoints that use predictable tokens or identifiers. If token generation lacks sufficient entropy and the lookup in CockroachDB is performed via a direct query without additional access controls, an attacker can iterate through token values to hijack password resets. The Fiber application must ensure that password reset tokens are cryptographically random, single-use, and bound to user accounts with strict validation before any database operation. Without these controls, a dictionary or brute-force approach against token or identifier values becomes feasible.

Additionally, if the application exposes user enumeration through account creation or profile lookup endpoints, an attacker can determine whether a given username or email already exists in CockroachDB before attempting authentication. Even without direct timing differences, HTTP status codes or response bodies can reveal whether an account is present, enabling targeted dictionary attempts. Defense requires designing these endpoints to behave similarly for valid and invalid inputs, enforcing rate limits, and ensuring that tokens and identifiers are opaque and unguessable.

Cockroachdb-Specific Remediation in Fiber — concrete code fixes

To mitigate dictionary attacks in a Fiber application using CockroachDB, apply consistent authentication controls, parameterized queries, and rate limiting. Below are concrete code examples that demonstrate secure patterns for login, password reset, and user lookup scenarios.

Secure login with parameterized query and constant-time comparison

Use a parameterized query to prevent injection and avoid branching behavior based on whether the user exists. Hash and compare passwords with a constant-time function to prevent timing leaks.

package main

import (
	"context"
	"crypto/subtle"
	"net/http"

	"github.com/gofiber/fiber/v2"
	"github.com/jackc/pgx/v5/pgxpool"
	"golang.org/x/crypto/bcrypt"
)

func loginHandler(pool *pgxpool.Pool) fiber.Handler {
	return func(c *fiber.Ctx) error {
		var req struct {
			Email    string `json:"email"`
			Password string `json:"password"`
		}
		if err := c.BodyParser(&req); err != nil {
			return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid request"})
		}

		ctx := c.Context()
		var hashedPassword string
		var userID int
		err := pool.QueryRow(ctx, `SELECT id, password_hash FROM users WHERE email = $1`, req.Email).Scan(&userID, &hashedPassword)
		if err != nil {
			// Use a dummy hash to keep response time consistent
			dummyHash := bcrypt.NewHasher().HashString([]byte("dummy"), bcrypt.DefaultCost)
			bcrypt.CompareHashAndPassword([]byte(dummyHash), []byte(req.Password))
			return c.Status(http.StatusUnauthorized).JSON(fiber.Map{"error": "invalid credentials"})
		}

		if subtle.ConstantTimeCompare([]byte(hashedPassword), []byte(hashPassword(req.Password))) != 1 {
			return c.Status(http.StatusUnauthorized).JSON(fiber.Map{"error": "invalid credentials"})
		}

		// Issue session/token here
		return c.JSON(fiber.Map{"user_id": userID})
	}
}

func hashPassword(password string) string {
	hash, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	return string(hash)
}

Rate-limited password reset with opaque token

Generate a high-entropy token, store it with the user in CockroachDB, and enforce rate limits on verification attempts to prevent brute-force dictionary attacks.

package main

import (
	"context"
	"crypto/rand"
	"encoding/base64"
	"net/http"
	"time"

	"github.com/gofiber/fiber/v2"
	"github.com/jackc/pgx/v5/pgxpool"
)

type ResetToken struct {
	Token     string    `db:"token"`
	ExpiresAt time.Time `db:"expires_at"`
}

func requestReset(c *fiber.Ctx) error {
	email := c.FormValue("email")
	// Generate cryptographically random token
	tokenBytes := make([]byte, 32)
	rand.Read(tokenBytes)
	token := base64.URLEncoding.EncodeToString(tokenBytes)

	ctx := c.Context()
	pool := c.Locals("db").(*pgxpool.Pool)
	_, err := pool.Exec(ctx, `
		INSERT INTO password_reset_tokens(user_email, token, expires_at) 
		VALUES ($1, $2, $3)
	`, email, token, time.Now().Add(1*time.Hour))
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "could not queue reset"})
	}
	// Send email with link containing token
	return c.JSON(fiber.Map{"message": "reset instructions sent"})
}

func verifyReset(c *fiber.Ctx) error {
	var payload struct {
		Token  string `json:"token"`
		NewPwd string `json:"new_password"`
	}
	if err := c.BodyParser(&payload); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid request"})
	}

	ctx := c.Context()
	pool := c.Locals("db").(*pgxpool.Pool)
	var tokenRecord ResetToken
	err := pool.QueryRow(ctx, `SELECT token, expires_at FROM password_reset_tokens WHERE token = $1`, payload.Token).Scan(&tokenRecord.Token, &tokenRecord.ExpiresAt)
	if err != nil || tokenRecord.ExpiresAt.Before(time.Now()) {
		return c.Status(http.StatusUnauthorized).JSON(fiber.Map{"error": "invalid or expired token"})
	}

	hash, _ := bcrypt.GenerateFromPassword([]byte(payload.NewPwd), bcrypt.DefaultCost)
	_, err = pool.Exec(ctx, `UPDATE users SET password_hash = $1 WHERE email IN (SELECT user_email FROM password_reset_tokens WHERE token = $2)`, hash, payload.Token)
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "could not update password"})
	}

	// Clean up used token
	pool.Exec(ctx, `DELETE FROM password_reset_tokens WHERE token = $1`, payload.Token)
	return c.JSON(fiber.Map{"message": "password updated"})
}

User enumeration defense with uniform responses and rate limiting

Ensure that profile or lookup endpoints do not leak existence information and are protected by rate limits to deter enumeration and dictionary attempts.

package main

import (
	"context"
	"net/http"

	"github.com/gofiber/fiber/v2"
	"github.com/jackc/pgx/v5/pgxpool"
)

func getProfile(c *fiber.Ctx) error {
	username := c.Params("username")
	ctx := c.Context()
	pool := c.Locals("db").(*pgxpool.Pool)

	var displayName string
	// Always query with the provided username; do not branch on existence
	err := pool.QueryRow(ctx, `SELECT display_name FROM profiles WHERE username = $1`, username).Scan(&displayName)
	if err != nil {
		// Return a generic response regardless of whether the user exists
		return c.JSON(fiber.Map{"display_name": "N/A"})
	}
	return c.JSON(fiber.Map{"display_name": displayName})
}

Apply global rate limiting in Fiber to restrict request volume per IP or API key, reducing the effectiveness of dictionary attacks.

package main

import (
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/limiter/v2/middleware/redis"
	"github.com/redis/go-redis/v9"
)

func main() {
	client := redis.NewClient(redis.Config{
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	})

	rateLimiter := redis.New(redis.Config{
		Client:  client,
		Rate:    redis.Rate{Period: time.Minute, Limit: 100},
		KeyGenerator: func(c *fiber.Ctx) (string, error) {
			return c.IP(), nil
		},
	})

	app := fiber.New()
	app.Use(rateLimiter)
	// Define routes here
}

By combining parameterized queries, constant-time password verification, opaque tokens, and rate limiting, the application reduces the risk of dictionary attacks against authentication flows that rely on CockroachDB for identity storage.

Frequently Asked Questions

How does middleBrick detect dictionary attack risks in API scans?
middleBrick runs 12 security checks in parallel, including Authentication, Rate Limiting, and Input Validation. It tests unauthenticated endpoints for weak identifiers, missing rate limits, and account enumeration patterns, then reports findings with severity and remediation guidance.
Can I use the free tier to scan my API for dictionary attack risks?
Yes. The free tier provides 3 scans per month, which is sufficient to run an initial scan against your API endpoints and receive prioritized findings, including authentication-related risks like dictionary attacks.