Sensitive information disclosure: error messages, versions and exposed data
Sensitive information disclosure covers all situations where an application reveals technical, structural, or business data that shouldn't be accessible to an unprivileged user. These pieces of information, taken individually, may seem harmless. Combined, they allow an attacker to build accurate reconnaissance before launching a targeted attack.
Detailed error messages
Verbose error messages reveal the application's internal structure: stack traces, file names, SQL queries, line numbers. An unhandled exception returning the full stack trace reveals the language, framework, dependencies, and sometimes absolute filesystem paths. An SQL error exposes the database structure.
Error handling: production vs. development
// Express.js : handler d'erreurs
app.use((err, req, res, next) => {
// Log complet côté serveur uniquement
console.error(err.stack);
// Réponse générique côté client
const isProd = process.env.NODE_ENV === 'production';
res.status(err.status || 500).json({
error: isProd ? 'Une erreur est survenue.' : err.message,
...(isProd ? {} : { stack: err.stack }),
});
});
Version numbers and software fingerprinting
HTTP headers frequently reveal the web server, its version, and the framework used. Server: Apache/2.4.49, X-Powered-By: Express, X-AspNet-Version: 4.0.30319: these details let an attacker target known CVEs for that specific version. The Shodan database indexes millions of servers with their fingerprints.
Removing revealing headers (nginx)
# nginx.conf
server_tokens off; # Masque la version dans Server: et les pages d'erreur
# Supprimer X-Powered-By côté application (Node.js/Express) :
app.disable('x-powered-by');
# Ou via un middleware :
const helmet = require('helmet');
app.use(helmet()); // Inclut la suppression de X-Powered-By
Debug mode active in production
Debug mode activates features designed for development that must never be accessible in production. Django with DEBUG=True exposes an interactive error page with environment variables, configuration, and full trace. PHP with display_errors=On shows errors directly in the page. These modes can expose API keys, database connection strings, or configuration secrets.
Sensitive data in cookies and headers
Some applications store operational information in cookies or headers that are readable by the user. The BIGipServer cookie from F5 Load Balancer encodes the internal server IP and port in base64. Session persistence cookies can reveal internal architecture. This information aids attacks against infrastructure.
Data exposure via TCP timestamps
TCP timestamps allow estimating a system's boot date and uptime. This reveals whether a server was recently restarted (and possibly patched) or has been running continuously for months without updates. It's a subtle but real reconnaissance vector.
Sensitive data exposure in logs
Application logs sometimes contain passwords, tokens, or personal data. This occurs when request parameters (some of which may contain passwords or tokens) are logged in full, or when objects containing sensitive data are serialised into logs without filtering.
Filtering sensitive data in logs
// Ne jamais logger les paramètres bruts d'une requête d'authentification
// Mauvais :
logger.info('Login attempt', { body: req.body }); // contient le mot de passe
// Correct :
logger.info('Login attempt', { email: req.body.email }); // uniquement l'email
Summary
- Generic error messages in production: detailed logs server-side only
- Hide software fingerprints: remove Server, X-Powered-By, X-AspNet-Version headers
- Disable debug mode in production: verify environment variables in the deployment pipeline
- Audit cookies and headers: remove operational and infrastructure information
- Filter logs: never log raw passwords, tokens, or personal data
Further reading
A question after reading?
Your application exposes too much information? Send a message.
Or book a 30-minute scoping call directly
Book a call →