Home Projects Portfolio Dashboard Export PDF Log in

Fortifying `estrella-tour`: Mitigating Rate Limit Bypass, Weak Tokens, and CSV Injection

The estrella-tour project recently implemented a series of crucial security enhancements aimed at bolstering user authentication and data integrity. These updates address several common vulnerabilities, making the application more resilient against various attack vectors.

The Problem

Our initial security audit revealed three key areas for improvement:

  1. IP-based Rate Limit Bypass: The rate limiting mechanism for critical endpoints like login, registration, and password reset relied on X-Forwarded-For headers. Unfortunately, client-provided X-Forwarded-For values can be easily spoofed, allowing malicious actors to bypass rate limits by cycling through forged IP addresses.
  2. Weak Session Token Entropy: Session tokens, fundamental to maintaining secure user sessions, were generated using Prisma's default cuid() function. While useful for unique identifiers, cuid() does not provide the cryptographic randomness required for high-entropy security tokens, making them potentially predictable and vulnerable to brute-force attacks.
  3. CSV/Excel Injection Vulnerability: The application's functionality to export passenger data to CSV or Excel formats introduced a risk of CSV injection. If a malicious user entered data starting with special characters like =, +, -, or @ into a field, it could be interpreted as a formula when opened in spreadsheet software, potentially leading to arbitrary code execution or data exfiltration.

The Solution: Comprehensive Security Patches

To address these vulnerabilities, we implemented targeted fixes:

Robust Rate Limiting

To prevent rate limit bypasses, the system now relies on the last X-Forwarded-For value from the request headers, as this is typically provided by the last proxy or load balancer and is less susceptible to client manipulation. This ensures that rate limits are enforced based on the most reliable IP address available.

function getClientIp(headers: Record<string, string | string[] | undefined>): string | undefined {
    const xForwardedFor = headers['x-forwarded-for'];
    if (typeof xForwardedFor === 'string') {
        // Get the last (most reliable) IP from the X-Forwarded-For chain
        return xForwardedFor.split(',').pop()?.trim();
    }
    // Fallback to X-Real-IP or remote address if X-Forwarded-For is not present
    return headers['x-real-ip'] as string | undefined;
}

// Usage in a rate limiting middleware
// const clientIp = getClientIp(request.headers);
// if (!clientIp || !rateLimiter.isAllowed(clientIp)) {
//     return response.status(429).send('Too many requests');
// }

Strengthening Session Tokens

Session tokens are now generated using crypto.randomBytes(32), a cryptographically secure random number generator provided by Node.js. This method generates a 32-byte (256-bit) random value, which is then typically converted to a hexadecimal string, ensuring high entropy and making the tokens virtually impossible to guess or brute-force. This aligns session token robustness with that of password reset tokens.

import crypto from 'crypto';

function generateSecureToken(): string {
    // Generates 32 cryptographically strong random bytes
    const tokenBuffer = crypto.randomBytes(32);
    // Converts the buffer to a hexadecimal string for storage/transmission
    return tokenBuffer.toString('hex');
}

// Example of usage with Prisma
// await prisma.session.create({
//     data: {
//         userId: userId,
//         token: generateSecureToken(), // Store the secure token
//         expiresAt: new Date(Date.now() + SESSION_DURATION)
//     }
// });

Preventing CSV Injection

All values exported to CSV or Excel are now sanitized. Specifically, any value starting with the characters =, +, -, or @ is prepended with a single quote ('). This instructs spreadsheet software to treat the value as plain text, neutralizing it as a potential formula and preventing injection attacks.

function sanitizeCsvValue(value: string): string {
    // Characters that can trigger formula execution in spreadsheets
    const problematicStarters = ['=', '+', '-', '@'];

    if (problematicStarters.some(starter => value.startsWith(starter))) {
        return `'${value}`; // Prepend with a single quote to neutralize
    }
    return value;
}

// Example during data export
// const sanitizedName = sanitizeCsvValue(passenger.name);
// const sanitizedEmail = sanitizeCsvValue(passenger.email);
// const csvRow = `${sanitizedName},${sanitizedEmail}\n`;

Enhancing Application Security

These changes significantly enhance the overall security posture of estrella-tour. By addressing common and critical vulnerabilities, we've reduced the attack surface, protected user accounts from various compromise methods, and ensured the integrity of data exports. Proactive measures like these are essential in maintaining user trust and compliance.

Lessons Learned

  1. Trust no input: Always validate and sanitize all external input, especially from headers or user-generated content.
  2. Cryptographic strength matters: When generating security-critical identifiers like session tokens, always use cryptographically strong random number generators.
  3. Beyond the obvious: Security threats can come from unexpected vectors, like data export functionalities. A comprehensive security review covers all user interaction points.

Key Insight

Security is not a one-time task but an ongoing commitment. Regularly reviewing and improving security measures, even for seemingly minor details, builds a robust and trustworthy application environment.


Generated with Gitvlg.com

Fortifying `estrella-tour`: Mitigating Rate Limit Bypass, Weak Tokens, and CSV Injection
p

pedro marzano

Author

Share: