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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-45806 — Функция импорта удаленных изображений в Penpot позволяет аутентифицированному редактору файлов превратить обычную медиа-функцию в SSRF с серверной стороны, поскольку управляемые атакующим URL попадали в путь загрузки сервера, который следует за перенаправлениями, без фильтрации назначения. | Kitploit
Инструменты/GitHubGitHub/0xmrma/cve-2026-45806
Анализ уязвимостейЭксплуатацияВеб-безопасностьТестирование на ПроникновениеСтатьи и ИсследованияОбучение и Образование
GitHub0xmrma/cve-2026-45806

CVE-2026-45806

Репозиторий
12 месяцев назадЕщё не проверено

Популярное

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

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

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

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

Смотреть все инструменты →

Описание

Функция импорта удаленных изображений в Penpot позволяет аутентифицированному редактору файлов превратить обычную медиа-функцию в SSRF с серверной стороны, поскольку управляемые атакующим URL попадали в путь загрузки сервера, который следует за перенаправлениями, без фильтрации назначения.

Поделиться

CVE-2026-45806

Импорт удаленных изображений в Penpot позволял аутентифицированному редактору файлов превратить обычную функцию работы с медиа в SSRF из бэкенда, поскольку управляемые атакующим URL попадали в путь выборки с сервера, который следовал перенаправлениям без фильтрации целевых адресов.

Введение

Я нашел эту проблему при анализе Penpot, платформы с открытым исходным кодом для совместного дизайна и кода, задавшись очень конкретным вопросом:

Что происходит, когда инструмент совместного дизайна позволяет одному пользователю передать бэкенду URL удаленного изображения для загрузки?

В данном случае этот вопрос привел к реальной ошибке.

Поток импорта удаленных изображений Penpot принимал управляемый пользователем URL и заставлял бэкенд загружать его из серверного сетевого контекста без применения ограничений на целевые адреса loopback или частных сетей. Общий HTTP-клиент также автоматически следовал перенаправлениям.

Это превратило обычную функцию работы с медиа в примитив аутентифицированного SSRF из бэкенда, что в итоге привело к CVE-2026-45806.

Penpot: Penpot на GitHub
CVE: CVE-2026-45806
CVSS: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N

Это затронуло Penpot. На своем официальном сайте и в медиа-ките Penpot позиционирует себя как платформа с пользовательской базой, превышающей 1 млн человек, и сообщает, что десятки тысяч организаций используют ее, включая Blender, Mozilla, Fedora, NTT Data, MIT, , , , и .

Société Générale
Cisco
Fujitsu
Indra
ByteDance
photo0

Цепочка атаки

аутентифицированный редактор файлов -> управляемый атакующим URL удаленного изображения -> create-file-media-object-from-url -> загрузка изображения бэкендом fetch с включенными перенаправлениями -> итоговый запрос попадает на внутреннюю конечную точку, возвращающую изображение -> SSRF из бэкенда / достижимость внутренних ресурсов


Что делает Penpot

Penpot — это платформа с открытым исходным кодом для совместного дизайна и кода.

Она обрабатывает такие вещи, как:

  • совместное редактирование файлов
  • рабочие процессы команд и проектов
  • загруженные медиа и ресурсы
  • пути рендеринга и предварительного просмотра
  • операции дизайна на основе браузера с обработкой на стороне сервера

Это означает, что ее путь импорта медиа находится на реальной границе доверия.

Важный вопрос здесь заключался не в том, поддерживает ли Penpot импорт удаленных изображений.

Настоящий вопрос был таким:

Ограничивает ли Penpot, куда бэкенду разрешено подключаться, когда пользователь импортирует удаленное изображение?

В данном случае — нет.


Почему эта ошибка заслуживала внимания

Многие недооценивают функции удаленного импорта.

Это ошибка.

Как только приложение:

  • принимает управляемый атакующим URL,
  • выполняет запрос с бэкенда,
  • и превращает этот запрос в обычный рабочий процесс продукта,

оно создает реальную границу доверия исходящих соединений.

В этом и была проблема.

Эта ошибка была не в рендеринге изображений. Не в хранении файлов. Не в обычных проверках разрешений на редактирование файла.

Это была классическая серверная ошибка доверия:

  • управляемый атакующим URL попал в систему,
  • бэкенд выполнил к нему запрос напрямую,
  • перенаправления были разрешены,
  • и в проверенном пути не было видимого контроля целевых адресов.

Этого достаточно, чтобы создать реальную уязвимость.


Граница, на которой я сосредоточился

Я не подходил к Penpot, слепо фаззя случайные RPC-методы или ища сбои в первую очередь.

Более сильным подходом было определить наиболее перспективную границу безопасности.

Для Penpot это был удаленный импорт медиа.

Почему?

Потому что эта функция сочетает:

  • ввод URL, контролируемый атакующим
  • исходящие запросы из бэкенда
  • проверку содержимого, которая происходит только после выполнения запроса
  • рабочий процесс дизайна, где успешные загрузки считаются обычными медиа-операциями

Это была правильная граница для проверки.

И именно здесь жила ошибка.


Коренная причина

Ошибка сводится к короткой цепочке доверия.

Во фронтенде:

root@kitploit:~
(defn upload-media-url
  [name file-id url]
  (rp/cmd!
   :create-file-media-object-from-url
   {:name name
    :file-id file-id
    :url url
    :is-local true}))

управляемый пользователем url напрямую передается в RPC-вызов.

Затем в бэкенде:

root@kitploit:~
(sv/defmethod ::create-file-media-object-from-url
  ...
  [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}]
  (files/check-edition-permissions! pool profile-id file-id)
  ...
  (let [_    (files/get-minimal-file cfg file-id)
        mobj (create-file-media-object-from-url cfg (assoc params :profile-id profile-id))])

и:

root@kitploit:~
(defn- create-file-media-object-from-url
  [cfg {:keys [url name] :as params}]
  (let [content (media/download-image cfg url)

бэкенд проверяет, что вызывающий может редактировать целевой файл, а затем передает управляемый атакующим URL в media/download-image.

Реализация выборки находится здесь:

root@kitploit:~
(defn download-image
  "Download an image from the provided URI and return the media input object"
  [{:keys [::http/client]} uri]
  ...
  (http/req! client
             {:method :get :uri uri}
             {:response-type :input-stream})

А общий HTTP-клиент настроен так:

root@kitploit:~
(http/build-client {:connect-timeout 30000
                    :follow-redirects :always}))

Вот и вся уязвимость:

  • атакующий управляет URL
  • бэкенд выполняет запрос
  • перенаправления выполняются автоматически
  • фильтрация целевых адресов перед запросом не применяется

Почему это эксплуатируемо

Потому что атакующему нужно только:

  • действующая учетная запись Penpot
  • разрешение на редактирование одного файла
  • цель, которая возвращает принятое содержимое изображения

Цепочка атаки проста:

  • атакующий предоставляет URL
  • Penpot загружает его с бэкенда
  • начальный переход может быть публичным или безобидным
  • цель перенаправления может быть внутренней
  • если итоговый ответ выглядит как разрешенное изображение, импорт завершается

Вот и вся ошибка.


Что делает это проблемой безопасности, а не просто обычным импортом удаленных изображений

Важное различие заключается в том, где выполняется запрос.

Вопрос не в том:

«Может ли Penpot импортировать изображения по URL?»

Реальный вопрос:

«Может ли аутентифицированный пользователь заставить бэкенд Penpot подключаться к внутренним адресам, к которым пользователь не должен иметь доступ через приложение?»

В данном случае ответ был «да».

Это важно, потому что есть реальная разница между:

  • браузером, загружающим предоставленный пользователем URL, и
  • бэкендом, загружающим этот URL из сетевого положения сервера

Валидация изображений не устраняет эту разницу.

Она сужает некоторые случаи прямой эксфильтрации, но не устраняет условие SSRF или нарушение сетевой границы.


PoC

Я подтвердил эту проблему с помощью контролируемого локального доказательства, напрямую связанного с проверенным кодом Penpot.

Целью было не воздействие на стороннюю инфраструктуру. Целью было доказать точное свойство безопасности:

  • выполнение запроса в стиле бэкенда
  • следование перенаправлениям
  • успешный переход на внутреннюю конечную точку
  • завершение при тех же ограничениях, связанных с изображениями, которые применяет Penpot

Я создал автономный валидатор на Java, который повторял соответствующее поведение:

  • GET-запрос со стороны бэкенда к URI, контролируемому вызывающим
  • автоматическое следование перенаправлениям
  • проверки на принятие изображения на основе content-type и content-length

Я проверил два случая.

Случай 1: прямой внутренний запрос

Валидатор запросил:

root@kitploit:~
http://127.0.0.1:7790/internal.png

Наблюдаемый результат:

  • запрошенный URI: http://127.0.0.1:7790/internal.png
  • итоговый URI: http://127.0.0.1:7790/internal.png
  • статус: 200
  • тип содержимого: image/png
  • артефакт успешно записан

Это доказало, что логика выборки в стиле импорта напрямую приняла внутреннюю конечную точку, возвращающую изображение.


Случай 2: внутренний запрос через перенаправление

Затем валидатор запросил:

root@kitploit:~
http://localhost:7791/redirect-to-internal

Эта конечная точка вернула HTTP-перенаправление на:

root@kitploit:~
http://127.0.0.1:7790/internal.png

Наблюдаемый результат:

  • запрошенный URI: http://localhost:7791/redirect-to-internal
  • итоговый URI: http://127.0.0.1:7790/internal.png
  • статус: 200
  • тип содержимого: image/png
  • артефакт успешно записан

Внутренний слушатель зафиксировал перенаправленный запрос.

Это доказало более важное утверждение:

  • начальный управляемый атакующим URL может отличаться от конечного пункта назначения
  • перенаправления выполняются автоматически
  • итоговая выборка бэкенда может попасть на внутреннюю конечную точку и все равно успешно завершиться

Почему PoC был построен таким образом

Полезная нагрузка здесь была намеренно простой:

  • крошечный ответ с валидным PNG
  • явная цель перенаправления
  • внутренний слушатель, привязанный к loopback

Это важно, потому что Penpot не просто загружает произвольные байты и останавливается. Он выполняет проверку, ориентированную на медиа, после запроса.

Поэтому правильным доказательством было не:

«бэкенд может попытаться куда-то подключиться»

Более сильным доказательством было:

«бэкенд можно заставить подключиться куда-то внутри и успешно завершить запрос при тех же ограничениях, связанных с изображениями, которые ожидает функция»

Именно это и продемонстрировала валидация.


Почему об этом всё равно стоило сообщить

Распространенная реакция на подобные ошибки SSRF:

«цель всё равно должна вернуть изображение»

Это наблюдение верно, но неполно.

Оно не устраняет уязвимость.

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

Эта проблема все еще позволяет:

  • достижимость внутренних ресурсов из бэкенда
  • переход через перенаправления в пространство loopback или частных сетей
  • взаимодействие с внутренними конечными точками, возвращающими изображения
  • злоупотребление сетевым доверием из положения сервера Penpot

Это все еще реальное нарушение границы безопасности.

Особенно в саморазмещенных средах внутренние сервисы часто существуют именно за этой границей.


Серьёзность и классификация

В итоге этой проблеме был присвоен высокий уровень серьезности CVSS:

  • CWE-918: Server-Side Request Forgery (SSRF)
  • CVSS:
root@kitploit:~
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N

Эта классификация имеет смысл.

Утверждение не в том, что неаутентифицированный атакующий может мгновенно скомпрометировать каждое развертывание Penpot с нуля.

Утверждение в том, что любой обычный аутентифицированный редактор файлов может превратить Penpot в примитив бэкенд-запроса к внутренним адресам, включая доступ через перенаправления к loopback и целям в частных сетях.

Во время раскрытия были некоторые обсуждения серьезности, в основном вокруг:

  • внутренних сервисов, требующих аутентификации
  • необходимости, чтобы загруженное содержимое прошло валидацию изображений
  • зависимости эксплуатации от знания внутренней инфраструктуры

Это разумные ограничения для обсуждения.

Но они не устраняют основную проблему:

  • управляемый атакующим URL
  • источник запроса со стороны бэкенда
  • следование перенаправлениям
  • отсутствие политики исходящих адресов в проверенном пути

Это реальная и обоснованная уязвимость SSRF.


Анализ исправления

Важное исправление здесь — не более строгая обработка MIME.

Настоящее исправление — политика исходящих адресов.

Корректное устранение для этого класса ошибок должно:

  1. разрешать только http и https
  2. разрешать и отклонять диапазоны loopback, RFC1918/частные, link-local, multicast, unspecified и метаданных сервиса до подключения
  3. повторно проверять каждый шаг перенаправления по той же политике
  4. рассмотреть возможность отключения перенаправлений для этой функции или жестко их ограничить
  5. добавить регрессионное покрытие для:
    • localhost
    • прямых частных целей
    • случаев перенаправления на частные адреса
    • сценариев типа DNS rebinding

Это правильное направление исправления, потому что это была не ошибка парсинга изображений. Это была ошибка на границе доверия сети.


Раскрытие

Эта проблема была сообщена конфиденциально через поток сообщений о безопасности GitHub.

Отчет включал:

  • анализ коренной причины на уровне исходного кода
  • надежную модель локальной валидации
  • доказательство перехода на внутренние адреса через перенаправление
  • доказательства артефактов и логов
  • рекомендации по устранению

Мейнтейнеры подтвердили проблему и начали работу над исправлением.

Позже проблеме был присвоен:

CVE-2026-45806


Чему на самом деле учит эта ошибка

Ключевой урок здесь прост:

удаленный импорт медиа — это граница доверия исходящих соединений, а не просто функция удобства

Многие разработчики мыслят в терминах:

  • URL принят
  • запрос выполнен успешно
  • изображение прошло валидацию
  • медиа сохранено

Это детали реализации.

Настоящий вопрос безопасности:

куда бэкенду разрешено подключаться от имени пользователя?

Если на этот вопрос нет явного ответа, такие функции, как удаленный импорт, по умолчанию становятся поверхностями SSRF.

Эта ошибка также подтверждает нечто важное в отношении анализа SSRF:

  • перенаправления имеют значение
  • проверка содержимого не заменяет сетевую политику
  • аутентифицированный SSRF по-прежнему серьезен, когда он пересекает внутренние границы доверия

Вот настоящий вывод.


Ключевые моменты

  • удаленный импорт изображений — это реальная граница доверия бэкенда
  • аутентифицированные функции все еще могут раскрывать серьезные SSRF
  • следование перенаправлениям делает исходящие пути выборки гораздо более опасными
  • проверка только изображений сужает некоторые пути злоупотребления, но не устраняет SSRF
  • доказательство успешного внутреннего пути через перенаправление сильнее, чем просто показ неудачной попытки подключения
  • правильное исправление — политика исходящих адресов, а не косметическая проверка ответов

Заключение

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

Она была о том, чтобы задать правильный вопрос о границе доверия.

Penpot позволил аутентифицированному редактору файлов предоставить URL удаленного изображения, и бэкенд доверял этому URL больше, чем следовало. Обработка перенаправлений сделала остальное.

Вот почему это стало CVE-2026-45806.

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