0x01 前言
在一次授权测试中对某网站进行测试时,marry大佬发现了一个网站的备份文件,里面有网站源代码和数据库备份等。根据网站信息和代码都可以发现该系统采用的是微擎cms,利用数据库备份中的用户信息解密后可以登录系统,接下来要看是否可以获取webshell。0x02 WEBSHELL获取的尝试
有了数据库备份文件,然后找一下是否有用户的信息,能否登录系统。1.登录后台
解压备份文件可以从data/backup
目录下找到数据库的备份,从中找到了用户表
ims_users
。
![646b4d2814df96c79063474441b31436.png](https://i-blog.csdnimg.cn/blog_migrate/4593da9ac4429ae1f5e3cff1ad88aaac.png)
password
,在forget.ctrl.php中找到了一处。
![a0e2ac0975b8f6370e5a14730be74c7c.png](https://i-blog.csdnimg.cn/blog_migrate/b0b3898034e447b15637d6a452029675.png)
$password = md5($password . $member_info['salt'] . $_W['config']['setting']['authkey']);
。是根据
原密码+salt+authkey
的形式进行拼接,然后进行md5加密。
authkey在
data/config.php
文件中。
![31c2f0295a88d1bc95f8847f2da56a81.png](https://i-blog.csdnimg.cn/blog_migrate/222c396fc86fae972f14b7c5e6fc9b20.png)
salt
和
authkey
拼接为新的
salt
,然后使用
md5($pass.$salt)
的加密方式进行解密。
![cd800e37a1bf3ca4c182d43e1937fb2e.png](https://i-blog.csdnimg.cn/blog_migrate/ba597ade4cc839825fb16f0dcfad6f15.png)
![0811bb6422b63c4099c56e9fce51efa1.png](https://i-blog.csdnimg.cn/blog_migrate/6dfad3300f1ee874cb554c12d0b88614.png)
2.失败的获取shell过程
根据搜索发现,该cms后台获取shell的方法也不少,主要还是围绕执行sql这里。但我这里都失败了,就简单的提一下。 第一种方法: 站点管理-附件设置-图片附件设置-支持文件后缀,任意添加一个类型,例如添加pppppp
。
然后执行sql语句
|
"*.php "
文件了。但是有限制,适用于apache下,而且版本有限制。目标站不使用该方法的原因有二,一是该系统上传的位置是腾讯云COS上,二是server是Tengine。
第二种方法:
第二种方法也是和sql执行有关,利用日志文件写shell。
|
0x03 代码审计
病急乱投医,熬成老中医。既然之前的方法不管用,只好去翻代码吧,找找是否有新的利用方式。翻出之前的一个文档,从里面找到之前的审计过程,看能否对现在有用。结果打开发现只有一个数据包和还有一句未实现的结论。![eb753242e712b10101f631863169fff4.png](https://i-blog.csdnimg.cn/blog_migrate/4d0e77bb72b3aecbe8cdcd7c415033bd.png)
1.分析
打开文件web/source/cloud/dock.ctrl.php
,找到执行的
download
方法。
![d31522b15745bf99945e23d840071bfa.png](https://i-blog.csdnimg.cn/blog_migrate/b0ec4b5a625f89ead52d158ce5e9a57b.png)
$data
就是请求包的内容。然后对
$data
进行发序列化返回
$ret
,接下来获取
$ret['file']
并Base64解密返回
$file
。当存在
gzcompress
和
gzuncompress
这两个函数时,就会利用
gzuncompress
函数对
$file
进行解压操作。
将获取的
$file
进行md5加密后,与
$ret['path']
以及获取的
$_W['setting']['site']['token']
进行拼接为
$string
。当满足
$_W['setting']['site']['token']
非空并且
$string
md5加密后的结果与
$ret['sign']
一致时,才可以进行下面的操作。下面就是文件的写入了,根据
$ret['path']
进行判断,然后写入的位置不一样。
这里关键的一点就是
$_W['setting']['site']['token']
这个值的获取。这个是利用authcode函数对
cache_load(cache_system_key('cloud_transtoken'))
进行解密获取的。
authcode
函数位于
framework/function/global.func.php
文件中。
![ab9ba8e2252b81b92538fa628cad02a9.png](https://i-blog.csdnimg.cn/blog_migrate/ec204c8b88680999fa033f647034ff58.png)
authcode
加解密,需要知道
$GLOBALS['_W']['config']['setting']['authkey']
,在上面提到过,authkey在
data/config.php
文件中。
那么如果想任意写文件,就需要知道
cache_system_key('cloud_transtoken')
的内容了。
2.cloud_transtoken的获取
通过搜索发现,这个值是在文件framework/model/cloud.mod.php
中的
cloud_build_transtoken
函数中被写入的,通过进入
cache_write
方法,发现会写入数据库中。
![d37a6079e2c515356f21d7fa22ad2c60.png](https://i-blog.csdnimg.cn/blog_migrate/bf6aa0499a981bbb9beab58d8797f26a.png)
cloud_transtoken
。结果并没有找到,可能原因是没有写入
cloud_transtoken
的时候就进行了数据库备份。
我们往上回溯,看哪里调用了
cloud_build_transtoken
。
发现了其中的一条利用链:
![17e57a76b47aafbfc3330a76a5d8904d.png](https://i-blog.csdnimg.cn/blog_migrate/5946792c5fb0dd158b0ac233c7740ab8.png)
cloud_site_info()
函数获取站点信息。函数
cloud_site_info()
调用了
cloud_api('site/info')
,这里的method为
site/info
,所以继续调用
cloud_build_transtoken
从会而将
cloud_transtoken
的内容写入数据库。然后通过数据库备份的功能,就可以看到数据库中保存的
cloud_transtoken
,进而可以利用之前的分析写shell。
3.自定义数据库备份
由于数据库备份需要关闭站点,为了不影响目标站点的使用,这里我们搭建一个环境演示一下过程(需要注册站点)。 登录成功后更新缓存,然后访问 http://ip:port/web/index.php?c=cloud&a=profile ,关闭站点后进行数据库备份。![2b545311a0607fa87d68e280b8075c68.png](https://i-blog.csdnimg.cn/blog_migrate/f35c10cfd0c9b8ef46422a13796c5b76.png)
cloud_transtoken
,但是数据库目录和文件的名字是随机的。
![05039a53a5c769f0c0a9c1654c486896.png](https://i-blog.csdnimg.cn/blog_migrate/66daebeb32ae6120415a8cb9b336cc52.png)
cloud_transtoken
也无法利用,我们需要最新的备份文件。
然后我们看一下数据库备份是怎么实现的,打开
web/source/system/database.ctrl.php
。
![81e51b06839da5844ede109d3f586cc5.png](https://i-blog.csdnimg.cn/blog_migrate/7ba749d2bcca6e28ef7f381befa35fb3.png)
volume-10位随机字符串-1.sql
的形式,既然可以自定义,那么就简单多了。
访问链接
http://ip:port/web/index.php?c=system&a=database&do=backup&status=1&start=2&folder_suffix=123&volume_suffix=456
进行数据库备份,则数据库备份文件的地址为:
http://ip:port/data/backup/123/volume-456-1.sql
![cab975b452fa1fdd34bcf128af5863df.png](https://i-blog.csdnimg.cn/blog_migrate/b14c1a6b4a096782aa2d3029d7baf86c.png)
cloud_transtoken
了。接下来就可以进行shell的获取了。
4.获取WEBSHELL
根据上面的分析,cloud_transtoken
、
authkey
已经知道了,接下来就是构造payload了。
![e28e75bcc59a80020cfb726e802d8d52.png](https://i-blog.csdnimg.cn/blog_migrate/1a66d478e207d913ae895c7b474b11a6.png)
![d53a2df34fea9288c4492245dd75c231.png](https://i-blog.csdnimg.cn/blog_migrate/b73f2cef18e093e5f3ea39ebb64e94a5.png)
![c8404e55921a030b445172c5a3a71f7f.png](https://i-blog.csdnimg.cn/blog_migrate/1c87f199f03b4419a86a8e180d087acd.png)
5.延伸
上面是因为有系统文件备份,然后获取/data/config.php
中的
authkey
。如果没有文件备份,登录了一个管理员权限的用户,能否获取shell呢。答案也是可以的。
该系统有一个木马查杀功能,可以根据这个功能读取文件内容。
![eb92142de8dc07d3ecea75ddd1311a25.png](https://i-blog.csdnimg.cn/blog_migrate/7258c944cda8739189fbc00dfc3f67fa.png)
data/.
,特征函数为
password
。然后就可以看到查杀结果,获取
authkey
的值。
![f0d8b16622e6877d51a6ff27a98d9612.png](https://i-blog.csdnimg.cn/blog_migrate/c4701465f7633498386e2f7643ae82a2.png)
![052499bac55c3b5c612e7e4f9c92021d.png](https://i-blog.csdnimg.cn/blog_migrate/8668c1e56bb59fc7bc705a5c98c7697b.png)
0x04 总结
根据上面对分析过程,该漏洞的利用过程如下: 1.成功登录后台,且拥有管理员权限。 2.更新缓存(非必须),访问链接 http://ip:port/web/index.php?c=cloud&a=profile 写入cloud_transtoken
到数据库中。
3.关闭站点并进行使用自定义的目录进行数据库备份,链接地址:
http://ip:port/web/index.php?c=system&a=database&do=backup&status=1&start=2&folder_suffix=123&volume_suffix=456
。然后下载数据库备份,地址为:
http://ip:port/data/backup/123/volume-456-1.sql
(多个分卷的话文件名为volume-456-2.sql、volume-456-3.sql… ),然后找到
cloud_transtoken
。
4.生成payload,请求
http://ip:port/web/index.php?c=cloud&a=dock&do=download
,写入shell。
总的来说,利用上述方法获取shell需要满足两个条件,第一是拥有一个管理员权限的用户,第二就是该站点注册了云服务。
作者: 浮萍,文章来源:浮萍's Blog
扫描关注乌云安全
觉得不错点个“赞”、“在看”哦