文件包含
通过include或require语句,可以将PHP文件的内容插入另一个PHP文件(在服务器执行它之前)
include和require语句是相同的,除了错误处理方面
- require会生成致命错误(E_COMPILE_ERROR)并停止脚本
- include只生成警告(E_WARNING)并且脚本会继续
因此,如果希望继续执行,并向用户输出结果,即使包含文件已丢失,那么请使用 include。否则,在框架、CMS 或者复杂的PHP 应用程序编程中,请始终使用 reguire 向执行流用关键文件。这在某个关键文件意外丢失的情况下,有助于提高应用程序的安全性和完整性。
像是这样的文件包含函数还有1
2
3
4
5
6
7
8
9include_once
require_once
highlight_file
show_source
file
readfile
file_get_contents
file_put_contents
fopen
文件包含
在此之前我们要知道,文件包含函数并不在意被包含的文件是什么类型,只要有php代码,都会被解析出来,利用这个特性,我们可以读取一下包含敏感信息的文件,一些文件上传的漏洞也是因此而出来的。
本地文件包含漏洞(LFI)
既然include等函数能包含本地文件并回显出来,那么我们可以利用它去读取一些本地固有的文件,用得最多的是phpinfo();
出此之外,我们可以读取一些系统本地的敏感信息,例如__C:\Windows\system.ini__ ,这是属于绝对路径读取。 相对路径读取是通过./ 表示当前位置路径,../表示上一级路径位置(在Linux中同样适用),例如当前页面所在路径为__C:\Apache24\htdocs_,我们需要使用../推到C盘再进行访问,构造路径如下:../../windows/system.ini_ 后面的路径穿越就是利用的这个原理,硕以说基础还是有必要学一学的。也就是打比赛找flag的时候,就用../../../……/flag,推到flag所在的目录位置就可以了。
一些常见的敏感目录信息路径
1 | Windows系统: |
1 | Linux/Unix系统: |
LFI漏洞利用技巧
配合文件上传使用
属于文件上传了那就到那里去看吧(っ’-‘)╮=͟͟͞͞💌
包含Apache日志文件
有些网站存在文件包含漏洞,但是却没有文件上传点。这个时候我们还可以通过利用Apache的日志文件来生成一句话木马。在用户发起请求时,服务器会将请求写入access.log,当发送错误时写入error.log可以用BP在里面编写一句话木马,像是这样
包含SESSION文件
这个出现的不多,了解一下就好,就是找到SESSION文件。根据文件内容找到可控变量,在构造payload插入到文件中,最后包含就可以了。
常见的session存储路径:
1 | /var/lib/php/sess_PHPSESSID |
看个题目,懂了说明你掌握了Session包含
包含临时文件
php中上传文件,会创建临时文件。在linux下使用/tmp目录,而在windows下使用C:\windows\temp目录。在临时文件被删除前,可以利用时间竞争的方式包含该临时文件。
由于包含需要知道包含的文件名。一种方法是进行暴力猜解,linux下使用的是随机函数有缺陷,而windows下只有65535种不同的文件名,所以这个方法是可行的。
另一种方法是配合phpinfo页面的php variables,可以直接获取到上传文件的存储路径和临时文件名,直接包含即可。 话不多说,看题时间竞争临时文件
远程文件包含(RFI)
如果PHP的配置选项allow_url_include、allow_url_fopen状态为ON的话,则include/require函数是可以加载远程文件的,这种漏洞被称为远程文件包含(RFI),这个需要自己有个web服务器,具体使用方法可以去CSDN看看大佬的blog
遍历文件
在PHP中,highlight_file函数用于高亮显示指定文件的内容。那么如何在不知道文件名的条件下遍历回显呢,payload就是:
1 | highlight_file(glob("/f*")[0]) |
这里的glob(“/f*”)会返回一个数组,包含所有匹配/f*模式的文件路径。[0] 取数组中的第一个元素(即第一个匹配的文件路径),然后将其传递给highlight_file。如果存在匹配的文件,这种用法将成功读取并高亮显示该文件的内容。
PHP伪协议
文件包含的重中之重,是一定需要掌握的。可以说,看见文件包含的题目就要想到伪协议。如下
1 | file:// — 访问本地文件系统 |
需要熟练掌握的有
php://filter
是一种元封装器,类似readfile(),file()等,可以获取指定文件源码(要知道,通常来说不会有人直接把源码放出来的,除了打比赛),所以我们需要用它来完成获取,php://filter流会被当做php文件执行,所以我们一般对其进行编码,让其不执行。从而导致任意文件读取。
最常用也是最好用的payload
1 | ?file=php://filter/read=convert.base64-encode/resource=flag.php |
扩展
当我们无法读取到有用信息或者不知道读取哪个php文件时,我们可以利用流写入一句话木马进去,详情请转到php_filter_chain_generator脚本参考
php://input
可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行,当传入的参数作为文件名打开时,可以将参数设为php://input,同时post写入想要执行的php代码,php执行时会将post内容当作文件内容,从而导致任意代码执行。
data://text/plain
在后面写入你想写入的数据给参数,例如data://text/plain,,如果对特殊字符进行了过滤,可以进行base64编码,data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4= 这个不常用,有这条件可以用php://input(doge)
结语
剩下的伪协议不常见也不常考(至少我还没遇到( ͡°❥ ͡°)),能学到这已经很不错了,重点在于实操去做题,两个字:沉淀,这些知识点在网上有很多资料都可以查到,我写的很多都是网上照抄的((ฅ•﹏•ฅ)),我写在blog里一来是为了引导学习路线,写的不详细或者看不懂的地方可以复制目录去搜索相关知识点,二来就是自己整理知识点,加强印象。希望各位师傅们能够在web道路上走得更快更远ヾ(❀╹◡╹)ノ゙❀~