DEV Community

Farhan Hussain
Farhan Hussain

Posted on

Changing One Word in the URL Logged Me In As Admin — Neighbour (TryHackMe)

Platform: TryHackMe · Difficulty: Easy · Category: IDOR

Introduction

Neighbour is a box whose entire security model rests on the assumption that users won't look at the URL bar after logging in. It's a PHP web app with a login form, a profile page, and all the authorisation rigor of an honour system at an unmanned farm stall. The login page even helpfully leaves guest credentials in an HTML comment with a winking Ctrl+U hint. The developer wanted you to find it. What they perhaps didn't intend was for ?user=admin to work just as smoothly right afterwards.

Recon

Full-range scan with RustScan, detailed service fingerprinting via Nmap:

rustscan -a 10.49.169.236 -r 1-65535 --ulimit 5000 -- -Pn -sC -sV
Enter fullscreen mode Exit fullscreen mode
Port Service Version
22/tcp SSH OpenSSH 8.2p1 Ubuntu 4ubuntu0.5
80/tcp HTTP Apache httpd 2.4.53 (Debian)

One detail worth flagging: the PHPSESSID cookie is missing the HttpOnly flag. A small note, but it confirms this is a PHP application and hints that session security wasn't a top priority here either.

Feroxbuster scanning with PHP, TXT, and HTML extensions:

feroxbuster -u http://10.49.169.236/ \
  -w /usr/share/wordlists/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt \
  -x php,txt,html
Enter fullscreen mode Exit fullscreen mode
# output (relevant hits only)
200  http://10.49.169.236/index.php
200  http://10.49.169.236/login.php
302  http://10.49.169.236/profile.php  =>  login.php   # ^^^ redirects unauthenticated users
301  http://10.49.169.236/db           =>  /db/
200  http://10.49.169.236/db.php                       # ^^^ exists but returns empty body
302  http://10.49.169.236/logout.php   =>  login.php
Enter fullscreen mode Exit fullscreen mode

profile.php bounces unauthenticated visitors straight to login.php — so there is some kind of session check at the door. The question is whether that check extends to which user's profile you can view once you're inside. Spoiler: it doesn't.

db.php returns a blank response, which likely means it's a database connection include file rather than a standalone page.

The login page itself drops a hint in plain HTML: Ctrl+U is called out right in the UI. Taking the bait:

view-source:http://10.49.169.236/
Enter fullscreen mode Exit fullscreen mode
<!-- use guest:guest credentials until registration is fixed. "admin" user account is off limits!!!!! -->
Enter fullscreen mode Exit fullscreen mode

Guest credentials, giftwrapped in an HTML comment. The five exclamation marks on "off limits" are doing a lot of emotional heavy lifting for what is ultimately a URL parameter.

Username Password Where Found
guest guest HTML comment in index.php source

Foothold

An Insecure Direct Object Reference occurs when an application uses a user-supplied value — a filename, a username, a numeric ID — to directly look up and return a resource, without checking whether the requesting user is actually authorised to access that specific resource. It's one of the most common and most impactful web vulnerabilities: the server trusts the client to only ask for things it's allowed to see, which is precisely the one thing a client should never be trusted to do.

After logging in with guest:guest, the application lands here:

http://10.49.169.236/profile.php?user=guest
Enter fullscreen mode Exit fullscreen mode
Hi, guest. Welcome to our site. Try not to peep your neighbor's profile.
Enter fullscreen mode Exit fullscreen mode

That message is either a warning or an instruction depending on your disposition. The ?user= parameter is server-side rendered — the PHP backend looks up whatever username value is passed and returns that profile. The question is whether it checks that the logged-in session matches the requested username.

Modifying the URL parameter directly in the browser address bar:

http://10.49.169.236/profile.php?user=admin
Enter fullscreen mode Exit fullscreen mode

The server doesn't check. It just looks up admin and returns:

Hi, admin. Welcome to your site. The flag is: flag{66be95c478473d91a5358f2440c7af1f}
Enter fullscreen mode Exit fullscreen mode

No re-authentication. No access control check. One URL edit.

Shell / Access

No shell required. The flag was delivered directly in the HTTP response body after the IDOR parameter manipulation.

Escalation

Not applicable — the challenge resolves entirely at the web layer with no system-level privilege escalation involved.

Exploitation — The Full Chain

  1. HTML comment on the login page → guest credentials guest:guest
  2. Login as guest → lands on profile.php?user=guest
  3. IDOR identified — ?user= has no server-side ownership check
  4. URL edit to ?user=admin → admin profile returned → flag delivered directly

Rabbit Holes

None encountered — the chain resolves cleanly in a handful of steps with no dead ends.

Flags

Flag Value Location
Challenge Flag flag{66be95c478473d91a5358f2440c7af1f} profile.php?user=admin response

Mitigations

Vulnerability Severity Mitigation
IDOR on profile.php?user= High Validate server-side that the authenticated session user matches the requested profile; never trust user-supplied object references for access control
Guest credentials hardcoded in HTML comment Medium Remove all credentials from client-deliverable files; use environment variables or a proper user registration flow
Missing HttpOnly flag on PHPSESSID Low Set session.cookie_httponly = 1 in php.ini to prevent JavaScript access to the session cookie

Key Takeaway

A session cookie proves you're logged in — it doesn't automatically prove you're allowed to access every resource on the server. Always verify server-side that the authenticated user owns or has permission to access the specific object being requested, not just that they're authenticated at all.


Room: TryHackMe — Neighbour

Top comments (0)