【漏洞分析复现】emlogV2.1.15存在反序列化漏洞 CVE-2023-43291

admin 2024年2月15日19:42:06评论9 views字数 5816阅读19分23秒阅读模式
​​

0x01

漏洞概述

该漏洞最早出现在emlog v1.7,影响范围 emlog v1.7-emlog v2.1.15

emlog官网最新版本为emlog v2.23

emlog 是 "Every Memory Log" 的简称,意即:点滴记忆。它是一款基于PHP语言和MySQL数据库的开源、免费、功能强大的个人或多人联合撰写的博客系统(blog)。基于PHP和MySQL的功能强大的博客及CMS建站系统。致力于提供快速、稳定,且在使用上又极其简单、舒适的博客服务。安装和使用都非常方便

官网 https://www.emlog.net/

【漏洞分析复现】emlogV2.1.15存在反序列化漏洞 CVE-2023-43291

0x02

漏洞分析

本次漏洞主要是emlog缓存机制导致

0x03

emlog的缓存机制

emlog使用的缓存机制,会将网站运行的一些数据以php序列化的形式存储在本地文件中,访问时再将其反序列化,以减少对数据库的请求,加快访问速度。

缓存机制的代码主要在include/lib/cache.php中,以下是存储缓存以及读取缓存的代码(include/lib/cache.php, 78~107行)

`public function cacheWrite($cacheData, $cacheName) {`    `$cacheFile = EMLOG_ROOT . '/content/cache/' . $cacheName . '.php';`    `$cacheData = "    if (!file_put_contents($cacheFile, $cacheData)) {        emMsg('写入缓存失败,缓存目录(content/cache)不可写');    }    $this->{$cacheName . '_cache'} = null;`}``public function readCache($cacheName) {`    `if ($this->{$cacheName . '_cache'} != null) {        return $this->{$cacheName . '_cache'};`    `}`    $cachefile = EMLOG_ROOT . '/content/cache/' . $cacheName . '.php';    if (!is_file($cachefile) || filesize($cachefile) <= 0) {        if (method_exists($this, 'mc_' . $cacheName)) {            $this->{'mc_' . $cacheName}();        }    }    if ($fp = fopen($cachefile, 'r')) {        $data = fread($fp, filesize($cachefile));        fclose($fp);        clearstatcache();        $this->{$cacheName . '_cache'} = unserialize(str_replace("        return $this->{$cacheName . '_cache'};    }`}`

在存储缓存时,会将序列化后的字符串存到文件中,为了防止被直接访问,作者将文件设置成了php文件,而且在文件头部添加了<?php exit;//,这样在被直接访问到时,也不会泄露序列化后的数据。 当需要读取缓存数据时,直接读取文件的内容,并将<?php exit;//去掉,反序列化即可。

但在读取缓存时,这样的设计就存在问题:攻击者可以将要序列化的变量内容设置为<?php exit;//,并写入缓存文件,在读取缓存时,将会导致反序列化时的字符串逃逸,构成反序列化漏洞

0x04

alias文章别名缓存

在include/lib/cache.php, 404~413行,这里将从数据库中查到的别名alias存到数组中,之后将该数组序列化后缓存到文件,如果数据库中的别名是我们可控的,那么这里将可以使用上面的方法来进行反序列化攻击

  `/**`    `*文章别名缓存*/``private function mc_logalias() {``$sql = "SELECT gid,alias FROM " . DB_PREFIX . "blog where alias!=''";``$query = $this->db->query($sql);``$log_cache_alias = [];``while ($row = $this->db->fetch_array($query)) {`  `$log_cache_alias[$row['gid']] = $row['alias'];``}``$cacheData = serialize($log_cache_alias);``$this->cacheWrite($cacheData, 'logalias');``}`

​在admin/article_save.php,这里可以通过新建blog或者更新blog的方式,来将alias插入数据库中

`<?php``/**` * `article save and update` * `@package EMLOG` * `@link https://www.emlog.net` `*/``/**` * `@var string $action` * `@var object $CACHE` `*/``require_once 'globals.php';``if (empty($_POST)) {`    `exit;``}``$Log_Model = new Log_Model();``$Tag_Model = new Tag_Model();``$title = Input::postStrVar('title');``$postDate = isset($_POST['postdate']) ? strtotime(trim($_POST['postdate'])) : time();``$sort = Input::postIntVar('sort', -1);``$tagstring = isset($_POST['tag']) ? strip_tags(addslashes(trim($_POST['tag']))) : '';``$content = Input::postStrVar('logcontent');``$excerpt = Input::postStrVar('logexcerpt');``$alias = Input::postStrVar('alias');``$top = Input::postStrVar('top', 'n');``$sortop = Input::postStrVar('sortop', 'n');``$allow_remark = Input::postStrVar('allow_remark', 'y');``$password = Input::postStrVar('password');``$cover = Input::postStrVar('cover');``$link = Input::postStrVar('link');``$author = isset($_POST['author']) && User::haveEditPermission() ? (int)trim($_POST['author']) : UID;``$ishide = Input::postStrVar('ishide', 'y');``$blogid = Input::postIntVar('as_logid', -1); //自动保存为草稿的文章id``if (isset($_POST['pubPost'])) {`    `$ishide = 'n';``}``if (!empty($alias)) {`    `$logalias_cache = $CACHE->readCache('logalias');`    `$alias = $Log_Model->checkAlias($alias, $logalias_cache, $blogid);``}``//管理员发文不审核,注册用户受开关控制``$checked = Option::get('ischkarticle') == 'y' && !User::haveEditPermission() ? 'n' : 'y';``$logData = [`    `'title'        => $title,`    `'alias'        => $alias,`    `'content'      => $content,`    `'excerpt'      => $excerpt,`    `'cover'        => $cover,`    `'author'       => $author,`    `'sortid'       => $sort,`    `'date'         => $postDate,`    `'top '         => $top,`    `'sortop '      => $sortop,`    `'allow_remark' => $allow_remark,`    `'hide'         => $ishide,`    `'checked'      => $checked,`    `'password'     => $password,`    `'link'         => $link,``];``if (User::isWiter()) {`    `$count = $Log_Model->getPostCountByUid(UID, time() - 3600 * 24);`    `$post_per_day = Option::get('posts_per_day');`    `if ($count >= $post_per_day) {`        `emDirect("./article.php?error_post_per_day=1");`    `}``}``if ($blogid > 0) {`    `$Log_Model->updateLog($logData, $blogid);`    `$Tag_Model->updateTag($tagstring, $blogid);``} else {`    `$blogid = $Log_Model->addlog($logData);`    `$Tag_Model->addTag($tagstring, $blogid);``}``$CACHE->updateArticleCache();``doAction('save_log', $blogid);``// 异步保存``if ($action === 'autosave') {`    `exit('autosave_gid:' . $blogid . '_');``}``// 保存草稿``if ($ishide === 'y') {`    `emDirect("./article.php?draft=1&active_savedraft=1");``}``// 文章(草稿)公开发布``if (isset($_POST['pubPost'])) {`    `if (!User::haveEditPermission()) {`        `notice::sendNewPostMail($title);`    `}`    `emDirect("./article.php?active_post=1");``}``// 编辑文章(保存并返回)``$page = $Log_Model->getPageOffset($postDate, Option::get('admin_perpage_num'));``emDirect("./article.php?active_savelog=1&page=" . $page);`

​找一下关键代码

`$alias = Input::postStrVar('alias');``...``// 将传入的数据放到数组中``$logData = [`  `'alias' => $alias,`  `...``];``...``// 新建文章,将数据插入数据库,或者更新文章,更新数据库``$blogid = $Log_Model->addlog($logData);``// $Log_Model->updateLog($logData, $blogid);``// 更新缓存``$CACHE->updateArticleCache();`

在include/lib/cache.php:79行定义了updateArticleCache(),其包含了更新logalias的缓存

`public function updateArticleCache() {`    `$this->updateCache(['sta', 'tags', 'sort', 'newlog', 'record', 'logsort', 'logalias']);``}`

到这一步发现可以通过新建文章和更新文章来控制文章别名的缓存

0x05

漏洞复现

先注册一个用户,登录后发布两篇文章(草稿),从返回结果可以获得文章的id,这里文章id分别是4和5

【漏洞分析复现】emlogV2.1.15存在反序列化漏洞 CVE-2023-43291

先修改id为5的blog,设置其alias为a";i:4;s:1:"x

【漏洞分析复现】emlogV2.1.15存在反序列化漏洞 CVE-2023-43291

同理,修改id为4的,设置alias为<?php exit;//

发送完两个数据包后,alias的缓存文件为content/cache/logalias.php,内容如下

`<?php exit;//a:2:{i:4;s:13:"<?php exit;//";i:5;s:13:"a";i:4;s:1:"x";}`

在读取缓存时,先将<?php exit;//替换为空,再进行反序列化,反序列化字符串为

a:2:{i:3;s:13:"";i:4;s:13:"a";i:4;s:1:"x";}

通过反序列化,结果为

`array(2) {`  `[3]=>`  `string(13) "";i:4;s:13:"a"`  `[4]=>`  `string(1) "x"``}`

到这里,其实可以很明显的看到反序列化字符逃逸漏洞的存在。

免责声明

Drt安全战队

由于传播、利用本公众号Drt安全战队所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号Drt安全战队及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉,谢谢!

原文始发于微信公众号(Drt安全战队):【漏洞分析复现】emlogV2.1.15存在反序列化漏洞 CVE-2023-43291

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月15日19:42:06
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【漏洞分析复现】emlogV2.1.15存在反序列化漏洞 CVE-2023-43291http://cn-sec.com/archives/2173106.html

发表评论

匿名网友 填写信息