Skip to content

Information Disclosure

Source: PortSwigger Web Security Academy Author: Johan Beysen


1. What Is Information Disclosure?

Information Disclosure (also: information leakage) occurs when an application unintentionally exposes sensitive information to users.

What can leak:

  • Technical details: software, versions, frameworks, internal paths
  • Source code, configuration files, backup files
  • User data: emails, API keys, passwords, tokens
  • Internal infrastructure: IP addresses, hostnames, network topology
  • Business logic and internal processes

Why it's dangerous:

Information leaks are sometimes low-severity on their own, but they form the basis for further attacks. A version number leads to a specific CVE. An internal hostname makes phishing more believable. An API key gives direct access.

Impact is context-dependent

A leaked admin email address is more trivial than a leaked database connection string. Always assess it in combination with the further exploitation possibilities.


2. Detection

Location What you're looking for
robots.txt / sitemap.xml Hidden paths, admin endpoints
HTML source Developer comments, hardcoded paths or keys
HTTP response headers Server, X-Powered-By, X-Generator, versions
Error messages Stack traces, file paths, SQL queries
JS files API endpoints, tokens, internal logic
Backup and temporary files .bak, .old, .swp, ~, _backup
Directory listings Open directory browsing
.git / .svn exposure Full source code recoverable
Debug parameters Hidden debug pages

Burp Suite

  • Burp Scanner automatically flags information leaks in responses
  • Burp Engagement Tools → Find comments — searches for developer comments across all responses
  • Burp Content Discovery — discovers hidden files and directories

3. HTTP Response Headers

By default, many web servers and frameworks reveal their identity in headers:

HTTP/1.1 200 OK
Server: Apache/2.4.51 (Ubuntu)
X-Powered-By: PHP/8.0.13
X-Generator: Drupal 9
X-AspNet-Version: 4.0.30319

Every version is a potential CVE lookup.

curl -I https://target.com

Interesting headers:

Header What it reveals
Server Web server + version
X-Powered-By Backend language/framework + version
X-Generator CMS or framework
X-AspNet-Version .NET version
X-Debug-Token Symfony Profiler token
Via Proxy / load balancer info
X-Forwarded-Server Internal hostname

4. Error Messages & Stack Traces

Verbose error messages are one of the richest sources of information leaks.

What Stack Traces Reveal

Internal Server Error

java.sql.SQLException: Table 'prod_db.users' doesn't exist
    at com.example.UserDAO.getUser(UserDAO.java:47)
    at com.example.UserServlet.doGet(UserServlet.java:23)
    ...

From this error you can extract: - The database name: prod_db - The table name: users - The language: Java - Class names and file paths - An internal version number, if present

Triggering Error Messages

Parameter manipulation:     id=abc  (integer expected)
Type mismatch:              date=not-a-date
Missing parameters:         remove required fields
Boundary testing:           extremely long strings, null bytes, special characters
' (apostrophe)
'' (double apostrophe)
1/0
SLEEP(5)
../../../etc/passwd
/invalid/path/that/doesnt/exist
?id=abc         (expects an integer)
?date=foobar    (expects a date)
?page=-1        (expects a positive number)

Difference between production and development

Development environments often show full stack traces. Production shouldn't — but regularly still does. Always test it.


5. Developer Comments in Source Code

<!-- TODO: remove hardcoded admin password before deployment -->
<!-- Admin login: admin / S3cur3P@ss -->
<!-- DEBUG: bypass auth with ?debug=true -->
<!-- Internal API: http://internal-api.corp.local/v2 -->
// Temporary: auth check disabled for testing
// if (!isAuthenticated()) return 403;

const API_KEY = "sk-prod-abc123xyz";   // ← hardcoded key
const INTERNAL_HOST = "10.0.0.5:8080";

Search patterns in Burp / browser:

TODO   FIXME   HACK   password   secret   key   token
admin  debug   test   internal   temp     old   backup

6. Debug Pages & Parameters

Some applications have debug functionality that stayed active in production:

?debug=true
?debug=1
?test=true
?dev=1
?verbose=true
?trace=true

Frameworks with known debug endpoints:

Framework Debug URL
Laravel /_ignition/health-check
Symfony /_profiler
Django A stack trace page when DEBUG=True
Spring Boot /actuator, /actuator/env, /actuator/heapdump
Flask Werkzeug debugger on port 5000

Spring Boot Actuator

/actuator/env reveals all environment variables — including database credentials and API keys. /actuator/heapdump returns a full memory dump.


7. Backup and Temporary Files

Text editors and deployment scripts sometimes leave files behind:

config.php.bak       config.php.old       config.php~
index.php.swp        .DS_Store            Thumbs.db
web.config.bak       .env.bak             database.yml.old
# Ffuf with a backup-extension wordlist
ffuf -u https://target.com/FUZZ -w backup-files.txt

# Manually testing known files
curl https://target.com/config.php.bak
curl https://target.com/.env.bak
curl https://target.com/index.php~

.DS_Store reveals a directory structure from the Mac developer:

# Tool: ds_store_exp
python ds_store_exp.py https://target.com/.DS_Store

8. Directory Listing

If the web server has directory listing enabled, directories are fully browsable:

Index of /uploads/
../
2024-01-15-backup.zip    2.3M
database-dump.sql        450K
internal-docs/
config-old.tar.gz        1.1M
# Check directories without an index.html
curl https://target.com/uploads/
curl https://target.com/backup/
curl https://target.com/files/

9. Version Control Exposure (.git / .svn)

If the .git directory is publicly accessible, the entire source code can be reconstructed — including the commit history with deleted files.

# Check whether .git is accessible
curl https://target.com/.git/HEAD
# Expected: ref: refs/heads/main

# Tool: git-dumper
git-dumper https://target.com/.git ./output

# Tool: gittools / GitHack
python GitHack.py https://target.com/.git/
# After dumping: search the commit history for sensitive data
git log --all --oneline
git show <commit-hash>
git diff HEAD~1

Commit history

Deleted files and cleaned-up commits are still present in the git object store. A hardcoded password that's "already removed" is often still simply retrievable.

# Search for sensitive strings across the full git history
git log -p --all | grep -i "password\|secret\|key\|token"

10. Cheat Sheet

Priority List

Priority Check Reason
1 .git exposure Full source code + history
2 /actuator/env Credentials and config
3 Stack traces DB names, paths, versions
4 .env / .env.bak API keys, DB credentials
5 robots.txt Hidden paths
6 JS source Endpoints, tokens, logic
7 Response headers Versions for CVE lookup
8 Backup files Configs, source code
9 Directory listing File structure
10 HTML comments Credentials, debug info

Quick Checks for Every Assessment

# Headers
curl -I https://target.com

# Robots and sitemap
curl https://target.com/robots.txt
curl https://target.com/sitemap.xml

# Git exposure
curl https://target.com/.git/HEAD

# Env files
curl https://target.com/.env
curl https://target.com/.env.bak
curl https://target.com/.env.local

# Spring Boot actuator
curl https://target.com/actuator
curl https://target.com/actuator/env

# Backup files in known locations
curl https://target.com/config.php.bak
curl https://target.com/wp-config.php.bak

Interesting Files per Technology

config.php      wp-config.php     .env
config.php.bak  settings.php      database.php
application.properties    application.yml
/actuator/env             /actuator/heapdump
/WEB-INF/web.xml
settings.py     .env     local_settings.py
requirements.txt         manage.py
.env            package.json      config.js
.env.local      .env.production   app.js