Skip to content

Information Disclosure Checks

10 min read Created Sep 13, 2026 Last updated Sep 13, 2026

Information disclosure covers any response, file, or header that leaks data useful for further exploitation: stack traces, framework versions, internal paths, credentials, and source code. These findings rarely grant direct access on their own, but they reduce guesswork and feed directly into targeted attacks. Run misconfiguration scans alongside these checks, and use content discovery to find hidden files that may expose sensitive data. A verbose error message revealing the database type narrows SQL injection payloads. A leaked .env file hands you credentials without any exploitation at all.

  • Error message analysis triggers verbose output with malformed input to extract stack traces, versions, and file paths.
  • Debug pages and endpoints probes for development interfaces left exposed in production.
  • Backup and temporary files checks known files with common backup suffixes.
  • Source code exposure covers .git, .svn, .DS_Store, source maps, and .env files.
  • HTTP header leaks inspects response headers for server and framework version strings.
  • Robots.txt and sitemap extracts hidden paths from crawler directives.

Error Message Analysis

Verbose error messages reveal the technology stack, internal file paths, database types, and sometimes partial query structures. The goal is to trigger error conditions and inspect the response for anything beyond a generic error page. Send malformed input to parameters, invalid content types, and unexpected HTTP methods:

┌──(kali㉿kali)-[~]
└─$ curl -sk "http://$TARGET_IP:$PORT/?id='"
Warning: mysqli_query(): You have an error in your SQL syntax near '''
File: /var/www/html/index.php on line 42
Explain command
-sk Silent mode with insecure TLS to suppress progress output and skip certificate verification.

A single quote in a parameter is enough to trigger SQL error output on vulnerable applications. The response reveals the database driver (mysqli), the full file path (/var/www/html/index.php), and the line number. This feeds directly into SQL injection testing with confirmed database type.

┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST http://$TARGET_IP:$PORT/api/login -H 'Content-Type: application/json' -d '{invalid'
{
  "error": "SyntaxError: Unexpected token i in JSON at position 1",
  "stack": "SyntaxError: Unexpected token i\n    at JSON.parse (<anonymous>)\n    at /app/src/middleware/auth.js:23:18"
}
Explain command
-sk Silent mode with insecure TLS to suppress progress and skip certificate checks.
-X POST Send a POST request instead of GET.
-H 'Content-Type: application/json' Set the Content-Type header to JSON.
-d '{invalid' Send malformed JSON as the request body to trigger a parse error.

Stack traces in JSON API responses are common in Node.js and Python applications running in development mode. The trace exposes the internal directory structure and the exact file handling the request.

Try additional triggers: request a non-existent path to see if the 404 page leaks framework details, send an oversized request body, or use an unexpected HTTP method like DELETE on a GET-only endpoint.

┌──(kali㉿kali)-[~]
└─$ curl -skI -X DELETE http://$TARGET_IP:$PORT/
HTTP/1.1 405 Method Not Allowed
Server: Apache/2.4.52 (Ubuntu)
X-Powered-By: PHP/8.1.2
Explain command
-skI Silent mode, skip TLS verification, fetch response headers only.
-X DELETE Send a DELETE request to trigger method-not-allowed errors.

A 405 response with Server and X-Powered-By headers reveals the exact web server and PHP versions. Even when error bodies are generic, the headers often leak version information.

Debug Pages and Endpoints

Development debug interfaces left exposed in production provide direct access to configuration, environment variables, and sometimes interactive code execution. These are high-value targets. Use ffuf to discover common debug paths:

┌──(kali㉿kali)-[~]
└─$ echo -e 'debug\nconsole\nphpinfo.php\nserver-status\nserver-info\n.env\nactuator\nactuator/env\nactuator/health\nactuator/configprops\nactuator/mappings\n_debug\n_profiler\nelmah.axd\ntrace.axd\nweb.config.bak' | ffuf -u http://$TARGET_IP:$PORT/FUZZ -w - -mc 200,403
phpinfo.php             [Status: 200, Size: 85437]
.env                    [Status: 200, Size: 1243]
actuator/health         [Status: 200, Size: 15]
server-status           [Status: 403, Size: 277]
Explain command
-u http://$TARGET_IP:$PORT/FUZZ Target URL with FUZZ placeholder for wordlist substitution.
-w - Read wordlist from stdin.
-mc 200,403 Match responses with 200 OK or 403 Forbidden status codes.

A 403 on server-status or server-info means the endpoint exists but is restricted. This may be bypassable with X-Forwarded-For: 127.0.0.1 or by accessing it from an SSRF context. A 200 on phpinfo.php exposes the full PHP configuration including loaded modules, environment variables, and file paths.

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/phpinfo.php | grep -iE 'DOCUMENT_ROOT|SERVER_SOFTWARE|REMOTE_ADDR|DB_|MAIL_|APP_KEY'
DOCUMENT_ROOT => /var/www/html
SERVER_SOFTWARE => Apache/2.4.52 (Ubuntu)
DB_HOST => 10.10.14.3
DB_DATABASE => appdb
APP_KEY => base64:xK2aB1cD3eF4gH5iJ6kL7mN8oP9qR0s=
Explain command
-sk Silent mode with insecure TLS.

A phpinfo() page with database credentials and application keys is a critical finding. The APP_KEY in Laravel applications enables remote code execution through deserialization attacks.

Spring Boot Actuator

Spring Boot applications expose actuator endpoints under /actuator by default. These can leak environment variables, configuration properties, and internal mappings:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/actuator | python3 -m json.tool
{
  "_links": {
    "self": {"href": "/actuator"},
    "health": {"href": "/actuator/health"},
    "env": {"href": "/actuator/env"},
    "configprops": {"href": "/actuator/configprops"},
    "mappings": {"href": "/actuator/mappings"}
  }
}
Explain command
-sk Silent mode with insecure TLS.
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/actuator/env | python3 -m json.tool | grep -iE 'password|secret|key|token|credential'
"spring.datasource.password": "******",
"aws.secret-access-key": "******",
"jwt.secret": "supersecretkey123"

Spring Boot masks sensitive values in /actuator/env by default, but the /actuator/configprops endpoint sometimes exposes them in plaintext. The /actuator/mappings endpoint lists every registered URL mapping, which reveals internal API endpoints not documented anywhere.

Django Debug Mode

Django in debug mode returns full stack traces with local variable values on any unhandled exception. Force an error by requesting a nonexistent path:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/nonexistent_path_trigger_debug
Explain command
-sk Silent mode with insecure TLS.

If Django debug mode is active, the 404 page shows all configured URL patterns. A 500 error page displays the full traceback including local variables, database queries, and the settings.py configuration. Look for SECRET_KEY, database credentials, and ALLOWED_HOSTS in the output.

Backup and Temporary Files

Editors, deployment scripts, and manual backups leave copies of files with predictable suffixes. These backup files are often served as plaintext by the web server, even when the original file would be processed by the application. A .bak copy of a PHP file returns the raw source code instead of executing it:

┌──(kali㉿kali)-[~]
└─$ for file in index.php config.php wp-config.php .htaccess web.config settings.py manage.py app.py; do
echo "${file}.bak"
echo "${file}.old"
echo "${file}.orig"
echo "${file}.save"
echo "${file}.swp"
echo "${file}~"
echo ".${file}.swp"
done | ffuf -u http://$TARGET_IP:$PORT/FUZZ -w - -mc 200 -fs 0
wp-config.php.bak       [Status: 200, Size: 3145]
.htaccess.old           [Status: 200, Size: 412]
Explain command
-u http://$TARGET_IP:$PORT/FUZZ Target URL with FUZZ placeholder for wordlist substitution.
-w - Read wordlist from stdin.
-mc 200 Match only 200 OK responses.
-fs 0 Filter out empty responses.

A wp-config.php.bak hit returns the full WordPress configuration in plaintext, including database credentials, table prefix, authentication salts, and debug settings. The same applies to config.php.bak, settings.py.bak, and any other server-side configuration file.

Vim swap files (.swp) follow a specific naming pattern. The swap file for config.php is .config.php.swp (note the leading dot). Recover the content with vim -r:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/.config.php.swp -o config.swp
┌──(kali㉿kali)-[~]
└─$ vim -r config.swp -c ':w recovered_config.php' -c ':q!'

Source Code Exposure

Version control metadata, environment files, and build artifacts left on production servers expose source code, credentials, and infrastructure details. Dedicated pages cover the two most common cases in depth:

Beyond those, check for additional version control and metadata files:

┌──(kali㉿kali)-[~]
└─$ for path in .svn/entries .svn/wc.db .DS_Store .env .env.local .env.production .env.staging .env.backup .dockerenv docker-compose.yml Dockerfile; do
code=$(curl -skI http://$TARGET_IP:$PORT/$path | grep HTTP | awk '{print $2}')
echo "$code /$path"
done
200 /.env
403 /.svn/entries
200 /.DS_Store
404 /.env.local
200 /.env.production
404 /docker-compose.yml

A 200 on .env is often the single most impactful finding in a web assessment. It typically contains database credentials, API keys, mail server passwords, and application secrets in plaintext:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/.env
APP_NAME=MyApp
APP_ENV=production
APP_KEY=base64:xK2aB1cD3eF4gH5iJ6kL7mN8oP9qR0s=
DB_HOST=127.0.0.1
DB_DATABASE=production
DB_USERNAME=admin
DB_PASSWORD=S3cr3tP@ssw0rd
MAIL_PASSWORD=smtp_pass_123
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

A .DS_Store file is a macOS Finder metadata file that lists filenames in the directory. Parse it to discover hidden files and directories that are not linked from the application:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/.DS_Store -o ds_store
┌──(kali㉿kali)-[~]
└─$ python3 -m pip install ds-store 2>/dev/null
┌──(kali㉿kali)-[~]
└─$ python3 -c "from ds_store import DSStore; [print(r.filename) for r in DSStore.open('ds_store')]"
admin
backup
config.php
old_site
upload

Directory names revealed by .DS_Store often include backup directories, admin panels, and upload directories that are not indexed or linked from the main application.

HTTP Headers Leaking Info

Response headers frequently expose the web server software, framework version, and runtime environment. These are low-effort checks that provide immediate intelligence for targeted attacks:

┌──(kali㉿kali)-[~]
└─$ curl -skI http://$TARGET_IP:$PORT/ | grep -iE '^(server|x-powered-by|x-aspnet-version|x-aspnetmvc-version|x-generator|x-drupal|x-runtime|x-version|via):'
Server: nginx/1.18.0 (Ubuntu)
X-Powered-By: Express
Explain command
-skI Silent mode, skip TLS verification, fetch response headers only.

The Server header reveals the web server and often the OS. X-Powered-By exposes the application framework (Express, PHP, ASP.NET). X-AspNet-Version and X-AspNetMvc-Version pin the exact .NET runtime, which narrows deserialization and known CVE options.

Check multiple endpoints, not just the root. Error pages, API endpoints, and static file responses sometimes return different headers than the main page:

┌──(kali㉿kali)-[~]
└─$ for path in / /api/ /login /favicon.ico /nonexistent; do
echo "--- $path ---"
curl -skI http://$TARGET_IP:$PORT$path | grep -iE '^(server|x-powered-by|x-aspnet)'
done
--- / ---
Server: nginx/1.18.0
--- /api/ ---
Server: nginx/1.18.0
X-Powered-By: Express
--- /nonexistent ---
Server: Apache/2.4.52
X-Powered-By: PHP/8.1.2

Different servers behind a reverse proxy sometimes leak through on specific paths. A 404 hitting a backend directly instead of being caught by the proxy reveals the upstream server details. Cross-reference header findings with HTTP tech fingerprinting results.

Robots.txt and Sitemap

robots.txt tells search engines which paths to avoid. From a pentesting perspective, every Disallow entry is a path the developer considered sensitive enough to hide from crawlers. That is exactly what to investigate first:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/robots.txt
User-agent: *
Disallow: /admin/
Disallow: /backup/
Disallow: /api/internal/
Disallow: /old/
Disallow: /staging/
Sitemap: http://example.com/sitemap.xml
Explain command
-sk Silent mode with insecure TLS.

Every disallowed path deserves a direct request to check whether it returns content, a login page, or a directory listing. Paths like /admin/, /backup/, and /api/internal/ are obvious targets. The Sitemap directive points to an XML file listing all indexed pages:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/sitemap.xml | grep -oP '<loc>\K[^<]+' | sort -u
http://example.com/
http://example.com/about
http://example.com/admin/dashboard
http://example.com/api/docs
http://example.com/internal/status

Sitemaps sometimes include admin panels, internal status pages, and API documentation endpoints that are not linked from the public-facing application. Large applications use a sitemap index file that references multiple sitemaps. Check /sitemap_index.xml and /sitemaps/ as well.

Extract unique paths from both robots.txt and sitemap.xml and probe each one:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/robots.txt | grep -i disallow | awk '{print $2}' | sed 's#^/##' | ffuf -u http://$TARGET_IP:$PORT/FUZZ -w - -mc 200,301,302,403
admin/                  [Status: 302, Size: 0]
backup/                 [Status: 200, Size: 4521]
api/internal/           [Status: 403, Size: 277]
Explain command
-u http://$TARGET_IP:$PORT/FUZZ Target URL with FUZZ placeholder for path substitution.
-w - Read wordlist from stdin.
-mc 200,301,302,403 Match responses with common success and redirect status codes.

A 302 on /admin/ indicates a login page exists. A 200 on /backup/ may be a directory listing with downloadable files. A 403 on /api/internal/ confirms the path exists and is worth testing for access control bypasses.

References