Weakness reference
CWE-523

Unprotected Transport of Credentials

This weakness occurs when login credentials, API keys, authentication tokens, or other sensitive authentication data are transmitted over unencrypted…

01Summary

This weakness occurs when login credentials, API keys, authentication tokens, or other sensitive authentication data are transmitted over unencrypted channels—typically HTTP instead of HTTPS. An attacker on the same network or positioned to intercept traffic can capture these credentials in plain text, leading to account compromise or unauthorized access.

02How It Happens

Applications sometimes transmit credentials without encryption for convenience, legacy compatibility, or developer oversight. When a user submits a login form over HTTP, sends an API key in a plain-text request, or stores credentials in cookies without the Secure flag, the data travels across the network unencrypted. Any intermediary—a compromised router, a malicious WiFi hotspot, a network sniffer, or an ISP—can read the traffic and extract the credentials. Even if the credentials are hashed in a database, transmitting them unencrypted over the wire defeats that protection.

03Real-World Impact

Compromised credentials lead directly to account takeover. An attacker can log in as the legitimate user, access their data, modify their account, or pivot to other systems that share the same password. For administrative or API credentials, the impact scales to full application compromise. In regulated environments (healthcare, finance, payment processing), unencrypted credential transmission violates compliance standards (HIPAA, PCI-DSS, GDPR) and triggers mandatory breach notifications and fines.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import http.server
import urllib.parse

class LoginHandler(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        body = self.rfile.read(content_length).decode()
        params = urllib.parse.parse_qs(body)
        username = params.get('username', [''])[0]
        password = params.get('password', [''])[0]
        # Credentials received over plain HTTP, visible to any network observer
        self.authenticate_user(username, password)

Why it's vulnerable:
The server accepts POST requests over HTTP (not HTTPS), so the username and password travel unencrypted across the network and can be captured by anyone monitoring traffic.

Fixed pattern
import ssl
import http.server
import urllib.parse

context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain('cert.pem', 'key.pem')

class LoginHandler(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        body = self.rfile.read(content_length).decode()
        params = urllib.parse.parse_qs(body)
        username = params.get('username', [''])[0]
        password = params.get('password', [''])[0]
        # Credentials received over HTTPS; encrypted in transit
        self.authenticate_user(username, password)

# Server runs with SSL/TLS enabled
server = http.server.HTTPServer(('localhost', 443), LoginHandler)
server.socket = context.wrap_socket(server.socket, server_side=True)
Vulnerable pattern
<?php
// Form submitted over HTTP (not HTTPS)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $_POST['username'];
    $password = $_POST['password'];
    // Credentials transmitted unencrypted
    authenticate_user($username, $password);
}
?>
<form method="POST" action="http://example.com/login.php">
    <input type="text" name="username" />
    <input type="password" name="password" />
    <button type="submit">Login</button>
</form>

Why it's vulnerable:
The form posts to an HTTP URL, not HTTPS. Credentials are sent unencrypted and visible to network sniffers.

Fixed pattern
<?php
// Enforce HTTPS
if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off') {
    header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $_POST['username'];
    $password = $_POST['password'];
    // Credentials transmitted over HTTPS; encrypted in transit
    authenticate_user($username, $password);
}
?>
<form method="POST" action="https://example.com/login.php">
    <input type="text" name="username" />
    <input type="password" name="password" />
    <button type="submit">Login</button>
</form>

05Prevention Checklist

Enforce HTTPS site-wide.
Configure your web server to serve all pages over HTTPS and redirect HTTP requests to HTTPS. Use HSTS headers to instruct browsers to always use HTTPS.
Use valid, trusted SSL/TLS certificates.
Obtain certificates from a recognized certificate authority (CA). Self-signed certificates are better than nothing but may trigger browser warnings.
Secure authentication cookies.
Set the Secure flag on session cookies so they are only transmitted over HTTPS, and set HttpOnly to prevent JavaScript access.
Transmit API keys and tokens over HTTPS only.
Never embed credentials in URLs or send them over unencrypted channels. Use HTTPS for all API calls.
Audit third-party integrations.
Verify that any external services or embedded scripts your application communicates with also use HTTPS.
Test your configuration.
Use tools to verify that your site redirects HTTP to HTTPS and that certificates are valid and not expired.

06Signs You May Already Be Affected

Check your web server logs and network traffic for POST requests to HTTP endpoints (not HTTPS). Look for login forms or API endpoints that accept credentials over unencrypted connections. Review your SSL/TLS certificate configuration to ensure it covers all domains and is not expired. If users report browser warnings about insecure connections during login, or if your site is accessible over both HTTP and HTTPS without automatic redirection, you may be transmitting credentials unencrypted.

07Related Recent Vulnerabilities