Author: Aditya Bhatt Category: Web App Hacking | Recon | Info Disclosure | CVE Enumeration

πŸ” Preface

Welcome to the first installment of Exposure Protocol β€” a technical bug bounty series that digs deep into the art of extracting sensitive intel through seemingly harmless leaks. From verbose errors to hidden secrets in source files, this series explores how whispers in web traffic can scream out loud to the trained eye.

In this opener, we'll start with a classic yet powerful case: Error-Based Info Disclosure. You'll see how a mistyped input unravelled the backend, helped us fingerprint vulnerable software, and laid the groundwork for CVE enumeration β€” all wrapped in a clean automation script.

This article is the beginning of a five-part saga, each focusing on a distinct form of information disclosure you might encounter in the wild β€” and how to weaponize it ethically.

So buckle up β€” recon just got real.

πŸ“š Series Index: Information Disclosure β€” A Bug Hunter's Treasure Map

None

πŸ“œ Prelude to a Leak

Some bugs scream. Others whisper.

This one? It accidentally drops its whole backend rΓ©sumΓ© just because I threw a string into a parameter that expected a good ol' integer. πŸ’₯

Today, I'll walk you through how I turned a bad typecast into a full-on reconnaissance goldmine, discovered Apache Struts 2.3.31, and solved the PortSwigger lab with the swagger of a bounty hunter in a trench coat.

But wait… we're not stopping at the PoC. You'll also get a Python script to automate the whole shebang. Let's twist it up, automate the intel grab, and make devs cry (ethically, of course 🫑).

None

πŸ•ΉοΈ TL;DR of the Attack

We take a productId endpoint, feed it malformed input (a string instead of an int), and the app coughs up a verbose error message containing its internal framework version.

We collect that info and submit it to solve the lab. Simple, elegant, and deliciously leaky.

βš”οΈ Step-by-Step PoC

  1. Go to Lab: Burp Lab β€” Info Leak via Error Messages. Open any product and capture the request.
None

2. Send GET /product?productId=5 to Repeater.

None

3. Observe the normal response. Yawn. 😴

None

4. Now swap 5 with "example" β†’ productId="example" and boom β€” πŸ’₯ full Java stack trace drops in your lap.

None

In the stack trace, we spot the vulnerable tech: Apache Struts 2 2.3.31

5. Submit this version in the lab.

None

6. You just solved it. Now imagine doing this across 200 subdomains. That's bug bounty artillery right there. πŸš€

None

πŸ€– Automation Script: Lab Destroyer 9000

Here's your script to automate the whole lab. Just plug in the lab URL, and it'll throw a string payload, catch the error, extract the version, and print it like a true recon master.

You can simply git clone and use the script from My GitHubπŸ˜‰.

⚠️ NOTE: Make sure you're logged into your PortSwigger Academy session in the same browser session (or use the session cookie in this script).

import requests
import re

# πŸ”§ CONFIG
LAB_URL = "https://YOUR-LAB-ID.web-security-academy.net/product?productId="
PAYLOAD = '"injection"'
# 🧠 HEADERS (Optionally add your session cookie if needed)
headers = {
    "User-Agent": "Mozilla/5.0",
    # "Cookie": "session=YOUR_SESSION_HERE"
}

# πŸš€ MAKE THE REQUEST
def extract_version():
    try:
        print(f"[+] Sending request to: {LAB_URL}{PAYLOAD}")
        response = requests.get(LAB_URL + PAYLOAD, headers=headers, timeout=10)
        if response.status_code == 200:
            # πŸ§™ Regex magic to find Apache Struts version
            match = re.search(r'Apache Struts 2(?:\.| )([0-9]+\.[0-9]+\.[0-9]+)', response.text)
            if match:
                version = "2." + match.group(1)
                print(f"[🎯] Apache Struts version disclosed: {version}")
                return version
            else:
                print("[-] No version info found. Maybe lab is patched or wrong URL.")
        else:
            print(f"[-] Unexpected response code: {response.status_code}")
    except Exception as e:
        print(f"[!] Exception occurred: {e}")

# πŸ” Run the extractor
if __name__ == "__main__":
    extract_version()

πŸ’­ Real World Implications

  • That one version string? It's a fingerprint.
  • Apache Struts is notorious for RCEs like CVE-2017–5638 β€” the Equifax breach? Yeah, it started with something like this.
  • Once you know the version, you can map it against CVEs and craft custom exploits or pivot further.

πŸ” Defensive Measures

  • Never expose internal stack traces to the user.
  • Catch your exceptions, log them server-side, and serve generic 500 pages to users.
  • Use a WAF or RASP to detect parameter fuzzing.

🧠 Final Thoughts

Information disclosure is a gateway bug. It rarely gives you root access upfront, but it opens the door to version detection, CVE chaining, and attack surface expansion. Every recon artist's dream.

When in doubt, just toss in the wrong input and let the server do the talking.