代码审计 MiniCMS从头开始

代码审计 MiniCMS从头开始

写在之前

最近从头开始学习代码审计,准备从开发的眼光入手,至少要熟悉整个框架的执行流程。MiniCMS体积小,代码短小易读,所以首先详细分析其执行流程。通过学习可以大致熟悉MVC框架的构造,对Web server的后台处理有一个基本了解。

简介

MiniCMS是由达达设计编写的一个针对个人网站设计的微型内容管理系统。它的特点是:

  1. 不需要数据库在支持,只需要一个可以运行PHP的Web环境
  2. 只针对个人网站设计,没有复杂的成员管理和权限设置
  3. 没有分类只有标签,免除发布文章时到底该怎么分类的纠结
  4. 只有“文章”和“页面”两该个系统,没有“评论”、“插件”、“主题”,让你更专注于创造内容

项目地址:https://github.com/bg5sbk/MiniCMS

安装

  • 解压
  • 复制并重命名install.txt为install.php
  • 在PHP环境下,浏览器打开install.php,填写网站路径、网站名等信息,点击安装即可(此处填写网站信息等可以注入命令造成RCE,但是由于install.php在安装完成后会自动删除,漏洞不可利用,所以并没有太大的威胁)

安装完成后的目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
│ build.php
│ index.php 整个项目的入口,首先引入核心库mc-core.php,然后进行路由,对路由结果进行相应的渲染,相当于MVC中的C
│ install.txt 复制为php文件后,用来安装MiniCMS
│ README.md
├─mc-admin 管理功能的实现
│ conf.php 用户设置页面,包括接收和保存更改的设置
│ editor.php 编辑器的大小、样式调整的库
│ foot.php html<foot>标签构造
│ head.php token验证,html<head>标签构造;若验证失败,跳转至主页
│ index.php 后台登陆身份验证页面
│ page-edit.php 页面编写处理逻辑,包括显示编辑页面、接收提交的页面、页面序列化储存
│ page.php 管理页面的库,声明加载数据、删除页面、还原页面(从回收站还原)
│ post-edit.php 文章编写处理逻辑,包括显示编辑页面、接收提交的页面、页面序列化储存
│ post.php 管理文章的库,声明加载数据、删除文章、还原文章(从回收站还原)
│ style.css 后台用到的CSS
└─mc-files
│ markdown.php 一个开源的markdown解析库
│ mc-conf.php 配置文件,包含用户名和密码等敏感信息
│ mc-core.php 引入mc-tags、mc-conf,声明404函数
│ mc-rss.php 订阅RSS的链接
│ mc-tags.php 相当于M,引入markdown、包括一些核心函数,包括了加载各种信息的函数(网站名、文章数、前进后退等,中间有各种过滤,可以重点分析)
├─pages
│ └─index
│ delete.php 使用数组储存了删除页面的信息(id、标题、标签等)与data文件夹内的文章数据一一对应
│ draft.php 使用数组储存了草稿页面的信息(id、标题、标签等)与data文件夹内的文章数据一一对应
│ publish.php 使用数组储存了已发布的页面的信息(id、标题、标签等)与data文件夹内的文章数据一一对应
├─posts
│ ├─data 储存了文章内容的反序列化数据(文章内容等)
│ └─index
│ delete.php 使用数组储存了删除的文章的信息(id、标题、标签等)与data文件夹内的文章数据一一对应
│ draft.php 使用数组储存了草稿文章的信息(id、标题、标签等)与data文件夹内的文章数据一一对应
│ publish.php 使用数组储存了已发布文章的信息(id、标题、标签等)与data文件夹内的文章数据一一对应
└─theme
index.php 主题文件,决定了页面的风格,将C传入的信息显示出来,相当于V
style.css 主题使用的CSS风格

访客端

路由与控制器(MVC-C)

  • MiniCMS在index.php页面进行简单的正则匹配和字符串对比路由,index.php会取出$_SERVER['QUERY_STRING']并进行正则匹配;主要有以下几种路由:
    1
    2
    3
    4
    5
    6
    7
    1. preg_match('|^post/([a-z0-5]{6})$|', $qs, $matches) // 路由至查看文章功能
    2. preg_match('|^tag/([^/]+)/(\?page=([0-9]+)){0,1}$|', $qs, $matches) // 路由至查看页面功能
    3. preg_match('|^date/([0-9]{4}-[0-9]{2})/(\?page=([0-9]+)){0,1}$|', $qs, $matches) // 路由至按日期查看文章
    4. preg_match('|^archive/$|', $qs, $matches) // 路由至按archive查看文章
    5. $qs == 'rss/' // 路由至返回RSS订阅
    6. preg_match('|^(([-a-zA-Z0-5]+/)+)$|', $qs, $matches) // 路由至page查看文章
    7. default:index // 其他情况,路由至主页

视图(MVC-V)

  • mc_files/theme/index.php文件中,通过
    1
    <div class="content"><?php mc_the_content(); ?></div>

直接渲染路由到的内容。

  • 通过mc-files/theme/style.css修改主页的CSS风格。

模型(MVC-M)

  • 模型M相关的功能主要在 mc-files/mc-tags.php中实现。 主要函数有:
  1. mc_site_name 获取网站名
  2. mc_site_desc 获取网站标题后缀
  3. mc_site_link 获取网站链接
  4. mc_nick_name 获取昵称
  5. mc_theme_url 获取主题文件路径
  6. mc_is_post 返回路由是否是post
  7. mc_is_page 返回路由是否是page
  8. mc_is_tag 返回路由是否是tag
  9. mc_is_date 返回路由是否是date
  10. mc_is_archive 返回路由是否是archive
  11. mc_tag_name 获取标签名
  12. mc_date_name 获取日期
  13. mc_has_new 获取是否有更新的页面(页面底部的页数)
  14. mc_has_old 获取是否有更早的页面(页面底部的页数)
  15. mc_goto_old 打印输出更早页面的超链接
  16. mc_goto_new 打印输出更晚页面的超链接
  17. mc_date_list 打印输出日期列表
  18. mc_tag_list 打印输出标签列表
  19. mc_next_post 判断是否有下一个post
  20. mc_the_title 打印输出标题
  21. mc_the_date 打印输出日期
  22. mc_the_time 打印输出时间
  23. mc_the_tags 打印输出标签
  24. mc_the_content 打印输出主要内容(文章、页面)
  25. mc_the_link 打印输出超链接和其标题
  26. mc_the_url 打印输出url的超链接
  27. mc_can_comment 返回是否能够评论
  28. mc_comment_code 获取填入的第三方评论代码

后台管理端

后台管理端直接用代码按功能写入文件,各文件的功能如下:

  • conf.php 用户设置页面,包括接收和保存更改的设置
  • editor.php 编辑器的大小、样式调整的库
  • foot.php html标签构造
  • head.php token验证,html 标签构造;若验证失败,跳转至主页
  • index.php 后台登陆身份验证页面
  • page-edit.php 页面编写处理逻辑,包括显示编辑页面、接收提交的页面、页面序列化储存
  • page.php 管理页面的库,声明加载数据、删除页面、还原页面(从回收站还原)
  • post-edit.php 文章编写处理逻辑,包括显示编辑页面、接收提交的页面、页面序列化储存
  • post.php 管理文章的库,声明加载数据、删除文章、还原文章(从回收站还原)
  • style.css 后台用到的CSS

CVE漏洞

在MiniCMS公开期间,爆出了多个CVE漏洞,并且至今未修复,主要如下(按时间先后顺序排列):

  • CVE-2018-1000638 反射型XSS 存在位置:/MiniCMS-master/mc-admin/page.php处date参数存在XSS漏洞
  • CVE-2018-10227 储存型XSS 存在位置:/MiniCMS-master/MiniCMS-master/mc-admin/conf.php 在设置中修改网站地址处存在XSS漏洞,可直接储存XSS payload
  • CVE-2018-10296 储存型XSS 存在位置: /MiniCMS-master/mc-admin/post-edit.php 编辑文章标题处可直接储存XSS payload
  • CVE-2018-10423 个人认为不是漏洞,只是个BUG,此处的BUG只是网页中的超链接错误地指向了网站根目录,点击后就会去访问网站根目录,这个时候,洞主的apache配置没有关文件遍历,就误认为是CMS的漏洞,显然是不对的,洞主应该是刷分的,没想到竟然过了:)
  • CVE-2018-10424 物理路径泄露 存在位置:/MiniCMS-master/mc-admin/post-edit.php处将GET的参数id改为不存在的文件名,会爆出物理地址
  • CVE-2018-15899 反射型XSS 存在位置:/minicms/mc-admin/page.php的GET参数date存在XSS(似乎与CVE-2018-1000638重复了。。)
  • CVE-2018-16233 反射型XSS 存在位置:/MiniCMS-1.10/mc-admin/post-edit.php处的POST参数tags存在XSS
  • CVE-2018-16298 反射型XSS 存在位置:/MiniCMS-1.10/mc-admin/post.php的GET参数tag存在XSS
  • CVE-2018-17039 反射型XSS 存在位置:/mc-admin/index.php使用任意GET参数并取XSS payload,可在IE浏览器中执行JS
  • CVE-2018-18890 物理路径泄露 存在位置:post.php?delete=qe54cn&state=delete删除不存在的文章时爆出物理路径
  • CVE-2018-18891 部分文件删除(逻辑漏洞,删除操作在身份认证之前进行) 存在位置:/mc-admin/post.php?delete=qe54cn&state=delete不用登陆可直接删除文章
  • CVE-2018-18892 鸡肋的RCE 存在位置: install.php在安装时在配置处可以向配置文件直接注入PHP代码;由于在MiniCMS安装完毕后此文件会自我删除,在实际情况下并没有太大的作用
  • CVE-2018-20520 反射型XSS 存在位置:类似于CVE-2018-17039,/MiniCMS1/mc-admin/post-edit.php使用任意GET参数并取XSS payload,可在IE浏览器中执行JS
  • CVE-2018-9092 CSRF 存在位置: http://127.0.0.1//MiniCMS/mc-admin/post.php?delete=aaaaaa&state=publish&date=&tag= 此处的CSRF会导致任意文章删除:
  • CVE-2019-9603 CSRF 存在位置:/minicms/mc-admin/conf.php 此处的CSRF会导致任意修改网站配置