This vulnerability occurs when an application transmits sensitive data, such as passwords, session tokens, or personal information, over an unencrypted channel (like HTTP). An attacker on the same network (e.g., public Wi-Fi) can “sniff” this traffic and steal the data, leading to account compromise or data breaches.
Transmitting data in cleartext is a critical failure of confidentiality. It can lead to the widespread theft of user credentials, session hijacking, and the exposure of all data your application handles. This directly violates compliance standards like PCI-DSS and GDPR, leading to severe fines and a complete loss of user trust.
Reference Details
CWE ID:CWE-319OWASP Top 10 (2021): A02:2021 - Cryptographic Failures
Severity: High
This is controlled by SECURE_SSL_REDIRECT in settings.py. In a production deployment behind a reverse proxy (like Nginx), you must also ensure the proxy is configured to pass the correct headers.
The application is deployed without SSL redirection, allowing users to access the site and submit forms over HTTP.
# settings.py (Production)# DANGEROUS: The application will not redirect HTTP requests to HTTPS.# If a user bookmarks or types "http://...", they will be insecure.SESSION_COOKIE_SECURE = FalseCSRF_COOKIE_SECURE = FalseSECURE_SSL_REDIRECT = False
The SECURE_SSL_REDIRECT is True, but the reverse proxy (Nginx) doesn’t set the X-Forwarded-Proto header. Django won’t know it’s behind a secure connection and may cause a redirect loop or serve insecure content.
In your production settings.py, set SECURE_SSL_REDIRECT, SESSION_COOKIE_SECURE, and CSRF_COOKIE_SECURE to True. Configure your proxy to pass the X-Forwarded-Proto header and enable SECURE_PROXY_SSL_HEADER.
Use a tool like curl -I http://your-domain.com. Assert that the response is a 301 Moved Permanently with a Location header pointing to https://your-domain.com. Also, check your session cookies in a browser to ensure the “Secure” flag is set.
The SecurityConfig does not enforce a secure channel, allowing the app to serve requests over HTTP.
// config/SecurityConfig.java@Overrideprotected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().permitAll(); // DANGEROUS: No `.requiresChannel().anyRequest().requiresSecure()` // The app will happily serve sensitive data over HTTP.}
// config/SecurityConfig.java (Secure)@Overrideprotected void configure(HttpSecurity http) throws Exception { http // SECURE: This forces all requests to be over HTTPS. .requiresChannel() .anyRequest().requiresSecure() .and() .authorizeRequests() .anyRequest().permitAll();}
# application.properties (Secure)# SECURE: Tell Spring to trust the X-Forwarded-* headers from the proxyserver.forward-headers-strategy=FRAMEWORK# SECURE: Ensure cookies are only sent over HTTPSserver.servlet.session.cookie.secure=true
Use curl -I http://your-domain.com. Assert the response is a 302 Found with a Location header pointing to https://your-domain.com. Check the Set-Cookie header for the JSESSIONID cookie and verify it contains the Secure flag.
The cookie policy is set to None, allowing cookies to be sent over HTTP.
// Startup.cs - ConfigureServices()public void ConfigureServices(IServiceCollection services){ services.AddSession(options => { // DANGEROUS: Cookies will be sent over insecure channels. options.Cookie.SecurePolicy = CookieSecurePolicy.None; });}
Ensure app.UseHttpsRedirection() is present in your Configure method. Set all cookie policies to CookieSecurePolicy.Always in production. If behind a proxy, configure ForwardedHeadersOptions.
Use curl -I http://your-domain.com. Assert the response is a 301 Moved Permanently (or 307 Temporary Redirect) with a Location header pointing to https://your-domain.com. Check the Set-Cookie header for your session cookie and verify the Secure flag.
The secure option in config/session.php is set to false in production.
// config/session.php'secure' => false, // DANGEROUS// This allows the session cookie to be sent over HTTP,// even if the user just visits one page insecurely.
# .env (Production)APP_URL=[https://myapp.com](https://myapp.com)# SECURE: This tells Laravel to set the 'Secure' flag on cookiesSESSION_SECURE_COOKIE=true
// config/session.php// This reads the value from .env'secure' => env('SESSION_SECURE_COOKIE', false),
Use curl -I http://your-domain.com. Assert the response is a 301 Moved Permanently with a Location header pointing to https://your-domain.com. Check the Set-Cookie header for laravel_session and verify the Secure flag.
In Express, this is handled by checking the req.secure flag (or x-forwarded-proto header) and issuing a redirect. Cookie security is set in express-session.
Vulnerable Scenario 1: No HTTPS Redirect Middleware
The application runs and serves traffic over HTTP without any logic to redirect to HTTPS.
// app.jsconst express = require('express');const app = express();app.get('/', (req, res) => { // DANGEROUS: This will be served over HTTP if requested. res.send('Welcome!');});app.listen(80);
The session middleware is configured, but cookie.secure is not set to true for production.
// app.jsconst session = require('express-session');app.use(session({ secret: 'my-secret', cookie: { // DANGEROUS: The session cookie will be sent over HTTP. secure: false } }));
Use curl -I http://your-domain.com. Assert the response is a 302 Found with a Location header pointing to https://your-domain.com. Check the Set-Cookie header for connect.sid and verify the Secure flag.
# config/environments/production.rb# DANGEROUS: This is the default, but it should be true.# The app will not redirect HTTP to HTTPS.config.force_ssl = false
The session_store initializer does not set the secure flag.
# config/initializers/session_store.rb# DANGEROUS: 'secure' is not set to true, so the session# cookie will be sent over HTTP.Rails.application.config.session_store :cookie_store, key: '_my_app_session'
Set config.force_ssl = true in config/environments/production.rb. This one setting handles HTTP-to-HTTPS redirection, HSTS, and sets the Secure flag on cookies.
Use curl -I http://your-domain.com. Assert the response is a 301 Moved Permanently with a Location header pointing to https://your-domain.com. Check the Set-Cookie header for _my_app_session and verify the Secure flag.