文件包含

因为是开始学的时候写的,可能有的知识点没学全,当时懵懵的,之后遇到了会有补充

文件包含漏洞

一种注入型漏洞, 就是输入一段用户能够控制的脚本或者代码,并让服务端执行, 攻击者可以通过修改文件的位置来让后台执行任意文件,从而导致文件包含漏洞

文件包含的函数

include()

程序一运行文件便会包含进来,若包含文件不存在产生致命错误,程序终止运行

include()函数不在意被包含的文件是什么类型,只要有php代码,都会被解析出来

require()

与include相似,但如果文件不存在会抛出致命错误并终止程序

include_once()

确保同一个文件只被包含一次,避免重复定义函数或变量

require_once()

与require相似,但同样确保文件只被包含一次

本地文件包含漏洞(LFI)

能够打开并包含本地文件的漏洞(小皮暂时没搭成功)

获取本地信息的方法

1、使用绝对路径

2、使用相对路径读取

通过./表示当前位置路径,…/表示上一级路径位置,在linux中同样适用,类似于目录遍历

3、一些常见的敏感目录信息路径

Linux/Unix系统

1
2
3
4
5
6
7
8
9
/etc/passwd:账户信息  

/etc/shadow:账户密码信息

/usr/local/app/php5/lib/php.ini:PHP相关配置

/etc/httpd/conf/httpd.conf:Apache配置文件

/etc/my.conf:mysql配置文件

Windows系统

1
2
3
C:\boot.ini:查看系统版本

C:\ProgramFiles\mysql\my.ini:Mysql配置

LFI漏洞利用技巧

利用条件

  • include()等函数通过动态变量的方式引入包含文件
  • 用户能够控制该动态变量

1、读取敏感文件

1
?参数名=/etc/passwd

2、利用伪协议读源码

1
?参数名=php://filter/read=convert.base64-encode/resource=config.php

3、与文件上传配合使用

4、包含Apache日志文件

有时候网站存在文件包含漏洞,但是却没有文件上传点。这个时候我们还可以通过利用Apache的日志文件来生成一句话木马。

利用条件

  • 对日志文件可读
  • 知道日志文件access.log的存储目录( 默认位置:/var/log/httpd/access_log

  • 一般情况下日志存储目录会被修改,需要读取服务器配置文件(httpd,conf,nginx.conf等)或者根据phpinfo()中的信息来得知
  • 日志记录的信息都可以被调整,如报错的等级或者内容格式

5、包含SESSION文件

可以先根据尝试包含到SESSION文件,在根据文件内容寻找可控变量,在构造payload插入到文件中,最后包含即可。

利用条件

  • 找到Session内的可控变量
  • Session文件可读写,并且指定存储路径

php的session文件的保存路径可以在phpinfo中 session.save_path看到

Session常见存储路径

1
2
3
4
5
6
7
/var/lib/php/sess_PHPSESSID

/var/lib/php/sess_PHPSESSID

/tmp/sess_PHPSESSID

/tmp/sessions/sess_PHPSESSID

session文件格式:sess_[phpsessid],而phpsessid在发送的请求的cookie字段中可以看到

6、包含临时文件

php中上传文件,会创建临时文件。在linux下使用/tmp目录,而在windows下使用C:\windows\temp目录。

远程文件包含(RFI)

漏洞利用条件(phpinfo中查看)

  • allow_url_incude on
  • allow_url_fopen on

则include和require函数是可以加载远程文件的

访问本地目录下的phpinfo.php文件,若该页面没有对$path做任何过滤,因此存在文件包含漏洞

可以在远端Web服务器/site/目录下创建一个test.php文件,内容为phpinfo(),利用漏洞去读取这个文件。

如果test.php是恶意的webshell文件,那么利用该漏洞就可以获取到服务器权限即允许攻击者远程执行恶意代码

例题CTFHub

1
2
3
4
5
6
7
8
9
10
11
12
 <?php
error_reporting(0);
if (isset($_GET['file'])) {
if (!strpos($_GET["file"], "flag")) {
include $_GET["file"];
} else {
echo "Hacker!!!";
}
} else {
highlight_file(__FILE__);
}
?>

查看phpinfo

image-20260124005822135

两个都是on满足利用条件

bp抓包

image-20260124005827876

执行php代码

image-20260124005833210

日志文件包含(日志注入)

日志注入是一种通过将恶意数据插入到应用程序的日志文件中来实施的攻击。当这些日志被其他系统或应用程序读取和解析时,攻击者的恶意数据可能会被执行。这种攻击通常利用了不安全的日志处理机制和文件包含漏洞的组合。

在网站中用f12,点击网络,查看请求的响应头上的server字段

image-20260124005840481 Nginx默认日志路径是var/log/nginx/access.log(访问日志)或var/log/nginx/error.log(错误日志)

Apache的访问日志文件记录了客户端的每次请求及服务器响应的相关信息,我们可以访问日志文件得到一些网站信息如访问记录,此时可以尝试在url里写入一句话木马,通常在bp里面修改User-Agent,因为直接在网站上get传参可能会被url编码,然后再用蚁剑连接

Session文件包含

当可以获取Session文件路径并且Session文件内容可控时,就可以通过包含session文件进行攻击

漏洞利用

1)获取Session文件所在位置

通过phpinfo的信息获取session的存储位置

image-20260124005844358

Linux中Session默认存储在/var/lib/php/session目录下

文件路径例如

1
2
3
4
5
6
7
/var/lib/php/

/var/lib/php/sessions/

/tmp/

/tmp/sessions/

2)控制Session内容

伪协议

php://filter

过滤器,用于读取源码

格式:

1
php://filter/read=convert.base64-encode/resource=文件名

使用的convert.base64-encode,是一种过滤器。

利用条件:

  • allow_url_fopen :off/on
  • allow_url_include:off/on
过滤器
1)转换过滤器

作用:对数据流进行编码,通常用来读取文件源码

常见的转换过滤器

  1. base64

convert.base64-encode:将内容Base64编码

convert.base64-decode:将Base64内容解码

  1. 引号可打印

convert.quoted-printable-encode:引号可打印编码

convert.quoted-printable-decode:引号可打印解码

  1. 字符编码转换

convert.iconv.目标编码/源编码 例:convert.iconv.UTF-8/GBK

convert.iconv.源编码.目标编码 例:convert.iconv.UTF-8.UTF-16

2)字符串过滤器

该类通常以string开头,对每个字符都进行同样方式的处理

  1. string.toupper:转为大写
  2. string.tolower:转为小写
  3. string.strip_tags:用来处理掉读入的所有标签,例如XML的等等。在绕过死亡exit大有用处
  4. string.rot13:字符右移13位
3)加密过滤器

mcrypt.*/mdecrypt.*:使用MCrypt扩展进行加密/解密

4)压缩过滤器

zlib.deflate:压缩

zlib.inflate:解压

绕过死亡exit
1
2
3
4
5
<?php
$content = '<?php exit; ?>';
$content .= $_POST['txt'];
file_put_contents($_POST['filename'], $content);
?>

由于开头一直有一个exit的存在,会使得我们的一句话木马并不会被执行(这个过程在实战中十分常见,通常出现在缓存、配置文件等等地方,不允许用户直接访问的文件,都会被加上if(!defined(xxx))exit;之类的限制)

file_put_contents函数中,第一个参数是可以使用php伪协议的,所以这里就可以用php://filter伪协议以及各种过滤器

base64绕过

因为$content开头的死亡代码中包含<?···?>这些字符,而这些字符并不在base64的字符中,所以对其进行base64解码时会忽略掉这些字符,所以最终被解码的字符只有”phpexit”和传入的其他字符

“phpexit”一共只有7字符,但是base64算法解码时是4个byte一组,所以需要增加1个a一共8个字符,这样”phpexita”就能被正常解码,而后面我们传入的webshell的base64内容也被正常解码,结果就是

然后就可以通过对一句话木马进行base64编码并利用filter伪协议来构造payload

1
php://filter/write=convert.base64-decode/resource=文件名&txt=a PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==  

一定要在开头加上a来凑满8个字符满足base64解码要求

string.rot13绕过

string.rot13是常用的字符串过滤器,作用是右移13位也就是rot13编码

<?php exit; ?>在经过rot13编码后会变成<?cuc rkvg; ?>

在配置中, short_open_tag :off的时候,php不认识这个字符串,就不会执行命令

写入的一句话木马要求是经过rot13编码后恢复原状

构造payload:

1
php://filter/write=string.rot13/resource=kirito.php&txt=<?cuc riny($_CBFG['pzq']);?>
string.strip_tags与base64共同使用

string.strip_tags也是字符串过滤器,是用来处理掉读入的所有标签

例如

<?php exit;?>Test经过string.strip_tags以后只要Test

https://blog.csdn.net/JL20050725/article/details/150420908

php://input

用于执行php代码,读取HTTP请求体(如POST请求)

可以访问请求的原始数据,用于执行php代码,将POST数据作为PHP代码执行,可以将参数改为file=php://input,然后使用bp抓包后直接传参即将POST参数作为php代码执行

image-20260124005856602

例如:最后一行传参(但这个好像传的也有问题,要把请求头改为POST)

利用条件:

  • allow_url_fopen :off/on
  • allow_url_include:off/on

file://

用于访问本地文件系统, 在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响

image-20260124005902759

格式:

1
file:// [文件的绝对路径和文件名] 

data://

它允许将原始数据嵌入到 URL 中。

利用data:// 伪协议可以直接达到执行php代码的效果

文件包含漏洞,可以用这个伪协议,将恶意 PHP 代码作为数据嵌入,并让服务器解释执行

1
?file=data://text/plain,<?php system('ls'); ?>

利用条件

  • allow_url_include:on
  • allow_url_fopen :on

ZIP://协议

可以访问压缩包里面的文件

zip://中只能传入绝对路径

要用#分割压缩包和压缩包里的内容,并且#要用url编码成%23

格式:zip://[压缩包绝对路径]#[压缩包内文件]

1
?file=zip://D:\:\1.zip%23phpinfo.txt

%23是#的URL编码

利用条件

  • allow_url_fopen :off/on
  • allow_url_include:off/on

phar伪协议

就是php解压缩包的一个函数,不管后缀是什么,都会当做压缩包来解压

格式:

1
?file=phar://压缩包/内部文件

步骤

1)写一个一句话木马shell.php

2)然后用zip协议解压缩为shell.zip

3)然后将后缀改为png等其他格式

伪协议利用条件

image-20260124005910963


文件包含
https://colourful228.github.io/2026/01/24/文件包含/
作者
Colourful
发布于
2026年1月24日
更新于
2026年1月24日
许可协议