4.攻防世界Web_php_include
进入题目页面如下
是PHP源码,进行代码审计
<?php
// 显示当前 PHP 文件的源代码,方便开发者查看代码结构和内容,也可用于调试或代码审计。
show_source(__FILE__);
// 输出通过 GET 请求传递的名为 'hello' 的参数的值。
// 如果在 URL 中未传递该参数,可能会产生警告信息(取决于 PHP 的错误报告设置)。
echo $_GET['hello'];
// 从 GET 请求中获取名为 'page' 的参数的值,并将其赋值给变量 $page。
// 这个参数通常用于指定要包含的文件。
$page = $_GET['page'];
// 使用 while 循环检查 $page 变量中是否包含字符串 "php://"。
// strstr 函数用于查找一个字符串在另一个字符串中首次出现的位置,如果找到则返回该位置及之后的字符串,否则返回 false。
while (strstr($page, "php://")) {
// 如果 $page 中包含 "php://",则使用 str_replace 函数将所有的 "php://" 替换为空字符串。
// 这样做的目的是防止用户通过 "php://" 伪协议来访问敏感资源或执行恶意操作。
$page = str_replace("php://", "", $page);
}
// 使用 include 语句包含 $page 变量所指定的文件。
// include 会将指定文件的内容插入到当前脚本中执行,如果文件不存在会产生警告,但脚本会继续执行。
include($page);
?>
include($page) 语句直接包含用户通过 page 参数指定的文件,没有对文件路径进行严格的验证和过滤。攻击者可以通过构造特殊的文件路径来包含系统中的任意文件,从而执行任意代码或获取敏感信息。例如,使用相对路径(如 ../../etc/passwd)或绝对路径来包含系统文件。
代码的目的是通过 include
函数包含用户通过 page
参数指定的文件,同时尝试过滤掉 php://
伪协议,以防止用户利用伪协议进行恶意操作
利用 strstr()
函数大小写敏感特性
strstr()
函数特性
strstr()
函数是 PHP 中用于查找一个字符串在另一个字符串中首次出现位置的函数,并且该函数是区分大小写的。也就是说,strstr('PHP://input', 'php://')
会返回 false
,因为它严格区分大小写,只有当字符串完全匹配时才会返回相应结果。
大小写绕过思路
基于 strstr()
函数的这个特性,我们可以将 php://
写成大写形式,如 PHP://
。这样在执行 while (strstr($page, "php://"))
时,由于大小写不匹配,不会进入循环进行替换操作,从而绕过了代码对 php://
的过滤。
PHP://input
原理及作用
php://input
是 PHP 中的一个非常有用的伪协议流
php://input
是一个只读的数据流,它允许你以原始的、未经过解析的形式访问 HTTP 请求体中的数据。在处理 HTTP POST 请求时,除了使用 $_POST
数组来获取表单数据之外,还可以通过 php://input
来获取 POST 请求中的原始数据。与 $_POST
不同的是,php://input
可以处理任何类型的 POST 数据,而不仅仅是表单编码的数据。
PHP://input
是一个只读的数据流,它允许你以原始形式读取 POST 请求体中的数据。当客户端通过 POST 方法发送数据时,服务器可以通过 PHP://input
来获取这些数据。
工作原理
当客户端向服务器发送 HTTP POST 请求时,请求体中的数据会被发送到服务器。在 PHP 中,可以通过 php://input
这个伪协议来访问这些数据。当使用 file_get_contents('php://input')
或其他文件操作函数来读取 php://input
时,PHP 会将请求体中的数据作为一个文件流返回给你,可以像处理普通文件一样处理这些数据。
结合利用
当我们通过将 page
参数设置为 PHP://input
并使用 POST 方法传输恶意代码时,服务器会将 POST 请求体中的数据当作文件内容来处理。由于 include()
函数会包含指定的文件并执行其中的代码,所以当 include('PHP://input')
时,就相当于执行了通过 POST 方法发送的恶意代码。
构造请求
- GET 参数:在 URL 中设置
page
参数为PHP://input
,即http://网址?page=PHP://input
<?php echo file_get_contents('/path/to/flag');?>
服务器接收到请求后,对 page
参数进行处理。由于 PHP://input
大小写与过滤字符串 php://
不同,绕过了过滤。
include('PHP://input')
会将 POST 请求体中的代码当作文件内容执行,从而读取并输出 flag
文件的内容。
构造payload
?page=data://text/plain,<?php system("ls")?>
?page=data://text/plain,<?php system("cat fl4gisisish3r3.php")?>
最后F12查看源代码得到flag