deituicms 1.0 任意文件上传
前言
最近开始实习,要开始早睡早起,改善作息了~
实习主要是负责漏洞复现方面的工作,这样也蛮好,可以沉下心去审计是件很开心的事情 : )
环境搭建
在 cnvd 上看到这个 cms 的一个文件上传漏洞,白天的时候审了一下,这里总结下漏洞发生的原因。
迁出该 cms 的 v1.0 分支。
1 | git clone git@github.com:lrjxgl/deituiCMs.git |
代码审计
还是从 index.php 开始,跟一遍代码逻辑。
index.php
1 | // line 45 |
跟进 /skymvc/skymvc.php,其中对 gpc 中的数据做了 addslashes 处理。
主要关注 /skymvc/skymvc.php 中的路由逻辑。
在 /source/index/ 目录下主要是前台相关逻辑的代码,在 /source/admin/ 目录下是后台相关逻辑的代码。这里我们可以调用 /source/index/ 中某 xxControl 类中的 onxx 方法。
在 /source/index/ 目录下发现和上传相关的类文件为 upload.ctrl.php,类名为 uploadControl,其中有很多和上传相关的方法。大部分方法中都调用了 uploadfile 函数去处理上传相关的行为,随便拿一个 onUpload 方法来看。
跟进 upload 类的 uploadfile 方法。
先通过 umkdir 函数创建目录,接着取出文件后缀名存入 f_type 变量,之后就没有对 f_type 变量进行检查,直接拼接到最后的文件名 uploadfile 变量中,并调用 move_file 方法上传文件。
可以看到,实际上,中间有一段对文件类型进行验证的代码,跟进 getTrueType 方法。
其中可以看到验证文件类型的方式,而该方式可以被绕过。当我们在一张正常的图片后面加上<?php phpinfo();?>
时,在该检测中仍然会被认为是一张图片。
在 getTrueType 方法中调用了 getfiletype 方法取出文件类型的简短名字。
取出文件类型名后,回到 uploadfile 方法的检测逻辑中。
1 | $fileType=$this->getTrueType($FILE['tmp_name']); |
sysallowtype 和 allowtype 属性的值定义在 upload 类的开头。
1 | public $allowtype=array("gif","jpg","bmp","png",'jpeg'); |
总结一下就是,我们可以控制上传文件的后缀名,因为 uploadfile 方法并没有对该值进行检测和过滤。只是对文件类型进行白名单检测,而在图片后面添加 php 代码仍然可以通过白名单检测。
漏洞复现
先写个上传文件表单。
上传一张正常图片,抓包后在图片内容后面添加恶意代码。
在 Response 中可以取到上传文件路径。
该文件在 /attach/ 目录下,具体路径和日期有关。
漏洞补丁
在最新的 v1.2 中,可以看到在 /skymvc/library/cls_upload.php 文件的 upload 类的 uploadfile 方法中,添加了对文件后缀 f_type 变量的过滤。
尽管如此,但是文件类型还是 getTrueType 方法进行检测,所以我们还是可以上传一个结尾添加了恶意代码的图片,只不过后缀是白名单中的合法后缀。不过,如果我们找到一个文件包含的利用点,该上传文件仍然存在被用于 getshell 的风险。
Author: ll
Link: http://yoursite.com/2019/07/16/deituicms_v1.0_文件上传/
License: 知识共享署名-非商业性使用 4.0 国际许可协议