MiniCMS 1.10漏洞总结

前言

第一次线下被打成💩了,比赛中一直被打,修洞的过程也是磕磕碰碰。想着之后要增加一下cms的审计经验,但是摸了一学期又陷入期末复习的深渊,没法子,审计学习咕到了现在。。。现在终于有了时间,在寻找目标的时候恰好看到一个极简风格的cms——MiniCMS,应该很适合我这个菜鸡(嘿嘿嘿)。

目录结构

mc-admin           后台
  |--...           后台功能及前端面板
mc-files           文章或页面内容处理
  |--theme         渲染文章
  |--posts         文章
  |    |--data     文章信息序列化数据
  |    |--index    保存已创建或删除的文章信息
  |    |      |--delete.php    回收站
  |    |      |--draft.php     草稿箱
  |    |      |--publish.php   已发布
  |--pages         页面
  |    |--data     页面信息序列化数据
  |    |--index    保存已创建或删除的页面信息
  |    |      |--delete.php    回收站
  |    |      |--draft.php     草稿箱
  |    |      |--publish.php   已发布
  |--mc-tags.php   模板标签定义
  |...

XSS

mc-admin/conf.php

漏洞代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php if (mc_is_post()) { ?>
    <div class="post">
      <h1 class="title"><?php mc_the_link(); ?></h1>
      <div class="tags"><?php mc_the_tags('','',''); ?> by <?php mc_nick_name(); ?> at <?php mc_the_date(); ?></div>
      <div class="content"><?php mc_the_content(); ?></div>
    </div>
    <?php if (mc_can_comment()) { ?> // 检验是否开启评论
    <?php mc_comment_code(); ?>
    <?php } ?>
...

可以看到这里对信息的输出都没有采取任何的转义处理,在mc_the_link()mc_comment_code()定义处也没有对身份信息进行转义处理,而mc_nick_name()却使用了htmlspecialchars处理,可能是作者只考虑了站长昵称的危险性

payload

1
2
IP"><script>alert('site_link')</script>
<img src=0 onerror=alert('comment_code')>

修复

源头处理,直接在conf.php使用htmlspecialchars处理comment_codesite_link

mc-admin/post-edit.php

漏洞代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
function mc_the_content($print = true) {
  global $mc_data;

  if (!isset($mc_data)) {
    global $mc_post_id;

    $data = unserialize(file_get_contents('mc-files/posts/data/'.$mc_post_id.'.dat')); 

    $html = Markdown($data['content']); 
  }
  else {
    $html = Markdown($mc_data['content']);
  }

  if ($print) {
    echo $html;
    return;
  }
  
  return $html;
}

上面模板输出没有处理,且mc_the_content函数也没有任何输出处理导致了content也存在XSS

payload

1
</p><script>alert('content')</script>

修复

1
2
3
4
5
6
...
if ($print) {
    echo htmlspecialchars($html);
    return;
}
...

mc-admin/post.php

分类显示的tag和data同样也是无处理直接输出。

payload

post.php?state=publish&tag="><script>alert('tag')</script>&date="><script>alert('date')</script>

修复

1
2
3
4
5
6
7
8
9
if (isset($_GET['tag']))
  $filter_tag = htmlspecialchars($_GET['tag']);
else
  $filter_tag = '';

if (isset($_GET['date']))
  $filter_date = htmlspecialchars($_GET['date']);
else
  $filter_date = '';

同理,page的也需要修改。

剩下的就咕了,审起来确实没劲。

信息泄露

mc-admin/post-edit.php

编辑文章的URL中id存在目录穿越,但是由于代码中进行了后缀拼接所以不会导致任意文件读取(在00截断还存在的php版本中可以成功任意文件读),但是错误信息会暴露项目的绝对路径。

post-edit.php?id=../../../../../../../etc/passwd

修复

1
error_reporting(0);

该cms全局都是默认显示错误信息,所以post.php、page.php啥的都要设置一下

mc-admin/post.php(伪)

这里路径遍历漏洞挺好奇的,这应该是中间件配置问题,所以应该不能算cms漏洞。那这个漏洞审核的时候是咋复现的?这应该是个人环境问题啊,迷惑ing

代码执行

mc-admin/install.php

mc-admin/conf.php

1
$code = "<?php\n\$mc_config = ".var_export($mc_config, true)."\n?>";

下个断点看一下code值

'<?php
$mc_config = array (
  \'version\' => \'1.10\',
  \'site_link\' => \'http://IP/mini/\',
  \'site_name\' => \'我的网站\',
  \'site_desc\' => \'又一个MiniCMS网站\',
  \'user_name\' => \'admin\',
  \'user_pass\' => \'123456\',
  \'user_nick\' => \'<script>alert(\\\'link\\\')</script>\',
  \'comment_code\' => \'&amp;amp;amp;lt;img src=0 onerror=alert(\\\'comment_code\\\')&amp;amp;amp;gt;\',
)
?>'

存在单引号闭合,所以可以在安装过程中提前插入单引号闭合执行代码

payload

hhh',);phpinfo();//

但是由于install.php在安装完会自我删除,所以这个利用不大,除非有个文件包含能包含根目录下的install.txt

参考

https://github.com/AvaterXXX/MiniCms/blob/master/Command%20Execution.md