You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some additional hardening was applied to the php installation to make sure that previously known solutions wouldn't work (for further information read [this writeup from the challenge author](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)).
I didn't solve the challenge during the competition - [here is a writeup from someone who did](https://lewin.co.il/winning-the-impossible-race-an-unintended-solution-for-includers-revenge-counter-hxp-2021/) - but since the idea I had differed from the techniques used in the published writeups I read (and I thought it was cool :D), here is my approach.
## The rough Idea
During the competition I read [this blogpost from gynvael](https://gynvael.coldwind.pl/?id=671) where he bypassed a filter using the `convert.iconv` functionality of `php://filter/` and wondered
if that trick could be used to generate a php backdoor ... turns out it can be used for that :D
There are probably different/better solutions that take a similar approach, but here
is what I came up with after spending quite some time thinking about this:
After playing around a little, I noticed two interesting things:
-`convert.iconv.UTF8.CSISO2022KR` will always prepend `\x1b$)C` to the string
-`convert.base64-decode` is extremely tolerant, it will basically just ignore any characters that aren't valid base64.
Using these we can do the following:
1. prepend `\x1b$)C` to our string as described above
2. apply some chain of iconv conversions that leaves our initial base64 intact
and converts the part we just prepended to some string where the only valid
base64 char is the next part of our base64-encoded php code
3. base64-decode and base64-encode the string which will remove any garbage in between
4. Go back to 1 if the base64 we want to construct isn't finished yet
5. base64-decode to get our php code
## Getting the filter chains for step 2
I pretty much got these by just bruteforcing one conversion step at a time, looking at the results
and then choosing interesting results from which to continue.
(Considering the amount of time this cost me it probably would've been better to automate this entirely 🙃)
While bruteforcing I had to try all the aliases from `iconv -l` since somehow none of the iconv versions I found
online seemed to match in terms of alias names.
## Some problems I encountered
- Pretty much the only condition I encountered where the convert.base64-decode filter would fail is if it encounters an equal sign when it didn't expect one, luckily we can again use iconv and convert from UTF8 to UTF7 which will turn any equal signs in the string into some base64.
- If we base64-decode a string that doesn't have 4*n characters then the result
won't fit into whole bytes. The `convert.base64-decode` implementation deals with
this by just ignoring the last bits until the result is a multiple of 8 bits again.
This means that until we arrive at our desired base64 we will lose some bytes at the end of our string. This isn't an issue if we read from a file like `/etc/passwd` but we can just generate some garbage base64 before beginning to make sure that this will work even if the file is empty.
## Getting the flag
Now that we have our string of filters that will generate our backdoor getting the flag is as easy as