← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Forced Browsing

security CWE-425 OWASP A1:2021 CVSS 7.5 PHP 5.0+ Beginner

Also Known As

unprotected endpoint path guessing direct URL access

TL;DR

Accessing resources at predictable URLs that are not linked from the application's UI but lack proper authorisation checks.

Explanation

Forced browsing (also called direct object reference or insecure direct access) occurs when an attacker guesses or enumerates URLs for resources the application assumes are private due to obscurity — backup files, admin panels, uploaded files, API endpoints, or configuration dumps. The fix is never to rely on URL secrecy: every resource must enforce server-side authorisation regardless of how it is accessed. Tools like dirb, gobuster, and OWASP ZAP automate forced browsing discovery during pen tests.

Common Misconception

Unpublished URLs are safe because attackers cannot guess them. Common paths (admin/, backup/, .git/, phpinfo.php) are in every attacker wordlist — obscurity delays discovery by minutes at most.

Why It Matters

Sensitive resources that are not linked but are predictably named are fully accessible — security through obscurity is not access control.

Common Mistakes

  • Generating download URLs or IDs sequentially — attackers enumerate ±1 from any known ID.
  • No server-side authorisation check on direct file or resource requests — only the link is hidden.
  • Backup files, old scripts, or admin panels deployed to the webroot and forgotten.
  • Relying on robots.txt to hide admin paths — it advertises them to attackers.

Code Examples

✗ Vulnerable
// No ownership check — any user can download any invoice
public function download(string \$filename): Response {
    return response()->file(storage_path("invoices/\$filename"));
}
✓ Fixed
// Use ID, not filename — enforce ownership
public function download(int \$invoiceId): Response {
    \$invoice = Invoice::findOrFail(\$invoiceId);

    if (\$invoice->user_id !== auth()->id()) abort(403);

    return response()->file(
        storage_path("invoices/{\$invoice->stored_filename}"),
        ['Content-Disposition' => "attachment; filename=invoice-\$invoiceId.pdf"]
    );
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 17
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 2 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T
No pings yet today
No pings yesterday
Amazonbot 8 Perplexity 3 ChatGPT 2 Google 1 Ahrefs 1
crawler 14 crawler_json 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Every URL must verify authorisation, not just authentication — never rely on obscurity (hidden links, GUIDs) as an access control mechanism
📦 Applies To
PHP 5.0+ web
🔗 Prerequisites
🔍 Detection Hints
Routes without authentication or authorisation middleware; admin panel at /admin accessible without admin role check; backup files at /backup.zip
Auto-detectable: ✓ Yes nikto dirbuster owasp-zap semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update
CWE-425 CWE-284

✓ schema.org compliant