Use of Hard-coded Credentials

Description

Use of Hard-coded Credentials occurs when a product contains hard-coded credentials such as passwords, cryptographic keys, or API tokens embedded directly in source code, configuration files, or compiled binaries. These credentials may be used for inbound authentication (allowing external parties to authenticate to the software) or outbound authentication (the software authenticating to external services). Hard-coded credentials create a significant security risk because they cannot be easily changed, are often discoverable through reverse engineering or source code access, and are typically shared across all installations of the software.

Risk

Hard-coded credentials consistently rank among the most dangerous software weaknesses. CVE-2025-2538 in Esri Portal for ArcGIS (CVSS 9.8 Critical) allows unauthenticated attackers to gain administrative access through hard-coded credentials, affecting government, utilities, and transportation sectors. CVE-2025-36087 in IBM Security Verify Access exposes hard-coded credentials in versions 10.0.0-10.0.9 and 11.0.0. Over 40% of data breaches involve weak or exposed credentials. The Mirai botnet exploited IoT devices with factory-default hard-coded credentials to launch massive DDoS attacks. Developers frequently commit code with embedded credentials to public repositories.

Solution

Never embed credentials in source code. Use environment variables, configuration files with restricted permissions, or secrets management solutions (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault). Implement credential rotation mechanisms. Use unique credentials per installation. For IoT devices, require credential change on first use. Scan code repositories for accidentally committed credentials. Use pre-commit hooks to prevent credential commits. Implement runtime credential injection. For API keys, use short-lived tokens with automatic rotation.

Common Consequences

ImpactDetails
AuthenticationScope: Complete Bypass

Hard-coded credentials provide immediate authentication bypass to anyone who discovers them.
Access ControlScope: Unauthorized Access

Attackers gain access to systems, data, and functionality protected by the hard-coded credentials.
ConfidentialityScope: Mass Compromise

Same credentials across all installations means one discovery compromises all deployments.

Example Code + Solution Code

Vulnerable Code

// VULNERABLE: Hard-coded database password
public class DatabaseConnection {
    private static final String DB_HOST = "db.example.com";
    private static final String DB_USER = "admin";
    private static final String DB_PASSWORD = "SuperSecret123!";  // Hard-coded!

    public Connection getConnection() throws SQLException {
        return DriverManager.getConnection(
            "jdbc:mysql://" + DB_HOST + "/mydb",
            DB_USER,
            DB_PASSWORD
        );
    }
}

// VULNERABLE: Hard-coded API key
public class PaymentService {
    private static final String STRIPE_API_KEY = "sk_live_51H7...abc123";  // Exposed!

    public void processPayment(Payment payment) {
        Stripe.apiKey = STRIPE_API_KEY;
        // Process payment
    }
}
# VULNERABLE: Credentials in source code
import requests

API_KEY = "AIzaSyD-abc123xyz789"  # Hard-coded Google API key!
SECRET_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"  # AWS secret!

def connect_to_api():
    headers = {"Authorization": f"Bearer {API_KEY}"}
    return requests.get("https://api.example.com/data", headers=headers)

# VULNERABLE: Hard-coded admin credentials for backdoor
ADMIN_USERNAME = "admin"
ADMIN_PASSWORD = "admin123"  # Default backdoor!

def authenticate(username, password):
    if username == ADMIN_USERNAME and password == ADMIN_PASSWORD:
        return True  # Backdoor access
    return check_database(username, password)
// VULNERABLE: Credentials in client-side code
const config = {
    apiKey: 'sk-1234567890abcdef',  // Exposed in browser!
    firebaseConfig: {
        apiKey: "AIzaSyD-abc123",    // Public API key
        authDomain: "myapp.firebaseapp.com",
        databaseURL: "https://myapp.firebaseio.com"
    }
};

// VULNERABLE: SSH key in source
const SSH_PRIVATE_KEY = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA PRIVATE KEY-----`;

async function deployToServer() {
    const conn = await ssh.connect({
        host: 'production.server.com',
        username: 'deploy',
        privateKey: SSH_PRIVATE_KEY  // Hard-coded private key!
    });
}

Fixed Code

// SAFE: Credentials from environment or secrets manager
import com.amazonaws.services.secretsmanager.AWSSecretsManager;

public class SecureDatabaseConnection {
    private final AWSSecretsManager secretsManager;

    public SecureDatabaseConnection(AWSSecretsManager secretsManager) {
        this.secretsManager = secretsManager;
    }

    public Connection getConnection() throws Exception {
        // Get credentials from secrets manager
        GetSecretValueResult secret = secretsManager.getSecretValue(
            new GetSecretValueRequest().withSecretId("prod/db/credentials")
        );

        JSONObject creds = new JSONObject(secret.getSecretString());
        String host = creds.getString("host");
        String user = creds.getString("username");
        String password = creds.getString("password");

        return DriverManager.getConnection(
            "jdbc:mysql://" + host + "/mydb",
            user,
            password
        );
    }
}

// SAFE: API key from environment with validation
public class SecurePaymentService {
    private final String stripeApiKey;

    public SecurePaymentService() {
        this.stripeApiKey = System.getenv("STRIPE_API_KEY");
        if (stripeApiKey == null || stripeApiKey.isEmpty()) {
            throw new IllegalStateException("STRIPE_API_KEY environment variable not set");
        }
    }

    public void processPayment(Payment payment) {
        Stripe.apiKey = stripeApiKey;
        // Process payment
    }
}
# SAFE: Credentials from environment and secrets manager
import os
import boto3
from botocore.exceptions import ClientError

def get_secret(secret_name):
    """Retrieve secret from AWS Secrets Manager."""
    client = boto3.client('secretsmanager')

    try:
        response = client.get_secret_value(SecretId=secret_name)
        return json.loads(response['SecretString'])
    except ClientError as e:
        raise RuntimeError(f"Failed to retrieve secret: {e}")

def connect_to_api():
    # Get API key from environment or secrets manager
    api_key = os.environ.get('API_KEY')

    if not api_key:
        secrets = get_secret('prod/api/credentials')
        api_key = secrets['api_key']

    headers = {"Authorization": f"Bearer {api_key}"}
    return requests.get("https://api.example.com/data", headers=headers)

# SAFE: No backdoor credentials - use proper authentication
def authenticate(username, password):
    # Always check against secure credential store
    user = get_user_from_database(username)

    if not user:
        # Constant-time comparison to prevent timing attacks
        dummy_hash = generate_dummy_hash()
        verify_password(password, dummy_hash)
        return False

    return verify_password(password, user.password_hash)
// SAFE: Credentials from environment (server-side only)
require('dotenv').config();

const config = {
    // Loaded from environment variables
    apiKey: process.env.API_KEY,
    stripeKey: process.env.STRIPE_SECRET_KEY
};

// Validate required credentials at startup
const requiredEnvVars = ['API_KEY', 'STRIPE_SECRET_KEY', 'DATABASE_URL'];
for (const envVar of requiredEnvVars) {
    if (!process.env[envVar]) {
        throw new Error(`Missing required environment variable: ${envVar}`);
    }
}

// SAFE: SSH key from file with proper permissions
const fs = require('fs');
const path = require('path');

async function deployToServer() {
    const keyPath = process.env.SSH_KEY_PATH || path.join(os.homedir(), '.ssh', 'deploy_key');

    // Verify key file permissions (should be 0600)
    const stats = fs.statSync(keyPath);
    const mode = stats.mode & 0o777;
    if (mode !== 0o600) {
        throw new Error('SSH key file has insecure permissions');
    }

    const privateKey = fs.readFileSync(keyPath, 'utf8');

    const conn = await ssh.connect({
        host: process.env.DEPLOY_HOST,
        username: process.env.DEPLOY_USER,
        privateKey: privateKey
    });
}

// SAFE: Client-side code uses only public configuration
// Sensitive operations happen server-side
const publicConfig = {
    firebaseConfig: {
        apiKey: "AIzaSyD-abc123",  // Firebase public key (designed for client)
        authDomain: "myapp.firebaseapp.com",
        projectId: "myapp"
        // No secrets here - sensitive ops use Firebase Security Rules
    }
};

Exploited in the Wild

Esri Portal for ArcGIS (Esri, 2025)

CVE-2025-2538 (CVSS 9.8 Critical) in Esri Portal for ArcGIS 11.4 and below contains hard-coded credentials enabling unauthenticated remote attackers to gain administrative access to GIS systems used in government, utilities, transportation, and environmental management.

IBM Security Verify Access (IBM, 2025)

CVE-2025-36087 in IBM Security Verify Access versions 10.0.0-10.0.9 and 11.0.0 exposes hard-coded credentials, affecting finance, healthcare, government, and critical infrastructure sectors that rely on robust access controls.

Mirai Botnet IoT Attacks (Multiple, 2016-Present)

The Mirai botnet exploited IoT devices with hard-coded factory credentials, compromising millions of devices for massive DDoS attacks that took down major internet services including Dyn DNS.


Tools to test/exploit

  • TruffleHog — scan for secrets in git repositories.

  • GitLeaks — detect hard-coded secrets in code.

  • Detect-Secrets — pre-commit hook for credential detection.


CVE Examples


References

  1. MITRE. "CWE-798: Use of Hard-coded Credentials." https://cwe.mitre.org/data/definitions/798.html

  2. OWASP. "Use of hard-coded password." https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password