web

Challenges

grandas_notes

My grandma is into vibe coding and has developed this web application to help her remember all the important information. It would work be great, if she wouldn't keep forgetting her password, but she's found a solution for that, too.

http://52.59.124.14:5015arrow-up-right

source.ziparrow-up-right

circle-check

Okay now here is the long version. Now first look at the code base, we need to identify where is the flag?

In docker file (as environment variable) access by the web app in config.php when it seed the data for the webapp. And later on It lives in the database, in the users.note column for the admin user, and is displayed to the logged-in user on the dashboard.

So obviously, naive solution is log in as admin → GET /dashboard.php → read <textarea name="note">…</textarea>. But we do know that the username is "admin" but how do we get the password?

  • On failed login, the code compares the submitted password from the start against those stored hashes and returns how many front characters match. That creates a prefix oracle: we can recover the password by growing a correct prefix one character at a time, then log in and fetch the note.

After a password failure, the code leaks a prefix match count:

Exploit strategy:

  • Target: admin.

  • Initialize an empty prefix "".

  • For position i = 0..:

    • For each printable character c:

      • Submit login (username=admin, password=prefix + c).

      • If we get the dashboard → we’re done (full password matched).

      • Else read the flash: “you got X characters correct!”

      • If X == len(prefix) + 1, keep c (it’s correct for this position) and move to the next position.

  • Repeat until we log in (or until the prefix stops growing → adjust charset).

circle-info

Script

  • ENO{V1b3_C0D1nG_Gr4nDmA_Bu1ld5_InS3cUr3_4PP5!!}

pwgen

Password policies aren't always great. That's why we generate passwords for our users based on a strong master password!

http://52.59.124.14:5003arrow-up-right

circle-check
  • Since the source is...like 1 file so the source is just right there you know...

  • Also, see that nthpw? yea, curl that sh

  • Solve it in reverse

  • ENO{N3V3r_SHUFFLE_W1TH_STAT1C_S333D_OR_B4D_TH1NGS_WiLL_H4pp3n:-/_0d68ea85d88ba14eb6238776845542cf6fe560936f128404e8c14bd5544636f7}

webby

MFA is awesome! Even if someone gets our login credentials, and they still can't get our secrets!

http://52.59.124.14:5010arrow-up-right

circle-check
  • To get the source...you do /?source=1 (pretty neat, aye?)

  • Alrighty, where is the flag? — The value is read from /tmp/flag.txt into FLAG and rendered only by the /flag handler:

(So: be admin and be loggedIn when you hit /flag.)

  • What lines of code is vulnerable?

In /flag:

  • The code saves loggedIn=True before MFA completes.

  • It performs slow work (bcrypt(14)) before resetting loggedIn=False.

  • /flag does not check that MFA passed—only loggedIn + username.

This produces a time-of-check/time-of-use race window where the session is already “logged in” as admin.

Exploit strategry:

  • Get a fresh session cookie: GET /webpy_session_id.

  • Start login as admin:admin in the background using that cookie.

    • Server sets loggedIn=True; username=admin; save()

    • Server spends ~hundreds of ms doing bcrypt(14).

    • Only after that it flips loggedIn=False.

  • Hammer /flag with the same cookie during that slow window.

  • One request lands while loggedIn=True/flag returns the flag page.

circle-info

Script

  • ENO{R4Ces_Ar3_3ver1Wher3_Y3ah!!}

slasher

Slashing all the slashes...

http://52.59.124.14:5011arrow-up-right

note: this was a hard challenge to me since I went for a funny ahh route, but it didn't give out much it was a header injection challenge tbh...This probably the hardest web challege of this batch imo. Except the dogv2, I have a sense of what to do but me sleep...💤

circle-check

The page included the source, which is quite nice, here is the long version of my writeup.

  • Now, lets see where is the flag?:

Therefore, reading flag.php or causing the page to print its contents will show the flag. My focus are on these lines

Again, as mentioned that they challenge will tries to sanitizes our input and prevent us from doing our shenanigans (highlighted lines of code above):

That is why we need to craft an eval payload that:

  • avoids quotes/variables (they’re backslash-escaped),

  • uses only function calls and operator chaining,

  • lists files in the working directory and prints each with readfile()arrow-up-right

If you think about this methodically, the filters fail?

  • The eval sees the raw PHP code ($input supposed to be a strings...give it some quotes man).

  • Backslashes don’t stop tokens like opendir, readdir, readfile, parentheses, commas, pipes, etc.

  • An error handler suppresses warnings, so failed attempts don’t reveal much —but we don’t need them. (good job bozo, I test this locally with php -S localhost:8000)

I was able to do an equivalent to a "ls" command and see what we are dealing with

Assume the web root contains ., .., Dockerfile, docker-compose.yml, flag.php, index.php, style.css

Now how would we print the flag and access the flag.php? — well it is is sitting at...index 5? including the . and ..

  • I will be using readfile to achieve this (small note that this payload took me a fat minutes to figured out). Here is a bit of visualization for ya.

  • ENO{3v4L_0nC3_Ag41n_F0r_Th3_W1n_:-)}

  • Take away:

    • readdir() without a handle uses the last opendir handle, so you can iterate without variables.

    • readfile() prints as a side effect, so the flag is emitted even if $output is just an integer.

    • 🥀

dogfinder

I like dogs, so I wrote this awesome dogfinder page. Somewhere on the filesystem is a nice treat for you.

http://52.59.124.14:5020arrow-up-right

This was solved by my teammate "anar" (🗣️🗣️🔥🥀), really want to see the official writeups or the intended solution of this challenge...As our path to solve this challenge at the time was quite guessy (not my favorite thing). Regardless, it was ... rough.

  • ENO{CuT3_D0GG0S_T0_F1nD_Ev3r1Wh3re_<3}

dogfinderv2

I still like dogs, so I tried to make the previous version more secure. The treat is now in the root directory - that should help, shouldn't it?

http://52.59.124.14:5021arrow-up-right

  • I have a feeling it has to do something with listening the request via rce, as I was able to dump some of the permission and file using sqlmap, but i didn't solve it in time :<.

  • todo: ...lazy

Last updated