0x00 环境准备

XYHCMS官网:http://www.xyhcms.com/

网站源码版本:XYHCMS V3.5(2017-12-04 更新)

程序源码下载:http://www.xyhcms.com/Show/download/id/2/at/0.html

测试网站首页:

 

【代码审计】XYHCMS V3.5文件上传漏洞分析_上传

0x01 代码分析

1、漏洞文件位置:/App/Common/Lib/YunUpload.class.php   第231-271行:

1. public function _upload() {  
2.     $ext = ''; //原文件后缀  
3.     foreach ($_FILES as $key => $v) {  
4.         $strtemp = explode('.', $v['name']);  
5.         $ext     = end($strtemp); //获取文件后缀,或$ext = end(explode('.', $_FILES['fileupload']['name']));  
6.         break;  
7.     }  
8.     $upload = new \Think\Upload(); //new Upload($config)  
9.     //修配置项  
10. 10.     $upload->autoSub  = true; //是否使用子目录保存图片  
11. 11.     $upload->subType  = 'date'; //子目录保存规则  
12. 12.     $upload->subName  = array('date', 'Ymd');  
13. 13.     $upload->maxSize  = get_upload_maxsize(); //设置上传文件大小  
14. 14.     $upload->exts     = $this->allowType; //设置上传文件类型  
15. 15.     $upload->rootPath = $this->rootPath; //上传根路径  
16. 16.     $upload->savePath = $this->subDirectory; //上传(子)目录  
17. 17.     $upload->saveName = array('uniqid', ''); //上传文件命名规则  
18. 18.     $upload->replace  = true; //存在同名是否覆盖  
19. 19.     $upload->callback = false; //检测文件是否存在回调函数,如果存在返回文件信息数组  
20. 20.       if ($info = $upload->upload()) {  
21. 21.   
22. 22.         //判断是添加水印--有缩略的才添加水印  
23. 23.         if ($this->thumFlag) {  
24. 24.             $this->_doWater($info);  
25. 25.         }  
26. 26.           //是否有缩略图  
27. 27.         if ($this->thumFlag) {  
28. 28.             $this->_doThum($info);  
29. 29.         }  
30. 30.         return $info;  
31. 31.       } else {  
32. 32.           //$str = array('err' =>1 ,'msg' => $upload->getError() );  
33. 33.         return $upload->getError();  
34. 34.     }  
35. 35.   }


这段图片上传函数中对上传参数进行设置,然后上传。文件上传类型是客户端参数可控的,导致攻击者可以修改文件上传类型,上传恶意脚本,上传完还得去保存,继续去看一下程序如何处理保存:

文件位置:/App/Manage/Controller/SystemController.class.php,第194-217行中:

1. public function site() {  
2.     if (IS_POST) {  
3.   
4.         $data = I('config', array(), 'trim');  
5.         foreach ($data as $key => $val) {  
6.             if (stripos($val, '<?php') !== false) {  
7.                 $data[$key] = preg_replace('/<\?php(.+?)\?>/i', '', $val);  
8.             }  
9.   
10. 10.         }  
11. 11.   
12. 12.         $data['CFG_IMGTHUMB_SIZE'] = strtoupper($data['CFG_IMGTHUMB_SIZE']);  
13. 13.         $data['CFG_IMGTHUMB_SIZE'] = str_replace(array(',', 'X'), array(',', 'X'), $data['CFG_IMGTHUMB_SIZE']);  
14. 14.         if (empty($data['CFG_IMGTHUMB_SIZE'])) {  
15. 15.             $this->error('缩略图组尺寸不能为空');  
16. 16.         }  
17. 17.   
18. 18.         if (!empty($data['CFG_IMAGE_WATER_FILE'])) {  
19. 19.             $img_ext = pathinfo($data['CFG_IMAGE_WATER_FILE'], PATHINFO_EXTENSION);  
20. 20.             $img_ext = strtolower($img_ext);  
21. 21.             if (!in_array($img_ext, array('jpg', 'gif', 'png', 'jpeg'))) {  
22. 22.                 $this->error('水印图片文件不是图片格式!请重新上传!');  
23. 23.                 return;  
24. 24.             }  
25. 25.           }



这段函数在全局配置存储过程中进行检测,注意看红色代码部分,检测图片文件格式是否是'jpg', 'gif', 'png', 'jpeg',否则提示重新上传,但是仅仅只是提示,并没有删除文件,也就是我们如果上传脚本文件,已经成功保存在服务器上面。

程序在实现上对文件上传过程处理不当,导致可以被绕过,通过该漏洞上传脚本木马,获取服务器控制权限。

0x02 漏洞利用

1、登录后台,在系统设置—网站设置—上传配置,修改文件上传类型,然后上传文件:

 

【代码审计】XYHCMS V3.5文件上传漏洞分析_服务器_02

2、点击保存时,发现程序提示不是图片格式,请重新上传

 

【代码审计】XYHCMS V3.5文件上传漏洞分析_php_03

3、继续去访问刚才成功上传的脚本,发现脚本文件依然在服务器上,并没有被删除。

 

【代码审计】XYHCMS V3.5文件上传漏洞分析_服务器_04

4、通过菜刀链接,控制网站服务器

 

【代码审计】XYHCMS V3.5文件上传漏洞分析_php_05

0x03 修复建议

1、重新梳理文件上传过程,通过白名单限制上传文件后缀;

2、禁止上传目录脚本执行权限。

 

最后

欢迎关注个人微信公众号:Bypass--,每周原创一篇技术干货。 

【代码审计】XYHCMS V3.5文件上传漏洞分析_上传_06